]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
threading and more SSE2 optimizations for dpsoftrast
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
120
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
132
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
156
157 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181
182 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
183
184 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
185
186 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
187
188 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
189 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
190 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
191 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
192 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
193 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
194 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
195 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
196 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
197
198 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
199 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
200
201 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
202
203 extern cvar_t v_glslgamma;
204
205 extern qboolean v_flipped_state;
206
207 static struct r_bloomstate_s
208 {
209         qboolean enabled;
210         qboolean hdr;
211
212         int bloomwidth, bloomheight;
213
214         int screentexturewidth, screentextureheight;
215         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
216
217         int bloomtexturewidth, bloomtextureheight;
218         rtexture_t *texture_bloom;
219
220         // arrays for rendering the screen passes
221         float screentexcoord2f[8];
222         float bloomtexcoord2f[8];
223         float offsettexcoord2f[8];
224
225         r_viewport_t viewport;
226 }
227 r_bloomstate;
228
229 r_waterstate_t r_waterstate;
230
231 /// shadow volume bsp struct with automatically growing nodes buffer
232 svbsp_t r_svbsp;
233
234 rtexture_t *r_texture_blanknormalmap;
235 rtexture_t *r_texture_white;
236 rtexture_t *r_texture_grey128;
237 rtexture_t *r_texture_black;
238 rtexture_t *r_texture_notexture;
239 rtexture_t *r_texture_whitecube;
240 rtexture_t *r_texture_normalizationcube;
241 rtexture_t *r_texture_fogattenuation;
242 rtexture_t *r_texture_fogheighttexture;
243 rtexture_t *r_texture_gammaramps;
244 unsigned int r_texture_gammaramps_serial;
245 //rtexture_t *r_texture_fogintensity;
246 rtexture_t *r_texture_reflectcube;
247
248 // TODO: hash lookups?
249 typedef struct cubemapinfo_s
250 {
251         char basename[64];
252         rtexture_t *texture;
253 }
254 cubemapinfo_t;
255
256 int r_texture_numcubemaps;
257 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
258
259 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
260 unsigned int r_numqueries;
261 unsigned int r_maxqueries;
262
263 typedef struct r_qwskincache_s
264 {
265         char name[MAX_QPATH];
266         skinframe_t *skinframe;
267 }
268 r_qwskincache_t;
269
270 static r_qwskincache_t *r_qwskincache;
271 static int r_qwskincache_size;
272
273 /// vertex coordinates for a quad that covers the screen exactly
274 extern const float r_screenvertex3f[12];
275 extern const float r_d3dscreenvertex3f[12];
276 const float r_screenvertex3f[12] =
277 {
278         0, 0, 0,
279         1, 0, 0,
280         1, 1, 0,
281         0, 1, 0
282 };
283 const float r_d3dscreenvertex3f[12] =
284 {
285         0, 1, 0,
286         1, 1, 0,
287         1, 0, 0,
288         0, 0, 0
289 };
290
291 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
292 {
293         int i;
294         for (i = 0;i < verts;i++)
295         {
296                 out[0] = in[0] * r;
297                 out[1] = in[1] * g;
298                 out[2] = in[2] * b;
299                 out[3] = in[3];
300                 in += 4;
301                 out += 4;
302         }
303 }
304
305 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
306 {
307         int i;
308         for (i = 0;i < verts;i++)
309         {
310                 out[0] = r;
311                 out[1] = g;
312                 out[2] = b;
313                 out[3] = a;
314                 out += 4;
315         }
316 }
317
318 // FIXME: move this to client?
319 void FOG_clear(void)
320 {
321         if (gamemode == GAME_NEHAHRA)
322         {
323                 Cvar_Set("gl_fogenable", "0");
324                 Cvar_Set("gl_fogdensity", "0.2");
325                 Cvar_Set("gl_fogred", "0.3");
326                 Cvar_Set("gl_foggreen", "0.3");
327                 Cvar_Set("gl_fogblue", "0.3");
328         }
329         r_refdef.fog_density = 0;
330         r_refdef.fog_red = 0;
331         r_refdef.fog_green = 0;
332         r_refdef.fog_blue = 0;
333         r_refdef.fog_alpha = 1;
334         r_refdef.fog_start = 0;
335         r_refdef.fog_end = 16384;
336         r_refdef.fog_height = 1<<30;
337         r_refdef.fog_fadedepth = 128;
338         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
339 }
340
341 static void R_BuildBlankTextures(void)
342 {
343         unsigned char data[4];
344         data[2] = 128; // normal X
345         data[1] = 128; // normal Y
346         data[0] = 255; // normal Z
347         data[3] = 128; // height
348         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
349         data[0] = 255;
350         data[1] = 255;
351         data[2] = 255;
352         data[3] = 255;
353         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
354         data[0] = 128;
355         data[1] = 128;
356         data[2] = 128;
357         data[3] = 255;
358         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359         data[0] = 0;
360         data[1] = 0;
361         data[2] = 0;
362         data[3] = 255;
363         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364 }
365
366 static void R_BuildNoTexture(void)
367 {
368         int x, y;
369         unsigned char pix[16][16][4];
370         // this makes a light grey/dark grey checkerboard texture
371         for (y = 0;y < 16;y++)
372         {
373                 for (x = 0;x < 16;x++)
374                 {
375                         if ((y < 8) ^ (x < 8))
376                         {
377                                 pix[y][x][0] = 128;
378                                 pix[y][x][1] = 128;
379                                 pix[y][x][2] = 128;
380                                 pix[y][x][3] = 255;
381                         }
382                         else
383                         {
384                                 pix[y][x][0] = 64;
385                                 pix[y][x][1] = 64;
386                                 pix[y][x][2] = 64;
387                                 pix[y][x][3] = 255;
388                         }
389                 }
390         }
391         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
392 }
393
394 static void R_BuildWhiteCube(void)
395 {
396         unsigned char data[6*1*1*4];
397         memset(data, 255, sizeof(data));
398         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
399 }
400
401 static void R_BuildNormalizationCube(void)
402 {
403         int x, y, side;
404         vec3_t v;
405         vec_t s, t, intensity;
406 #define NORMSIZE 64
407         unsigned char *data;
408         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
409         for (side = 0;side < 6;side++)
410         {
411                 for (y = 0;y < NORMSIZE;y++)
412                 {
413                         for (x = 0;x < NORMSIZE;x++)
414                         {
415                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
416                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
417                                 switch(side)
418                                 {
419                                 default:
420                                 case 0:
421                                         v[0] = 1;
422                                         v[1] = -t;
423                                         v[2] = -s;
424                                         break;
425                                 case 1:
426                                         v[0] = -1;
427                                         v[1] = -t;
428                                         v[2] = s;
429                                         break;
430                                 case 2:
431                                         v[0] = s;
432                                         v[1] = 1;
433                                         v[2] = t;
434                                         break;
435                                 case 3:
436                                         v[0] = s;
437                                         v[1] = -1;
438                                         v[2] = -t;
439                                         break;
440                                 case 4:
441                                         v[0] = s;
442                                         v[1] = -t;
443                                         v[2] = 1;
444                                         break;
445                                 case 5:
446                                         v[0] = -s;
447                                         v[1] = -t;
448                                         v[2] = -1;
449                                         break;
450                                 }
451                                 intensity = 127.0f / sqrt(DotProduct(v, v));
452                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
453                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
454                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
455                                 data[((side*64+y)*64+x)*4+3] = 255;
456                         }
457                 }
458         }
459         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
460         Mem_Free(data);
461 }
462
463 static void R_BuildFogTexture(void)
464 {
465         int x, b;
466 #define FOGWIDTH 256
467         unsigned char data1[FOGWIDTH][4];
468         //unsigned char data2[FOGWIDTH][4];
469         double d, r, alpha;
470
471         r_refdef.fogmasktable_start = r_refdef.fog_start;
472         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
473         r_refdef.fogmasktable_range = r_refdef.fogrange;
474         r_refdef.fogmasktable_density = r_refdef.fog_density;
475
476         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
477         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
478         {
479                 d = (x * r - r_refdef.fogmasktable_start);
480                 if(developer_extra.integer)
481                         Con_DPrintf("%f ", d);
482                 d = max(0, d);
483                 if (r_fog_exp2.integer)
484                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
485                 else
486                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
487                 if(developer_extra.integer)
488                         Con_DPrintf(" : %f ", alpha);
489                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
490                 if(developer_extra.integer)
491                         Con_DPrintf(" = %f\n", alpha);
492                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
493         }
494
495         for (x = 0;x < FOGWIDTH;x++)
496         {
497                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
498                 data1[x][0] = b;
499                 data1[x][1] = b;
500                 data1[x][2] = b;
501                 data1[x][3] = 255;
502                 //data2[x][0] = 255 - b;
503                 //data2[x][1] = 255 - b;
504                 //data2[x][2] = 255 - b;
505                 //data2[x][3] = 255;
506         }
507         if (r_texture_fogattenuation)
508         {
509                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, FOGWIDTH, 1);
510                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 1);
511         }
512         else
513         {
514                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
515                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
516         }
517 }
518
519 static void R_BuildFogHeightTexture(void)
520 {
521         unsigned char *inpixels;
522         int size;
523         int x;
524         int y;
525         int j;
526         float c[4];
527         float f;
528         inpixels = NULL;
529         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
530         if (r_refdef.fogheighttexturename[0])
531                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
532         if (!inpixels)
533         {
534                 r_refdef.fog_height_tablesize = 0;
535                 if (r_texture_fogheighttexture)
536                         R_FreeTexture(r_texture_fogheighttexture);
537                 r_texture_fogheighttexture = NULL;
538                 if (r_refdef.fog_height_table2d)
539                         Mem_Free(r_refdef.fog_height_table2d);
540                 r_refdef.fog_height_table2d = NULL;
541                 if (r_refdef.fog_height_table1d)
542                         Mem_Free(r_refdef.fog_height_table1d);
543                 r_refdef.fog_height_table1d = NULL;
544                 return;
545         }
546         size = image_width;
547         r_refdef.fog_height_tablesize = size;
548         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
549         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
550         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
551         Mem_Free(inpixels);
552         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
553         // average fog color table accounting for every fog layer between a point
554         // and the camera.  (Note: attenuation is handled separately!)
555         for (y = 0;y < size;y++)
556         {
557                 for (x = 0;x < size;x++)
558                 {
559                         Vector4Clear(c);
560                         f = 0;
561                         if (x < y)
562                         {
563                                 for (j = x;j <= y;j++)
564                                 {
565                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
566                                         f++;
567                                 }
568                         }
569                         else
570                         {
571                                 for (j = x;j >= y;j--)
572                                 {
573                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
574                                         f++;
575                                 }
576                         }
577                         f = 1.0f / f;
578                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
579                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
580                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
581                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
582                 }
583         }
584         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
585 }
586
587 //=======================================================================================================================================================
588
589 static const char *builtinshaderstring =
590 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
591 "// written by Forest 'LordHavoc' Hale\n"
592 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
593 "\n"
594 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
595 "# define USEFOG\n"
596 "#endif\n"
597 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
598 "#define USELIGHTMAP\n"
599 "#endif\n"
600 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
601 "#define USEEYEVECTOR\n"
602 "#endif\n"
603 "\n"
604 "#ifdef USESHADOWMAP2D\n"
605 "# ifdef GL_EXT_gpu_shader4\n"
606 "#   extension GL_EXT_gpu_shader4 : enable\n"
607 "# endif\n"
608 "# ifdef GL_ARB_texture_gather\n"
609 "#   extension GL_ARB_texture_gather : enable\n"
610 "# else\n"
611 "#   ifdef GL_AMD_texture_texture4\n"
612 "#     extension GL_AMD_texture_texture4 : enable\n"
613 "#   endif\n"
614 "# endif\n"
615 "#endif\n"
616 "\n"
617 "//#ifdef USESHADOWSAMPLER\n"
618 "//# extension GL_ARB_shadow : enable\n"
619 "//#endif\n"
620 "\n"
621 "//#ifdef __GLSL_CG_DATA_TYPES\n"
622 "//# define myhalf half\n"
623 "//# define myhalf2 half2\n"
624 "//# define myhalf3 half3\n"
625 "//# define myhalf4 half4\n"
626 "//#else\n"
627 "# define myhalf float\n"
628 "# define myhalf2 vec2\n"
629 "# define myhalf3 vec3\n"
630 "# define myhalf4 vec4\n"
631 "//#endif\n"
632 "\n"
633 "#ifdef VERTEX_SHADER\n"
634 "uniform mat4 ModelViewProjectionMatrix;\n"
635 "#endif\n"
636 "\n"
637 "#ifdef MODE_DEPTH_OR_SHADOW\n"
638 "#ifdef VERTEX_SHADER\n"
639 "void main(void)\n"
640 "{\n"
641 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
642 "}\n"
643 "#endif\n"
644 "#else // !MODE_DEPTH_ORSHADOW\n"
645 "\n"
646 "\n"
647 "\n"
648 "\n"
649 "#ifdef MODE_SHOWDEPTH\n"
650 "#ifdef VERTEX_SHADER\n"
651 "void main(void)\n"
652 "{\n"
653 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
654 "       gl_FrontColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
655 "}\n"
656 "#endif\n"
657 "\n"
658 "#ifdef FRAGMENT_SHADER\n"
659 "void main(void)\n"
660 "{\n"
661 "       gl_FragColor = gl_Color;\n"
662 "}\n"
663 "#endif\n"
664 "#else // !MODE_SHOWDEPTH\n"
665 "\n"
666 "\n"
667 "\n"
668 "\n"
669 "#ifdef MODE_POSTPROCESS\n"
670 "varying vec2 TexCoord1;\n"
671 "varying vec2 TexCoord2;\n"
672 "\n"
673 "#ifdef VERTEX_SHADER\n"
674 "void main(void)\n"
675 "{\n"
676 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
677 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
678 "#ifdef USEBLOOM\n"
679 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
680 "#endif\n"
681 "}\n"
682 "#endif\n"
683 "\n"
684 "#ifdef FRAGMENT_SHADER\n"
685 "uniform sampler2D Texture_First;\n"
686 "#ifdef USEBLOOM\n"
687 "uniform sampler2D Texture_Second;\n"
688 "uniform vec4 BloomColorSubtract;\n"
689 "#endif\n"
690 "#ifdef USEGAMMARAMPS\n"
691 "uniform sampler2D Texture_GammaRamps;\n"
692 "#endif\n"
693 "#ifdef USESATURATION\n"
694 "uniform float Saturation;\n"
695 "#endif\n"
696 "#ifdef USEVIEWTINT\n"
697 "uniform vec4 ViewTintColor;\n"
698 "#endif\n"
699 "//uncomment these if you want to use them:\n"
700 "uniform vec4 UserVec1;\n"
701 "uniform vec4 UserVec2;\n"
702 "// uniform vec4 UserVec3;\n"
703 "// uniform vec4 UserVec4;\n"
704 "// uniform float ClientTime;\n"
705 "uniform vec2 PixelSize;\n"
706 "void main(void)\n"
707 "{\n"
708 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
709 "#ifdef USEBLOOM\n"
710 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
711 "#endif\n"
712 "#ifdef USEVIEWTINT\n"
713 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
714 "#endif\n"
715 "\n"
716 "#ifdef USEPOSTPROCESSING\n"
717 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
718 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
719 "       float sobel = 1.0;\n"
720 "       // vec2 ts = textureSize(Texture_First, 0);\n"
721 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
722 "       vec2 px = PixelSize;\n"
723 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
724 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
725 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
726 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
727 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
728 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
729 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
730 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
731 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
732 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
733 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
734 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
735 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
736 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
737 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
738 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
739 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
740 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
741 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
742 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
743 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
744 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
745 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
746 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
747 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
748 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
749 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
750 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
751 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
752 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
753 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
754 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
755 "#endif\n"
756 "\n"
757 "#ifdef USESATURATION\n"
758 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
759 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
760 "       // 'vampire sight' effect, wheres red is compensated\n"
761 "       #ifdef SATURATION_REDCOMPENSATE\n"
762 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
763 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
764 "               gl_FragColor.r += rboost;\n"
765 "       #else\n"
766 "               // normal desaturation\n"
767 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
768 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
769 "       #endif\n"
770 "#endif\n"
771 "\n"
772 "#ifdef USEGAMMARAMPS\n"
773 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
774 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
775 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
776 "#endif\n"
777 "}\n"
778 "#endif\n"
779 "#else // !MODE_POSTPROCESS\n"
780 "\n"
781 "\n"
782 "\n"
783 "\n"
784 "#ifdef MODE_GENERIC\n"
785 "#ifdef USEDIFFUSE\n"
786 "varying vec2 TexCoord1;\n"
787 "#endif\n"
788 "#ifdef USESPECULAR\n"
789 "varying vec2 TexCoord2;\n"
790 "#endif\n"
791 "#ifdef VERTEX_SHADER\n"
792 "void main(void)\n"
793 "{\n"
794 "       gl_FrontColor = gl_Color;\n"
795 "#ifdef USEDIFFUSE\n"
796 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
797 "#endif\n"
798 "#ifdef USESPECULAR\n"
799 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
800 "#endif\n"
801 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
802 "}\n"
803 "#endif\n"
804 "\n"
805 "#ifdef FRAGMENT_SHADER\n"
806 "#ifdef USEDIFFUSE\n"
807 "uniform sampler2D Texture_First;\n"
808 "#endif\n"
809 "#ifdef USESPECULAR\n"
810 "uniform sampler2D Texture_Second;\n"
811 "#endif\n"
812 "\n"
813 "void main(void)\n"
814 "{\n"
815 "#ifdef USEVIEWTINT\n"
816 "       gl_FragColor = gl_Color;\n"
817 "#else\n"
818 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
819 "#endif\n"
820 "#ifdef USEDIFFUSE\n"
821 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
822 "#endif\n"
823 "\n"
824 "#ifdef USESPECULAR\n"
825 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
826 "# ifdef USECOLORMAPPING\n"
827 "       gl_FragColor *= tex2;\n"
828 "# endif\n"
829 "# ifdef USEGLOW\n"
830 "       gl_FragColor += tex2;\n"
831 "# endif\n"
832 "# ifdef USEVERTEXTEXTUREBLEND\n"
833 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
834 "# endif\n"
835 "#endif\n"
836 "}\n"
837 "#endif\n"
838 "#else // !MODE_GENERIC\n"
839 "\n"
840 "\n"
841 "\n"
842 "\n"
843 "#ifdef MODE_BLOOMBLUR\n"
844 "varying TexCoord;\n"
845 "#ifdef VERTEX_SHADER\n"
846 "void main(void)\n"
847 "{\n"
848 "       gl_FrontColor = gl_Color;\n"
849 "       TexCoord = gl_MultiTexCoord0.xy;\n"
850 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
851 "}\n"
852 "#endif\n"
853 "\n"
854 "#ifdef FRAGMENT_SHADER\n"
855 "uniform sampler2D Texture_First;\n"
856 "uniform vec4 BloomBlur_Parameters;\n"
857 "\n"
858 "void main(void)\n"
859 "{\n"
860 "       int i;\n"
861 "       vec2 tc = TexCoord;\n"
862 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
863 "       tc += BloomBlur_Parameters.xy;\n"
864 "       for (i = 1;i < SAMPLES;i++)\n"
865 "       {\n"
866 "               color += texture2D(Texture_First, tc).rgb;\n"
867 "               tc += BloomBlur_Parameters.xy;\n"
868 "       }\n"
869 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
870 "}\n"
871 "#endif\n"
872 "#else // !MODE_BLOOMBLUR\n"
873 "#ifdef MODE_REFRACTION\n"
874 "varying vec2 TexCoord;\n"
875 "varying vec4 ModelViewProjectionPosition;\n"
876 "uniform mat4 TexMatrix;\n"
877 "#ifdef VERTEX_SHADER\n"
878 "\n"
879 "void main(void)\n"
880 "{\n"
881 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
882 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
883 "       ModelViewProjectionPosition = gl_Position;\n"
884 "}\n"
885 "#endif\n"
886 "\n"
887 "#ifdef FRAGMENT_SHADER\n"
888 "uniform sampler2D Texture_Normal;\n"
889 "uniform sampler2D Texture_Refraction;\n"
890 "uniform sampler2D Texture_Reflection;\n"
891 "\n"
892 "uniform vec4 DistortScaleRefractReflect;\n"
893 "uniform vec4 ScreenScaleRefractReflect;\n"
894 "uniform vec4 ScreenCenterRefractReflect;\n"
895 "uniform vec4 RefractColor;\n"
896 "uniform vec4 ReflectColor;\n"
897 "uniform float ReflectFactor;\n"
898 "uniform float ReflectOffset;\n"
899 "\n"
900 "void main(void)\n"
901 "{\n"
902 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
903 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
904 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
905 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
906 "       // FIXME temporary hack to detect the case that the reflection\n"
907 "       // gets blackened at edges due to leaving the area that contains actual\n"
908 "       // content.\n"
909 "       // Remove this 'ack once we have a better way to stop this thing from\n"
910 "       // 'appening.\n"
911 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
912 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
913 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
914 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
915 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
916 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
917 "}\n"
918 "#endif\n"
919 "#else // !MODE_REFRACTION\n"
920 "\n"
921 "\n"
922 "\n"
923 "\n"
924 "#ifdef MODE_WATER\n"
925 "varying vec2 TexCoord;\n"
926 "varying vec3 EyeVector;\n"
927 "varying vec4 ModelViewProjectionPosition;\n"
928 "#ifdef VERTEX_SHADER\n"
929 "uniform vec3 EyePosition;\n"
930 "uniform mat4 TexMatrix;\n"
931 "\n"
932 "void main(void)\n"
933 "{\n"
934 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
935 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
936 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
937 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
938 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
939 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
940 "       ModelViewProjectionPosition = gl_Position;\n"
941 "}\n"
942 "#endif\n"
943 "\n"
944 "#ifdef FRAGMENT_SHADER\n"
945 "uniform sampler2D Texture_Normal;\n"
946 "uniform sampler2D Texture_Refraction;\n"
947 "uniform sampler2D Texture_Reflection;\n"
948 "\n"
949 "uniform vec4 DistortScaleRefractReflect;\n"
950 "uniform vec4 ScreenScaleRefractReflect;\n"
951 "uniform vec4 ScreenCenterRefractReflect;\n"
952 "uniform vec4 RefractColor;\n"
953 "uniform vec4 ReflectColor;\n"
954 "uniform float ReflectFactor;\n"
955 "uniform float ReflectOffset;\n"
956 "uniform float ClientTime;\n"
957 "#ifdef USENORMALMAPSCROLLBLEND\n"
958 "uniform vec2 NormalmapScrollBlend;\n"
959 "#endif\n"
960 "\n"
961 "void main(void)\n"
962 "{\n"
963 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
964 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
965 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
966 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
967 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
968 "       #ifdef USENORMALMAPSCROLLBLEND\n"
969 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
970 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
971 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
972 "       #else\n"
973 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
974 "       #endif\n"
975 "       // FIXME temporary hack to detect the case that the reflection\n"
976 "       // gets blackened at edges due to leaving the area that contains actual\n"
977 "       // content.\n"
978 "       // Remove this 'ack once we have a better way to stop this thing from\n"
979 "       // 'appening.\n"
980 "       float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
981 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
982 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
983 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
984 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
985 "       f  = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
986 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
987 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
988 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
989 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
990 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
991 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
992 "}\n"
993 "#endif\n"
994 "#else // !MODE_WATER\n"
995 "\n"
996 "\n"
997 "\n"
998 "\n"
999 "// common definitions between vertex shader and fragment shader:\n"
1000 "\n"
1001 "varying vec2 TexCoord;\n"
1002 "#ifdef USEVERTEXTEXTUREBLEND\n"
1003 "varying vec2 TexCoord2;\n"
1004 "#endif\n"
1005 "#ifdef USELIGHTMAP\n"
1006 "varying vec2 TexCoordLightmap;\n"
1007 "#endif\n"
1008 "\n"
1009 "#ifdef MODE_LIGHTSOURCE\n"
1010 "varying vec3 CubeVector;\n"
1011 "#endif\n"
1012 "\n"
1013 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1014 "varying vec3 LightVector;\n"
1015 "#endif\n"
1016 "\n"
1017 "#ifdef USEEYEVECTOR\n"
1018 "varying vec3 EyeVector;\n"
1019 "#endif\n"
1020 "#ifdef USEFOG\n"
1021 "varying vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1022 "#endif\n"
1023 "\n"
1024 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1025 "varying vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1026 "varying vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1027 "varying vec3 VectorR; // direction of R texcoord (surface normal)\n"
1028 "#endif\n"
1029 "\n"
1030 "#ifdef USEREFLECTION\n"
1031 "varying vec4 ModelViewProjectionPosition;\n"
1032 "#endif\n"
1033 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1034 "uniform vec3 LightPosition;\n"
1035 "varying vec4 ModelViewPosition;\n"
1036 "#endif\n"
1037 "\n"
1038 "#ifdef MODE_LIGHTSOURCE\n"
1039 "uniform vec3 LightPosition;\n"
1040 "#endif\n"
1041 "uniform vec3 EyePosition;\n"
1042 "#ifdef MODE_LIGHTDIRECTION\n"
1043 "uniform vec3 LightDir;\n"
1044 "#endif\n"
1045 "uniform vec4 FogPlane;\n"
1046 "\n"
1047 "#ifdef USESHADOWMAPORTHO\n"
1048 "varying vec3 ShadowMapTC;\n"
1049 "#endif\n"
1050 "\n"
1051 "\n"
1052 "\n"
1053 "\n"
1054 "\n"
1055 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1056 "\n"
1057 "// fragment shader specific:\n"
1058 "#ifdef FRAGMENT_SHADER\n"
1059 "\n"
1060 "uniform sampler2D Texture_Normal;\n"
1061 "uniform sampler2D Texture_Color;\n"
1062 "uniform sampler2D Texture_Gloss;\n"
1063 "#ifdef USEGLOW\n"
1064 "uniform sampler2D Texture_Glow;\n"
1065 "#endif\n"
1066 "#ifdef USEVERTEXTEXTUREBLEND\n"
1067 "uniform sampler2D Texture_SecondaryNormal;\n"
1068 "uniform sampler2D Texture_SecondaryColor;\n"
1069 "uniform sampler2D Texture_SecondaryGloss;\n"
1070 "#ifdef USEGLOW\n"
1071 "uniform sampler2D Texture_SecondaryGlow;\n"
1072 "#endif\n"
1073 "#endif\n"
1074 "#ifdef USECOLORMAPPING\n"
1075 "uniform sampler2D Texture_Pants;\n"
1076 "uniform sampler2D Texture_Shirt;\n"
1077 "#endif\n"
1078 "#ifdef USEFOG\n"
1079 "#ifdef USEFOGHEIGHTTEXTURE\n"
1080 "uniform sampler2D Texture_FogHeightTexture;\n"
1081 "#endif\n"
1082 "uniform sampler2D Texture_FogMask;\n"
1083 "#endif\n"
1084 "#ifdef USELIGHTMAP\n"
1085 "uniform sampler2D Texture_Lightmap;\n"
1086 "#endif\n"
1087 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1088 "uniform sampler2D Texture_Deluxemap;\n"
1089 "#endif\n"
1090 "#ifdef USEREFLECTION\n"
1091 "uniform sampler2D Texture_Reflection;\n"
1092 "#endif\n"
1093 "\n"
1094 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1095 "uniform sampler2D Texture_ScreenDepth;\n"
1096 "uniform sampler2D Texture_ScreenNormalMap;\n"
1097 "#endif\n"
1098 "#ifdef USEDEFERREDLIGHTMAP\n"
1099 "uniform sampler2D Texture_ScreenDiffuse;\n"
1100 "uniform sampler2D Texture_ScreenSpecular;\n"
1101 "#endif\n"
1102 "\n"
1103 "uniform myhalf3 Color_Pants;\n"
1104 "uniform myhalf3 Color_Shirt;\n"
1105 "uniform myhalf3 FogColor;\n"
1106 "\n"
1107 "#ifdef USEFOG\n"
1108 "uniform float FogRangeRecip;\n"
1109 "uniform float FogPlaneViewDist;\n"
1110 "uniform float FogHeightFade;\n"
1111 "vec3 FogVertex(vec3 surfacecolor)\n"
1112 "{\n"
1113 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1114 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1115 "       float fogfrac;\n"
1116 "#ifdef USEFOGHEIGHTTEXTURE\n"
1117 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1118 "       fogfrac = fogheightpixel.a;\n"
1119 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1120 "#else\n"
1121 "# ifdef USEFOGOUTSIDE\n"
1122 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1123 "# else\n"
1124 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1125 "# endif\n"
1126 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1127 "#endif\n"
1128 "}\n"
1129 "#endif\n"
1130 "\n"
1131 "#ifdef USEOFFSETMAPPING\n"
1132 "uniform float OffsetMapping_Scale;\n"
1133 "vec2 OffsetMapping(vec2 TexCoord)\n"
1134 "{\n"
1135 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1136 "       // 14 sample relief mapping: linear search and then binary search\n"
1137 "       // this basically steps forward a small amount repeatedly until it finds\n"
1138 "       // itself inside solid, then jitters forward and back using decreasing\n"
1139 "       // amounts to find the impact\n"
1140 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1141 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1142 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1143 "       vec3 RT = vec3(TexCoord, 1);\n"
1144 "       OffsetVector *= 0.1;\n"
1145 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1146 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1147 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1148 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1149 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1150 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1151 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1152 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1153 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1154 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1155 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1156 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1157 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1158 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1159 "       return RT.xy;\n"
1160 "#else\n"
1161 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1162 "       // this basically moves forward the full distance, and then backs up based\n"
1163 "       // on height of samples\n"
1164 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1165 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1166 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1167 "       TexCoord += OffsetVector;\n"
1168 "       OffsetVector *= 0.5;\n"
1169 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1170 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1171 "       return TexCoord;\n"
1172 "#endif\n"
1173 "}\n"
1174 "#endif // USEOFFSETMAPPING\n"
1175 "\n"
1176 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1177 "uniform sampler2D Texture_Attenuation;\n"
1178 "uniform samplerCube Texture_Cube;\n"
1179 "#endif\n"
1180 "\n"
1181 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1182 "\n"
1183 "#ifdef USESHADOWMAP2D\n"
1184 "# ifdef USESHADOWSAMPLER\n"
1185 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1186 "# else\n"
1187 "uniform sampler2D Texture_ShadowMap2D;\n"
1188 "# endif\n"
1189 "#endif\n"
1190 "\n"
1191 "#ifdef USESHADOWMAPVSDCT\n"
1192 "uniform samplerCube Texture_CubeProjection;\n"
1193 "#endif\n"
1194 "\n"
1195 "#if defined(USESHADOWMAP2D)\n"
1196 "uniform vec2 ShadowMap_TextureScale;\n"
1197 "uniform vec4 ShadowMap_Parameters;\n"
1198 "#endif\n"
1199 "\n"
1200 "#if defined(USESHADOWMAP2D)\n"
1201 "# ifdef USESHADOWMAPORTHO\n"
1202 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1203 "# else\n"
1204 "#  ifdef USESHADOWMAPVSDCT\n"
1205 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1206 "{\n"
1207 "       vec3 adir = abs(dir);\n"
1208 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1209 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1210 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1211 "}\n"
1212 "#  else\n"
1213 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1214 "{\n"
1215 "       vec3 adir = abs(dir);\n"
1216 "       float ma = adir.z;\n"
1217 "       vec4 proj = vec4(dir, 2.5);\n"
1218 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1219 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1220 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1221 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1222 "}\n"
1223 "#  endif\n"
1224 "# endif\n"
1225 "#endif // defined(USESHADOWMAP2D)\n"
1226 "\n"
1227 "# ifdef USESHADOWMAP2D\n"
1228 "float ShadowMapCompare(vec3 dir)\n"
1229 "{\n"
1230 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1231 "       float f;\n"
1232 "\n"
1233 "#  ifdef USESHADOWSAMPLER\n"
1234 "#    ifdef USESHADOWMAPPCF\n"
1235 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1236 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1237 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1238 "#    else\n"
1239 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1240 "#    endif\n"
1241 "#  else\n"
1242 "#    ifdef USESHADOWMAPPCF\n"
1243 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1244 "#      ifdef GL_ARB_texture_gather\n"
1245 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1246 "#      else\n"
1247 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1248 "#      endif\n"
1249 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1250 "#      if USESHADOWMAPPCF > 1\n"
1251 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1252 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1253 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1254 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1255 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1256 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1257 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1258 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1259 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1260 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1261 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1262 "       locols.yz += group2.ab;\n"
1263 "       hicols.yz += group8.rg;\n"
1264 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1265 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1266 "                               mix(locols, hicols, offset.y);\n"
1267 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1268 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1269 "       f = dot(cols, vec4(1.0/25.0));\n"
1270 "#      else\n"
1271 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1272 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1273 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1274 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1275 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1276 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1277 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1278 "#      endif\n"
1279 "#     else\n"
1280 "#      ifdef GL_EXT_gpu_shader4\n"
1281 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1282 "#      else\n"
1283 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1284 "#      endif\n"
1285 "#      if USESHADOWMAPPCF > 1\n"
1286 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1287 "       center *= ShadowMap_TextureScale;\n"
1288 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1289 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1290 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1291 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1292 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1293 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1294 "#      else\n"
1295 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1296 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1297 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1298 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1299 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1300 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1301 "#      endif\n"
1302 "#     endif\n"
1303 "#    else\n"
1304 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1305 "#    endif\n"
1306 "#  endif\n"
1307 "#  ifdef USESHADOWMAPORTHO\n"
1308 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1309 "#  else\n"
1310 "       return f;\n"
1311 "#  endif\n"
1312 "}\n"
1313 "# endif\n"
1314 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1315 "#endif // FRAGMENT_SHADER\n"
1316 "\n"
1317 "\n"
1318 "\n"
1319 "\n"
1320 "#ifdef MODE_DEFERREDGEOMETRY\n"
1321 "#ifdef VERTEX_SHADER\n"
1322 "uniform mat4 TexMatrix;\n"
1323 "#ifdef USEVERTEXTEXTUREBLEND\n"
1324 "uniform mat4 BackgroundTexMatrix;\n"
1325 "#endif\n"
1326 "uniform mat4 ModelViewMatrix;\n"
1327 "void main(void)\n"
1328 "{\n"
1329 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1330 "#ifdef USEVERTEXTEXTUREBLEND\n"
1331 "       gl_FrontColor = gl_Color;\n"
1332 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1333 "#endif\n"
1334 "\n"
1335 "       // transform unnormalized eye direction into tangent space\n"
1336 "#ifdef USEOFFSETMAPPING\n"
1337 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1338 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1339 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1340 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1341 "#endif\n"
1342 "\n"
1343 "       VectorS = (ModelViewMatrix * vec4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
1344 "       VectorT = (ModelViewMatrix * vec4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
1345 "       VectorR = (ModelViewMatrix * vec4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
1346 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1347 "}\n"
1348 "#endif // VERTEX_SHADER\n"
1349 "\n"
1350 "#ifdef FRAGMENT_SHADER\n"
1351 "void main(void)\n"
1352 "{\n"
1353 "#ifdef USEOFFSETMAPPING\n"
1354 "       // apply offsetmapping\n"
1355 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1356 "#define TexCoord TexCoordOffset\n"
1357 "#endif\n"
1358 "\n"
1359 "#ifdef USEALPHAKILL\n"
1360 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1361 "               discard;\n"
1362 "#endif\n"
1363 "\n"
1364 "#ifdef USEVERTEXTEXTUREBLEND\n"
1365 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1366 "       float terrainblend = clamp(float(gl_Color.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1367 "       //float terrainblend = min(float(gl_Color.a) * alpha * 2.0, float(1.0));\n"
1368 "       //float terrainblend = float(gl_Color.a) * alpha > 0.5;\n"
1369 "#endif\n"
1370 "\n"
1371 "#ifdef USEVERTEXTEXTUREBLEND\n"
1372 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1373 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1374 "#else\n"
1375 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1376 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1377 "#endif\n"
1378 "\n"
1379 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1380 "}\n"
1381 "#endif // FRAGMENT_SHADER\n"
1382 "#else // !MODE_DEFERREDGEOMETRY\n"
1383 "\n"
1384 "\n"
1385 "\n"
1386 "\n"
1387 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1388 "#ifdef VERTEX_SHADER\n"
1389 "uniform mat4 ModelViewMatrix;\n"
1390 "void main(void)\n"
1391 "{\n"
1392 "       ModelViewPosition = ModelViewMatrix * gl_Vertex;\n"
1393 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1394 "}\n"
1395 "#endif // VERTEX_SHADER\n"
1396 "\n"
1397 "#ifdef FRAGMENT_SHADER\n"
1398 "uniform mat4 ViewToLight;\n"
1399 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1400 "uniform vec2 ScreenToDepth;\n"
1401 "uniform myhalf3 DeferredColor_Ambient;\n"
1402 "uniform myhalf3 DeferredColor_Diffuse;\n"
1403 "#ifdef USESPECULAR\n"
1404 "uniform myhalf3 DeferredColor_Specular;\n"
1405 "uniform myhalf SpecularPower;\n"
1406 "#endif\n"
1407 "uniform myhalf2 PixelToScreenTexCoord;\n"
1408 "void main(void)\n"
1409 "{\n"
1410 "       // calculate viewspace pixel position\n"
1411 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1412 "       vec3 position;\n"
1413 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1414 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1415 "       // decode viewspace pixel normal\n"
1416 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1417 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1418 "       // surfacenormal = pixel normal in viewspace\n"
1419 "       // LightVector = pixel to light in viewspace\n"
1420 "       // CubeVector = position in lightspace\n"
1421 "       // eyevector = pixel to view in viewspace\n"
1422 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1423 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1424 "#ifdef USEDIFFUSE\n"
1425 "       // calculate diffuse shading\n"
1426 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1427 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1428 "#endif\n"
1429 "#ifdef USESPECULAR\n"
1430 "       // calculate directional shading\n"
1431 "       vec3 eyevector = position * -1.0;\n"
1432 "#  ifdef USEEXACTSPECULARMATH\n"
1433 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1434 "#  else\n"
1435 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1436 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1437 "#  endif\n"
1438 "#endif\n"
1439 "\n"
1440 "#if defined(USESHADOWMAP2D)\n"
1441 "       fade *= ShadowMapCompare(CubeVector);\n"
1442 "#endif\n"
1443 "\n"
1444 "#ifdef USEDIFFUSE\n"
1445 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1446 "#else\n"
1447 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1448 "#endif\n"
1449 "#ifdef USESPECULAR\n"
1450 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1451 "#else\n"
1452 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1453 "#endif\n"
1454 "\n"
1455 "# ifdef USECUBEFILTER\n"
1456 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1457 "       gl_FragData[0].rgb *= cubecolor;\n"
1458 "       gl_FragData[1].rgb *= cubecolor;\n"
1459 "# endif\n"
1460 "}\n"
1461 "#endif // FRAGMENT_SHADER\n"
1462 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1463 "\n"
1464 "\n"
1465 "\n"
1466 "\n"
1467 "#ifdef VERTEX_SHADER\n"
1468 "uniform mat4 TexMatrix;\n"
1469 "#ifdef USEVERTEXTEXTUREBLEND\n"
1470 "uniform mat4 BackgroundTexMatrix;\n"
1471 "#endif\n"
1472 "#ifdef MODE_LIGHTSOURCE\n"
1473 "uniform mat4 ModelToLight;\n"
1474 "#endif\n"
1475 "#ifdef USESHADOWMAPORTHO\n"
1476 "uniform mat4 ShadowMapMatrix;\n"
1477 "#endif\n"
1478 "void main(void)\n"
1479 "{\n"
1480 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1481 "       gl_FrontColor = gl_Color;\n"
1482 "#endif\n"
1483 "       // copy the surface texcoord\n"
1484 "       TexCoord = vec2(TexMatrix * gl_MultiTexCoord0);\n"
1485 "#ifdef USEVERTEXTEXTUREBLEND\n"
1486 "       TexCoord2 = vec2(BackgroundTexMatrix * gl_MultiTexCoord0);\n"
1487 "#endif\n"
1488 "#ifdef USELIGHTMAP\n"
1489 "       TexCoordLightmap = vec2(gl_MultiTexCoord4);\n"
1490 "#endif\n"
1491 "\n"
1492 "#ifdef MODE_LIGHTSOURCE\n"
1493 "       // transform vertex position into light attenuation/cubemap space\n"
1494 "       // (-1 to +1 across the light box)\n"
1495 "       CubeVector = vec3(ModelToLight * gl_Vertex);\n"
1496 "\n"
1497 "# ifdef USEDIFFUSE\n"
1498 "       // transform unnormalized light direction into tangent space\n"
1499 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1500 "       //  normalize it per pixel)\n"
1501 "       vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
1502 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
1503 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
1504 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
1505 "# endif\n"
1506 "#endif\n"
1507 "\n"
1508 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1509 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
1510 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
1511 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
1512 "#endif\n"
1513 "\n"
1514 "       // transform unnormalized eye direction into tangent space\n"
1515 "#ifdef USEEYEVECTOR\n"
1516 "       vec3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
1517 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
1518 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
1519 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
1520 "#endif\n"
1521 "\n"
1522 "#ifdef USEFOG\n"
1523 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
1524 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
1525 "#endif\n"
1526 "\n"
1527 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1528 "       VectorS = gl_MultiTexCoord1.xyz;\n"
1529 "       VectorT = gl_MultiTexCoord2.xyz;\n"
1530 "       VectorR = gl_MultiTexCoord3.xyz;\n"
1531 "#endif\n"
1532 "\n"
1533 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1534 "       gl_Position = ModelViewProjectionMatrix * gl_Vertex;\n"
1535 "\n"
1536 "#ifdef USESHADOWMAPORTHO\n"
1537 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1538 "#endif\n"
1539 "\n"
1540 "#ifdef USEREFLECTION\n"
1541 "       ModelViewProjectionPosition = gl_Position;\n"
1542 "#endif\n"
1543 "}\n"
1544 "#endif // VERTEX_SHADER\n"
1545 "\n"
1546 "\n"
1547 "\n"
1548 "\n"
1549 "#ifdef FRAGMENT_SHADER\n"
1550 "#ifdef USEDEFERREDLIGHTMAP\n"
1551 "uniform myhalf2 PixelToScreenTexCoord;\n"
1552 "uniform myhalf3 DeferredMod_Diffuse;\n"
1553 "uniform myhalf3 DeferredMod_Specular;\n"
1554 "#endif\n"
1555 "uniform myhalf3 Color_Ambient;\n"
1556 "uniform myhalf3 Color_Diffuse;\n"
1557 "uniform myhalf3 Color_Specular;\n"
1558 "uniform myhalf SpecularPower;\n"
1559 "#ifdef USEGLOW\n"
1560 "uniform myhalf3 Color_Glow;\n"
1561 "#endif\n"
1562 "uniform myhalf Alpha;\n"
1563 "#ifdef USEREFLECTION\n"
1564 "uniform vec4 DistortScaleRefractReflect;\n"
1565 "uniform vec4 ScreenScaleRefractReflect;\n"
1566 "uniform vec4 ScreenCenterRefractReflect;\n"
1567 "uniform myhalf4 ReflectColor;\n"
1568 "#endif\n"
1569 "#ifdef USEREFLECTCUBE\n"
1570 "uniform mat4 ModelToReflectCube;\n"
1571 "uniform sampler2D Texture_ReflectMask;\n"
1572 "uniform samplerCube Texture_ReflectCube;\n"
1573 "#endif\n"
1574 "#ifdef MODE_LIGHTDIRECTION\n"
1575 "uniform myhalf3 LightColor;\n"
1576 "#endif\n"
1577 "#ifdef MODE_LIGHTSOURCE\n"
1578 "uniform myhalf3 LightColor;\n"
1579 "#endif\n"
1580 "void main(void)\n"
1581 "{\n"
1582 "#ifdef USEOFFSETMAPPING\n"
1583 "       // apply offsetmapping\n"
1584 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1585 "#define TexCoord TexCoordOffset\n"
1586 "#endif\n"
1587 "\n"
1588 "       // combine the diffuse textures (base, pants, shirt)\n"
1589 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1590 "#ifdef USEALPHAKILL\n"
1591 "       if (color.a < 0.5)\n"
1592 "               discard;\n"
1593 "#endif\n"
1594 "       color.a *= Alpha;\n"
1595 "#ifdef USECOLORMAPPING\n"
1596 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1597 "#endif\n"
1598 "#ifdef USEVERTEXTEXTUREBLEND\n"
1599 "       myhalf terrainblend = clamp(myhalf(gl_Color.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1600 "       //myhalf terrainblend = min(myhalf(gl_Color.a) * color.a * 2.0, myhalf(1.0));\n"
1601 "       //myhalf terrainblend = myhalf(gl_Color.a) * color.a > 0.5;\n"
1602 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1603 "       color.a = 1.0;\n"
1604 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1605 "#endif\n"
1606 "\n"
1607 "       // get the surface normal\n"
1608 "#ifdef USEVERTEXTEXTUREBLEND\n"
1609 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1610 "#else\n"
1611 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1612 "#endif\n"
1613 "\n"
1614 "       // get the material colors\n"
1615 "       myhalf3 diffusetex = color.rgb;\n"
1616 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1617 "# ifdef USEVERTEXTEXTUREBLEND\n"
1618 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1619 "# else\n"
1620 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1621 "# endif\n"
1622 "#endif\n"
1623 "\n"
1624 "#ifdef USEREFLECTCUBE\n"
1625 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1626 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1627 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1628 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1629 "#endif\n"
1630 "\n"
1631 "\n"
1632 "\n"
1633 "\n"
1634 "#ifdef MODE_LIGHTSOURCE\n"
1635 "       // light source\n"
1636 "#ifdef USEDIFFUSE\n"
1637 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1638 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1639 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1640 "#ifdef USESPECULAR\n"
1641 "#ifdef USEEXACTSPECULARMATH\n"
1642 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1643 "#else\n"
1644 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1645 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1646 "#endif\n"
1647 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1648 "#endif\n"
1649 "#else\n"
1650 "       color.rgb = diffusetex * Color_Ambient;\n"
1651 "#endif\n"
1652 "       color.rgb *= LightColor;\n"
1653 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1654 "#if defined(USESHADOWMAP2D)\n"
1655 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1656 "#endif\n"
1657 "# ifdef USECUBEFILTER\n"
1658 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1659 "# endif\n"
1660 "#endif // MODE_LIGHTSOURCE\n"
1661 "\n"
1662 "\n"
1663 "\n"
1664 "\n"
1665 "#ifdef MODE_LIGHTDIRECTION\n"
1666 "#define SHADING\n"
1667 "#ifdef USEDIFFUSE\n"
1668 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1669 "#endif\n"
1670 "#define lightcolor LightColor\n"
1671 "#endif // MODE_LIGHTDIRECTION\n"
1672 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1673 "#define SHADING\n"
1674 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1675 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1676 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1677 "       // convert modelspace light vector to tangentspace\n"
1678 "       myhalf3 lightnormal;\n"
1679 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1680 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1681 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1682 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1683 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1684 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1685 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1686 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1687 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1688 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1689 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1690 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1691 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1692 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1693 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1694 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1695 "#define SHADING\n"
1696 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1697 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1698 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1699 "#endif\n"
1700 "\n"
1701 "\n"
1702 "\n"
1703 "\n"
1704 "#ifdef MODE_FAKELIGHT\n"
1705 "#define SHADING\n"
1706 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1707 "myhalf3 lightcolor = myhalf3(1.0);\n"
1708 "#endif // MODE_FAKELIGHT\n"
1709 "\n"
1710 "\n"
1711 "\n"
1712 "\n"
1713 "#ifdef MODE_LIGHTMAP\n"
1714 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1715 "#endif // MODE_LIGHTMAP\n"
1716 "#ifdef MODE_VERTEXCOLOR\n"
1717 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(gl_Color.rgb) * Color_Diffuse);\n"
1718 "#endif // MODE_VERTEXCOLOR\n"
1719 "#ifdef MODE_FLATCOLOR\n"
1720 "       color.rgb = diffusetex * Color_Ambient;\n"
1721 "#endif // MODE_FLATCOLOR\n"
1722 "\n"
1723 "\n"
1724 "\n"
1725 "\n"
1726 "#ifdef SHADING\n"
1727 "# ifdef USEDIFFUSE\n"
1728 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1729 "#  ifdef USESPECULAR\n"
1730 "#   ifdef USEEXACTSPECULARMATH\n"
1731 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1732 "#   else\n"
1733 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1734 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1735 "#   endif\n"
1736 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1737 "#  else\n"
1738 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1739 "#  endif\n"
1740 "# else\n"
1741 "       color.rgb = diffusetex * Color_Ambient;\n"
1742 "# endif\n"
1743 "#endif\n"
1744 "\n"
1745 "#ifdef USESHADOWMAPORTHO\n"
1746 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1747 "#endif\n"
1748 "\n"
1749 "#ifdef USEDEFERREDLIGHTMAP\n"
1750 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1751 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1752 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1753 "#endif\n"
1754 "\n"
1755 "#ifdef USEGLOW\n"
1756 "#ifdef USEVERTEXTEXTUREBLEND\n"
1757 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1758 "#else\n"
1759 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1760 "#endif\n"
1761 "#endif\n"
1762 "\n"
1763 "#ifdef USEFOG\n"
1764 "       color.rgb = FogVertex(color.rgb);\n"
1765 "#endif\n"
1766 "\n"
1767 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1768 "#ifdef USEREFLECTION\n"
1769 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1770 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1771 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1772 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1773 "       // FIXME temporary hack to detect the case that the reflection\n"
1774 "       // gets blackened at edges due to leaving the area that contains actual\n"
1775 "       // content.\n"
1776 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1777 "       // 'appening.\n"
1778 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1779 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1780 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1781 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1782 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1783 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1784 "#endif\n"
1785 "\n"
1786 "       gl_FragColor = vec4(color);\n"
1787 "}\n"
1788 "#endif // FRAGMENT_SHADER\n"
1789 "\n"
1790 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1791 "#endif // !MODE_DEFERREDGEOMETRY\n"
1792 "#endif // !MODE_WATER\n"
1793 "#endif // !MODE_REFRACTION\n"
1794 "#endif // !MODE_BLOOMBLUR\n"
1795 "#endif // !MODE_GENERIC\n"
1796 "#endif // !MODE_POSTPROCESS\n"
1797 "#endif // !MODE_SHOWDEPTH\n"
1798 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1799 ;
1800
1801 /*
1802 =========================================================================================================================================================
1803
1804
1805
1806 =========================================================================================================================================================
1807
1808
1809
1810 =========================================================================================================================================================
1811
1812
1813
1814 =========================================================================================================================================================
1815
1816
1817
1818 =========================================================================================================================================================
1819
1820
1821
1822 =========================================================================================================================================================
1823
1824
1825
1826 =========================================================================================================================================================
1827 */
1828
1829 const char *builtincgshaderstring =
1830 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1831 "// written by Forest 'LordHavoc' Hale\n"
1832 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1833 "\n"
1834 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1835 "#if defined(USEREFLECTION)\n"
1836 "#undef USESHADOWMAPORTHO\n"
1837 "#endif\n"
1838 "\n"
1839 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1840 "# define USEFOG\n"
1841 "#endif\n"
1842 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1843 "#define USELIGHTMAP\n"
1844 "#endif\n"
1845 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1846 "#define USEEYEVECTOR\n"
1847 "#endif\n"
1848 "\n"
1849 "#ifdef FRAGMENT_SHADER\n"
1850 "#ifdef HLSL\n"
1851 "//#undef USESHADOWMAPPCF\n"
1852 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1853 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1854 "#else\n"
1855 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1856 "#endif\n"
1857 "#endif\n"
1858 "\n"
1859 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1860 "#ifdef VERTEX_SHADER\n"
1861 "void main\n"
1862 "(\n"
1863 "float4 gl_Vertex : POSITION,\n"
1864 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1865 "out float4 gl_Position : POSITION,\n"
1866 "out float Depth : TEXCOORD0\n"
1867 ")\n"
1868 "{\n"
1869 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1870 "       Depth = gl_Position.z;\n"
1871 "}\n"
1872 "#endif\n"
1873 "\n"
1874 "#ifdef FRAGMENT_SHADER\n"
1875 "void main\n"
1876 "(\n"
1877 "float Depth : TEXCOORD0,\n"
1878 "out float4 gl_FragColor : COLOR\n"
1879 ")\n"
1880 "{\n"
1881 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1882 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1883 "       temp.yz -= floor(temp.yz);\n"
1884 "       gl_FragColor = temp;\n"
1885 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1886 "}\n"
1887 "#endif\n"
1888 "#else // !MODE_DEPTH_ORSHADOW\n"
1889 "\n"
1890 "\n"
1891 "\n"
1892 "\n"
1893 "#ifdef MODE_SHOWDEPTH\n"
1894 "#ifdef VERTEX_SHADER\n"
1895 "void main\n"
1896 "(\n"
1897 "float4 gl_Vertex : POSITION,\n"
1898 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1899 "out float4 gl_Position : POSITION,\n"
1900 "out float4 gl_FrontColor : COLOR0\n"
1901 ")\n"
1902 "{\n"
1903 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1904 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1905 "}\n"
1906 "#endif\n"
1907 "\n"
1908 "#ifdef FRAGMENT_SHADER\n"
1909 "void main\n"
1910 "(\n"
1911 "float4 gl_FrontColor : COLOR0,\n"
1912 "out float4 gl_FragColor : COLOR\n"
1913 ")\n"
1914 "{\n"
1915 "       gl_FragColor = gl_FrontColor;\n"
1916 "}\n"
1917 "#endif\n"
1918 "#else // !MODE_SHOWDEPTH\n"
1919 "\n"
1920 "\n"
1921 "\n"
1922 "\n"
1923 "#ifdef MODE_POSTPROCESS\n"
1924 "\n"
1925 "#ifdef VERTEX_SHADER\n"
1926 "void main\n"
1927 "(\n"
1928 "float4 gl_Vertex : POSITION,\n"
1929 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1930 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1931 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1932 "out float4 gl_Position : POSITION,\n"
1933 "out float2 TexCoord1 : TEXCOORD0,\n"
1934 "out float2 TexCoord2 : TEXCOORD1\n"
1935 ")\n"
1936 "{\n"
1937 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1938 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1939 "#ifdef USEBLOOM\n"
1940 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1941 "#endif\n"
1942 "}\n"
1943 "#endif\n"
1944 "\n"
1945 "#ifdef FRAGMENT_SHADER\n"
1946 "void main\n"
1947 "(\n"
1948 "float2 TexCoord1 : TEXCOORD0,\n"
1949 "float2 TexCoord2 : TEXCOORD1,\n"
1950 "uniform sampler Texture_First : register(s0),\n"
1951 "#ifdef USEBLOOM\n"
1952 "uniform sampler Texture_Second : register(s1),\n"
1953 "#endif\n"
1954 "#ifdef USEGAMMARAMPS\n"
1955 "uniform sampler Texture_GammaRamps : register(s2),\n"
1956 "#endif\n"
1957 "#ifdef USESATURATION\n"
1958 "uniform float Saturation : register(c30),\n"
1959 "#endif\n"
1960 "#ifdef USEVIEWTINT\n"
1961 "uniform float4 ViewTintColor : register(c41),\n"
1962 "#endif\n"
1963 "uniform float4 UserVec1 : register(c37),\n"
1964 "uniform float4 UserVec2 : register(c38),\n"
1965 "uniform float4 UserVec3 : register(c39),\n"
1966 "uniform float4 UserVec4 : register(c40),\n"
1967 "uniform float ClientTime : register(c2),\n"
1968 "uniform float2 PixelSize : register(c25),\n"
1969 "uniform float4 BloomColorSubtract : register(c43),\n"
1970 "out float4 gl_FragColor : COLOR\n"
1971 ")\n"
1972 "{\n"
1973 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
1974 "#ifdef USEBLOOM\n"
1975 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
1976 "#endif\n"
1977 "#ifdef USEVIEWTINT\n"
1978 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
1979 "#endif\n"
1980 "\n"
1981 "#ifdef USEPOSTPROCESSING\n"
1982 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
1983 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
1984 "       float sobel = 1.0;\n"
1985 "       // float2 ts = textureSize(Texture_First, 0);\n"
1986 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
1987 "       float2 px = PixelSize;\n"
1988 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
1989 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
1990 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1991 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1992 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
1993 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1994 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
1995 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
1996 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
1997 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
1998 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
1999 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2000 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2001 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2002 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2003 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2004 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2005 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2006 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2007 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2008 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2009 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2010 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2011 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2012 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2013 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2014 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2015 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2016 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2017 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2018 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2019 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2020 "#endif\n"
2021 "\n"
2022 "#ifdef USESATURATION\n"
2023 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2024 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2025 "       // 'vampire sight' effect, wheres red is compensated\n"
2026 "       #ifdef SATURATION_REDCOMPENSATE\n"
2027 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2028 "               gl_FragColor.rgb = mix(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2029 "               gl_FragColor.r += r;\n"
2030 "       #else\n"
2031 "               // normal desaturation\n"
2032 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2033 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2034 "       #endif\n"
2035 "#endif\n"
2036 "\n"
2037 "#ifdef USEGAMMARAMPS\n"
2038 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2039 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2040 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2041 "#endif\n"
2042 "}\n"
2043 "#endif\n"
2044 "#else // !MODE_POSTPROCESS\n"
2045 "\n"
2046 "\n"
2047 "\n"
2048 "\n"
2049 "#ifdef MODE_GENERIC\n"
2050 "#ifdef VERTEX_SHADER\n"
2051 "void main\n"
2052 "(\n"
2053 "float4 gl_Vertex : POSITION,\n"
2054 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2055 "float4 gl_Color : COLOR0,\n"
2056 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2057 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2058 "out float4 gl_Position : POSITION,\n"
2059 "#ifdef USEDIFFUSE\n"
2060 "out float2 TexCoord1 : TEXCOORD0,\n"
2061 "#endif\n"
2062 "#ifdef USESPECULAR\n"
2063 "out float2 TexCoord2 : TEXCOORD1,\n"
2064 "#endif\n"
2065 "out float4 gl_FrontColor : COLOR\n"
2066 ")\n"
2067 "{\n"
2068 "#ifdef HLSL\n"
2069 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2070 "#else\n"
2071 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2072 "#endif\n"
2073 "#ifdef USEDIFFUSE\n"
2074 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2075 "#endif\n"
2076 "#ifdef USESPECULAR\n"
2077 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2078 "#endif\n"
2079 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2080 "}\n"
2081 "#endif\n"
2082 "\n"
2083 "#ifdef FRAGMENT_SHADER\n"
2084 "\n"
2085 "void main\n"
2086 "(\n"
2087 "float4 gl_FrontColor : COLOR0,\n"
2088 "float2 TexCoord1 : TEXCOORD0,\n"
2089 "float2 TexCoord2 : TEXCOORD1,\n"
2090 "#ifdef USEDIFFUSE\n"
2091 "uniform sampler Texture_First : register(s0),\n"
2092 "#endif\n"
2093 "#ifdef USESPECULAR\n"
2094 "uniform sampler Texture_Second : register(s1),\n"
2095 "#endif\n"
2096 "out float4 gl_FragColor : COLOR\n"
2097 ")\n"
2098 "{\n"
2099 "#ifdef USEVIEWTINT\n"
2100 "       gl_FragColor = gl_FrontColor;\n"
2101 "#else\n"
2102 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2103 "#endif\n"
2104 "#ifdef USEDIFFUSE\n"
2105 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2106 "#endif\n"
2107 "\n"
2108 "#ifdef USESPECULAR\n"
2109 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2110 "# ifdef USECOLORMAPPING\n"
2111 "       gl_FragColor *= tex2;\n"
2112 "# endif\n"
2113 "# ifdef USEGLOW\n"
2114 "       gl_FragColor += tex2;\n"
2115 "# endif\n"
2116 "# ifdef USEVERTEXTEXTUREBLEND\n"
2117 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2118 "# endif\n"
2119 "#endif\n"
2120 "}\n"
2121 "#endif\n"
2122 "#else // !MODE_GENERIC\n"
2123 "\n"
2124 "\n"
2125 "\n"
2126 "\n"
2127 "#ifdef MODE_BLOOMBLUR\n"
2128 "#ifdef VERTEX_SHADER\n"
2129 "void main\n"
2130 "(\n"
2131 "float4 gl_Vertex : POSITION,\n"
2132 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2133 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2134 "out float4 gl_Position : POSITION,\n"
2135 "out float2 TexCoord : TEXCOORD0\n"
2136 ")\n"
2137 "{\n"
2138 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2139 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2140 "}\n"
2141 "#endif\n"
2142 "\n"
2143 "#ifdef FRAGMENT_SHADER\n"
2144 "\n"
2145 "void main\n"
2146 "(\n"
2147 "float2 TexCoord : TEXCOORD0,\n"
2148 "uniform sampler Texture_First : register(s0),\n"
2149 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2150 "out float4 gl_FragColor : COLOR\n"
2151 ")\n"
2152 "{\n"
2153 "       int i;\n"
2154 "       float2 tc = TexCoord;\n"
2155 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2156 "       tc += BloomBlur_Parameters.xy;\n"
2157 "       for (i = 1;i < SAMPLES;i++)\n"
2158 "       {\n"
2159 "               color += tex2D(Texture_First, tc).rgb;\n"
2160 "               tc += BloomBlur_Parameters.xy;\n"
2161 "       }\n"
2162 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2163 "}\n"
2164 "#endif\n"
2165 "#else // !MODE_BLOOMBLUR\n"
2166 "#ifdef MODE_REFRACTION\n"
2167 "#ifdef VERTEX_SHADER\n"
2168 "void main\n"
2169 "(\n"
2170 "float4 gl_Vertex : POSITION,\n"
2171 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2172 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2173 "uniform float4x4 TexMatrix : register(c0),\n"
2174 "uniform float3 EyePosition : register(c24),\n"
2175 "out float4 gl_Position : POSITION,\n"
2176 "out float2 TexCoord : TEXCOORD0,\n"
2177 "out float3 EyeVector : TEXCOORD1,\n"
2178 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2179 ")\n"
2180 "{\n"
2181 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2182 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2183 "       ModelViewProjectionPosition = gl_Position;\n"
2184 "}\n"
2185 "#endif\n"
2186 "\n"
2187 "#ifdef FRAGMENT_SHADER\n"
2188 "void main\n"
2189 "(\n"
2190 "float2 TexCoord : TEXCOORD0,\n"
2191 "float3 EyeVector : TEXCOORD1,\n"
2192 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2193 "uniform sampler Texture_Normal : register(s0),\n"
2194 "uniform sampler Texture_Refraction : register(s3),\n"
2195 "uniform sampler Texture_Reflection : register(s7),\n"
2196 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2197 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2198 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2199 "uniform float4 RefractColor : register(c29),\n"
2200 "out float4 gl_FragColor : COLOR\n"
2201 ")\n"
2202 "{\n"
2203 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2204 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2205 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2206 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2207 "       // FIXME temporary hack to detect the case that the reflection\n"
2208 "       // gets blackened at edges due to leaving the area that contains actual\n"
2209 "       // content.\n"
2210 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2211 "       // 'appening.\n"
2212 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2213 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2214 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2215 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2216 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2217 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2218 "}\n"
2219 "#endif\n"
2220 "#else // !MODE_REFRACTION\n"
2221 "\n"
2222 "\n"
2223 "\n"
2224 "\n"
2225 "#ifdef MODE_WATER\n"
2226 "#ifdef VERTEX_SHADER\n"
2227 "\n"
2228 "void main\n"
2229 "(\n"
2230 "float4 gl_Vertex : POSITION,\n"
2231 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2232 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2233 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2234 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2235 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2236 "uniform float4x4 TexMatrix : register(c0),\n"
2237 "uniform float3 EyePosition : register(c24),\n"
2238 "out float4 gl_Position : POSITION,\n"
2239 "out float2 TexCoord : TEXCOORD0,\n"
2240 "out float3 EyeVector : TEXCOORD1,\n"
2241 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2242 ")\n"
2243 "{\n"
2244 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2245 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2246 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2247 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2248 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2249 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2250 "       ModelViewProjectionPosition = gl_Position;\n"
2251 "}\n"
2252 "#endif\n"
2253 "\n"
2254 "#ifdef FRAGMENT_SHADER\n"
2255 "void main\n"
2256 "(\n"
2257 "float2 TexCoord : TEXCOORD0,\n"
2258 "float3 EyeVector : TEXCOORD1,\n"
2259 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2260 "uniform sampler Texture_Normal : register(s0),\n"
2261 "uniform sampler Texture_Refraction : register(s3),\n"
2262 "uniform sampler Texture_Reflection : register(s7),\n"
2263 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2264 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2265 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2266 "uniform float4 RefractColor : register(c29),\n"
2267 "uniform float4 ReflectColor : register(c26),\n"
2268 "uniform float ReflectFactor : register(c27),\n"
2269 "uniform float ReflectOffset : register(c28),\n"
2270 "out float4 gl_FragColor : COLOR\n"
2271 ")\n"
2272 "{\n"
2273 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2274 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2275 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2276 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2277 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2278 "       // FIXME temporary hack to detect the case that the reflection\n"
2279 "       // gets blackened at edges due to leaving the area that contains actual\n"
2280 "       // content.\n"
2281 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2282 "       // 'appening.\n"
2283 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2284 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2285 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2286 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2287 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2288 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2289 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2290 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2291 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2292 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2293 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2294 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2295 "}\n"
2296 "#endif\n"
2297 "#else // !MODE_WATER\n"
2298 "\n"
2299 "\n"
2300 "\n"
2301 "\n"
2302 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2303 "\n"
2304 "// fragment shader specific:\n"
2305 "#ifdef FRAGMENT_SHADER\n"
2306 "\n"
2307 "#ifdef USEFOG\n"
2308 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2309 "{\n"
2310 "       float fogfrac;\n"
2311 "#ifdef USEFOGHEIGHTTEXTURE\n"
2312 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2313 "       fogfrac = fogheightpixel.a;\n"
2314 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2315 "#else\n"
2316 "# ifdef USEFOGOUTSIDE\n"
2317 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2318 "# else\n"
2319 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2320 "# endif\n"
2321 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2322 "#endif\n"
2323 "}\n"
2324 "#endif\n"
2325 "\n"
2326 "#ifdef USEOFFSETMAPPING\n"
2327 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2328 "{\n"
2329 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2330 "       // 14 sample relief mapping: linear search and then binary search\n"
2331 "       // this basically steps forward a small amount repeatedly until it finds\n"
2332 "       // itself inside solid, then jitters forward and back using decreasing\n"
2333 "       // amounts to find the impact\n"
2334 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2335 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2336 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2337 "       float3 RT = float3(TexCoord, 1);\n"
2338 "       OffsetVector *= 0.1;\n"
2339 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2340 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2341 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2342 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2343 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2344 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2345 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2346 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2347 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2348 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2349 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2350 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2351 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2352 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2353 "       return RT.xy;\n"
2354 "#else\n"
2355 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2356 "       // this basically moves forward the full distance, and then backs up based\n"
2357 "       // on height of samples\n"
2358 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2359 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2360 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2361 "       TexCoord += OffsetVector;\n"
2362 "       OffsetVector *= 0.333;\n"
2363 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2364 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2365 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2366 "       return TexCoord;\n"
2367 "#endif\n"
2368 "}\n"
2369 "#endif // USEOFFSETMAPPING\n"
2370 "\n"
2371 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2372 "#if defined(USESHADOWMAP2D)\n"
2373 "# ifdef USESHADOWMAPORTHO\n"
2374 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2375 "# else\n"
2376 "#  ifdef USESHADOWMAPVSDCT\n"
2377 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2378 "{\n"
2379 "       float3 adir = abs(dir);\n"
2380 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2381 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2382 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2383 "}\n"
2384 "#  else\n"
2385 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2386 "{\n"
2387 "       float3 adir = abs(dir);\n"
2388 "       float ma = adir.z;\n"
2389 "       float4 proj = float4(dir, 2.5);\n"
2390 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2391 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2392 "#ifdef HLSL\n"
2393 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2394 "#else\n"
2395 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2396 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2397 "#endif\n"
2398 "}\n"
2399 "#  endif\n"
2400 "# endif\n"
2401 "#endif // defined(USESHADOWMAP2D)\n"
2402 "\n"
2403 "# ifdef USESHADOWMAP2D\n"
2404 "#ifdef USESHADOWMAPVSDCT\n"
2405 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2406 "#else\n"
2407 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2408 "#endif\n"
2409 "{\n"
2410 "#ifdef USESHADOWMAPVSDCT\n"
2411 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2412 "#else\n"
2413 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2414 "#endif\n"
2415 "       float f;\n"
2416 "\n"
2417 "#  ifdef USESHADOWSAMPLER\n"
2418 "#    ifdef USESHADOWMAPPCF\n"
2419 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2420 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2421 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2422 "#    else\n"
2423 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2424 "#    endif\n"
2425 "#  else\n"
2426 "#    ifdef USESHADOWMAPPCF\n"
2427 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2428 "#      ifdef GL_ARB_texture_gather\n"
2429 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2430 "#      else\n"
2431 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2432 "#      endif\n"
2433 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2434 "#      if USESHADOWMAPPCF > 1\n"
2435 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2436 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2437 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2438 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2439 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2440 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2441 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2442 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2443 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2444 "       float4 locols = float4(group1.ab, group3.ab);\n"
2445 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2446 "       locols.yz += group2.ab;\n"
2447 "       hicols.yz += group8.rg;\n"
2448 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2449 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2450 "                               lerp(locols, hicols, offset.y);\n"
2451 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2452 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2453 "       f = dot(cols, float4(1.0/25.0));\n"
2454 "#      else\n"
2455 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2456 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2457 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2458 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2459 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2460 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2461 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2462 "#      endif\n"
2463 "#     else\n"
2464 "#      ifdef GL_EXT_gpu_shader4\n"
2465 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2466 "#      else\n"
2467 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2468 "#      endif\n"
2469 "#      if USESHADOWMAPPCF > 1\n"
2470 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2471 "       center *= ShadowMap_TextureScale;\n"
2472 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2473 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2474 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2475 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2476 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2477 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2478 "#      else\n"
2479 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2480 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2481 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2482 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2483 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2484 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2485 "#      endif\n"
2486 "#     endif\n"
2487 "#    else\n"
2488 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2489 "#    endif\n"
2490 "#  endif\n"
2491 "#  ifdef USESHADOWMAPORTHO\n"
2492 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2493 "#  else\n"
2494 "       return f;\n"
2495 "#  endif\n"
2496 "}\n"
2497 "# endif\n"
2498 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2499 "#endif // FRAGMENT_SHADER\n"
2500 "\n"
2501 "\n"
2502 "\n"
2503 "\n"
2504 "#ifdef MODE_DEFERREDGEOMETRY\n"
2505 "#ifdef VERTEX_SHADER\n"
2506 "void main\n"
2507 "(\n"
2508 "float4 gl_Vertex : POSITION,\n"
2509 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2510 "#ifdef USEVERTEXTEXTUREBLEND\n"
2511 "float4 gl_Color : COLOR0,\n"
2512 "#endif\n"
2513 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2514 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2515 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2516 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2517 "uniform float4x4 TexMatrix : register(c0),\n"
2518 "#ifdef USEVERTEXTEXTUREBLEND\n"
2519 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2520 "#endif\n"
2521 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2522 "#ifdef USEOFFSETMAPPING\n"
2523 "uniform float3 EyePosition : register(c24),\n"
2524 "#endif\n"
2525 "out float4 gl_Position : POSITION,\n"
2526 "#ifdef USEVERTEXTEXTUREBLEND\n"
2527 "out float4 gl_FrontColor : COLOR,\n"
2528 "#endif\n"
2529 "out float4 TexCoordBoth : TEXCOORD0,\n"
2530 "#ifdef USEOFFSETMAPPING\n"
2531 "out float3 EyeVector : TEXCOORD2,\n"
2532 "#endif\n"
2533 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2534 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2535 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2536 ")\n"
2537 "{\n"
2538 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2539 "#ifdef USEVERTEXTEXTUREBLEND\n"
2540 "#ifdef HLSL\n"
2541 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2542 "#else\n"
2543 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2544 "#endif\n"
2545 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2546 "#endif\n"
2547 "\n"
2548 "       // transform unnormalized eye direction into tangent space\n"
2549 "#ifdef USEOFFSETMAPPING\n"
2550 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2551 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2552 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2553 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2554 "#endif\n"
2555 "\n"
2556 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2557 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2558 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2559 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2560 "       VectorR.w = gl_Position.z;\n"
2561 "}\n"
2562 "#endif // VERTEX_SHADER\n"
2563 "\n"
2564 "#ifdef FRAGMENT_SHADER\n"
2565 "void main\n"
2566 "(\n"
2567 "float4 TexCoordBoth : TEXCOORD0,\n"
2568 "float3 EyeVector : TEXCOORD2,\n"
2569 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2570 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2571 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2572 "uniform sampler Texture_Normal : register(s0),\n"
2573 "#ifdef USEALPHAKILL\n"
2574 "uniform sampler Texture_Color : register(s1),\n"
2575 "#endif\n"
2576 "uniform sampler Texture_Gloss : register(s2),\n"
2577 "#ifdef USEVERTEXTEXTUREBLEND\n"
2578 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2579 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2580 "#endif\n"
2581 "#ifdef USEOFFSETMAPPING\n"
2582 "uniform float OffsetMapping_Scale : register(c24),\n"
2583 "#endif\n"
2584 "uniform half SpecularPower : register(c36),\n"
2585 "#ifdef HLSL\n"
2586 "out float4 gl_FragData0 : COLOR0,\n"
2587 "out float4 gl_FragData1 : COLOR1\n"
2588 "#else\n"
2589 "out float4 gl_FragColor : COLOR\n"
2590 "#endif\n"
2591 ")\n"
2592 "{\n"
2593 "       float2 TexCoord = TexCoordBoth.xy;\n"
2594 "#ifdef USEOFFSETMAPPING\n"
2595 "       // apply offsetmapping\n"
2596 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2597 "#define TexCoord TexCoordOffset\n"
2598 "#endif\n"
2599 "\n"
2600 "#ifdef USEALPHAKILL\n"
2601 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2602 "               discard;\n"
2603 "#endif\n"
2604 "\n"
2605 "#ifdef USEVERTEXTEXTUREBLEND\n"
2606 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2607 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2608 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2609 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2610 "#endif\n"
2611 "\n"
2612 "#ifdef USEVERTEXTEXTUREBLEND\n"
2613 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2614 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2615 "#else\n"
2616 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2617 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2618 "#endif\n"
2619 "\n"
2620 "#ifdef HLSL\n"
2621 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2622 "       float Depth = VectorR.w / 256.0;\n"
2623 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2624 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2625 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2626 "       gl_FragData1 = depthcolor;\n"
2627 "#else\n"
2628 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2629 "#endif\n"
2630 "}\n"
2631 "#endif // FRAGMENT_SHADER\n"
2632 "#else // !MODE_DEFERREDGEOMETRY\n"
2633 "\n"
2634 "\n"
2635 "\n"
2636 "\n"
2637 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2638 "#ifdef VERTEX_SHADER\n"
2639 "void main\n"
2640 "(\n"
2641 "float4 gl_Vertex : POSITION,\n"
2642 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2643 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2644 "out float4 gl_Position : POSITION,\n"
2645 "out float4 ModelViewPosition : TEXCOORD0\n"
2646 ")\n"
2647 "{\n"
2648 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2649 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2650 "}\n"
2651 "#endif // VERTEX_SHADER\n"
2652 "\n"
2653 "#ifdef FRAGMENT_SHADER\n"
2654 "void main\n"
2655 "(\n"
2656 "#ifdef HLSL\n"
2657 "float2 Pixel : VPOS,\n"
2658 "#else\n"
2659 "float2 Pixel : WPOS,\n"
2660 "#endif\n"
2661 "float4 ModelViewPosition : TEXCOORD0,\n"
2662 "uniform float4x4 ViewToLight : register(c44),\n"
2663 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2664 "uniform float3 LightPosition : register(c23),\n"
2665 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2666 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2667 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2668 "#ifdef USESPECULAR\n"
2669 "uniform half3 DeferredColor_Specular : register(c11),\n"
2670 "uniform half SpecularPower : register(c36),\n"
2671 "#endif\n"
2672 "uniform sampler Texture_Attenuation : register(s9),\n"
2673 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2674 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2675 "\n"
2676 "#ifdef USECUBEFILTER\n"
2677 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2678 "#endif\n"
2679 "\n"
2680 "#ifdef USESHADOWMAP2D\n"
2681 "# ifdef USESHADOWSAMPLER\n"
2682 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2683 "# else\n"
2684 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2685 "# endif\n"
2686 "#endif\n"
2687 "\n"
2688 "#ifdef USESHADOWMAPVSDCT\n"
2689 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2690 "#endif\n"
2691 "\n"
2692 "#if defined(USESHADOWMAP2D)\n"
2693 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2694 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2695 "#endif\n"
2696 "\n"
2697 "out float4 gl_FragData0 : COLOR0,\n"
2698 "out float4 gl_FragData1 : COLOR1\n"
2699 ")\n"
2700 "{\n"
2701 "       // calculate viewspace pixel position\n"
2702 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2703 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2704 "       float3 position;\n"
2705 "#ifdef HLSL\n"
2706 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2707 "#else\n"
2708 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2709 "#endif\n"
2710 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2711 "       // decode viewspace pixel normal\n"
2712 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2713 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2714 "       // surfacenormal = pixel normal in viewspace\n"
2715 "       // LightVector = pixel to light in viewspace\n"
2716 "       // CubeVector = position in lightspace\n"
2717 "       // eyevector = pixel to view in viewspace\n"
2718 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2719 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2720 "#ifdef USEDIFFUSE\n"
2721 "       // calculate diffuse shading\n"
2722 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2723 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2724 "#endif\n"
2725 "#ifdef USESPECULAR\n"
2726 "       // calculate directional shading\n"
2727 "       float3 eyevector = position * -1.0;\n"
2728 "#  ifdef USEEXACTSPECULARMATH\n"
2729 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2730 "#  else\n"
2731 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2732 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2733 "#  endif\n"
2734 "#endif\n"
2735 "\n"
2736 "#if defined(USESHADOWMAP2D)\n"
2737 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2738 "#ifdef USESHADOWMAPVSDCT\n"
2739 ", Texture_CubeProjection\n"
2740 "#endif\n"
2741 "       ));\n"
2742 "#endif\n"
2743 "\n"
2744 "#ifdef USEDIFFUSE\n"
2745 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2746 "#else\n"
2747 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2748 "#endif\n"
2749 "#ifdef USESPECULAR\n"
2750 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2751 "#else\n"
2752 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2753 "#endif\n"
2754 "\n"
2755 "# ifdef USECUBEFILTER\n"
2756 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2757 "       gl_FragData0.rgb *= cubecolor;\n"
2758 "       gl_FragData1.rgb *= cubecolor;\n"
2759 "# endif\n"
2760 "}\n"
2761 "#endif // FRAGMENT_SHADER\n"
2762 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2763 "\n"
2764 "\n"
2765 "\n"
2766 "\n"
2767 "#ifdef VERTEX_SHADER\n"
2768 "void main\n"
2769 "(\n"
2770 "float4 gl_Vertex : POSITION,\n"
2771 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2772 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2773 "float4 gl_Color : COLOR0,\n"
2774 "#endif\n"
2775 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2776 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2777 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2778 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2779 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2780 "\n"
2781 "uniform float3 EyePosition : register(c24),\n"
2782 "uniform float4x4 TexMatrix : register(c0),\n"
2783 "#ifdef USEVERTEXTEXTUREBLEND\n"
2784 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2785 "#endif\n"
2786 "#ifdef MODE_LIGHTSOURCE\n"
2787 "uniform float4x4 ModelToLight : register(c20),\n"
2788 "#endif\n"
2789 "#ifdef MODE_LIGHTSOURCE\n"
2790 "uniform float3 LightPosition : register(c27),\n"
2791 "#endif\n"
2792 "#ifdef MODE_LIGHTDIRECTION\n"
2793 "uniform float3 LightDir : register(c26),\n"
2794 "#endif\n"
2795 "uniform float4 FogPlane : register(c25),\n"
2796 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2797 "uniform float3 LightPosition : register(c27),\n"
2798 "#endif\n"
2799 "#ifdef USESHADOWMAPORTHO\n"
2800 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2801 "#endif\n"
2802 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2803 "out float4 gl_FrontColor : COLOR,\n"
2804 "#endif\n"
2805 "out float4 TexCoordBoth : TEXCOORD0,\n"
2806 "#ifdef USELIGHTMAP\n"
2807 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2808 "#endif\n"
2809 "#ifdef USEEYEVECTOR\n"
2810 "out float3 EyeVector : TEXCOORD2,\n"
2811 "#endif\n"
2812 "#ifdef USEREFLECTION\n"
2813 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2814 "#endif\n"
2815 "#ifdef USEFOG\n"
2816 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2817 "#endif\n"
2818 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2819 "out float3 LightVector : TEXCOORD1,\n"
2820 "#endif\n"
2821 "#ifdef MODE_LIGHTSOURCE\n"
2822 "out float3 CubeVector : TEXCOORD3,\n"
2823 "#endif\n"
2824 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2825 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2826 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2827 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2828 "#endif\n"
2829 "#ifdef USESHADOWMAPORTHO\n"
2830 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2831 "#endif\n"
2832 "out float4 gl_Position : POSITION\n"
2833 ")\n"
2834 "{\n"
2835 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2836 "#ifdef HLSL\n"
2837 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2838 "#else\n"
2839 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2840 "#endif\n"
2841 "#endif\n"
2842 "       // copy the surface texcoord\n"
2843 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2844 "#ifdef USEVERTEXTEXTUREBLEND\n"
2845 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2846 "#endif\n"
2847 "#ifdef USELIGHTMAP\n"
2848 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2849 "#endif\n"
2850 "\n"
2851 "#ifdef MODE_LIGHTSOURCE\n"
2852 "       // transform vertex position into light attenuation/cubemap space\n"
2853 "       // (-1 to +1 across the light box)\n"
2854 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2855 "\n"
2856 "# ifdef USEDIFFUSE\n"
2857 "       // transform unnormalized light direction into tangent space\n"
2858 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2859 "       //  normalize it per pixel)\n"
2860 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2861 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2862 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2863 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2864 "# endif\n"
2865 "#endif\n"
2866 "\n"
2867 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2868 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2869 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2870 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2871 "#endif\n"
2872 "\n"
2873 "       // transform unnormalized eye direction into tangent space\n"
2874 "#ifdef USEEYEVECTOR\n"
2875 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2876 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2877 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2878 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2879 "#endif\n"
2880 "\n"
2881 "#ifdef USEFOG\n"
2882 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2883 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2884 "#endif\n"
2885 "\n"
2886 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2887 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2888 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2889 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2890 "#endif\n"
2891 "\n"
2892 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2893 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2894 "\n"
2895 "#ifdef USESHADOWMAPORTHO\n"
2896 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2897 "#endif\n"
2898 "\n"
2899 "#ifdef USEREFLECTION\n"
2900 "       ModelViewProjectionPosition = gl_Position;\n"
2901 "#endif\n"
2902 "}\n"
2903 "#endif // VERTEX_SHADER\n"
2904 "\n"
2905 "\n"
2906 "\n"
2907 "\n"
2908 "#ifdef FRAGMENT_SHADER\n"
2909 "void main\n"
2910 "(\n"
2911 "#ifdef USEDEFERREDLIGHTMAP\n"
2912 "#ifdef HLSL\n"
2913 "float2 Pixel : VPOS,\n"
2914 "#else\n"
2915 "float2 Pixel : WPOS,\n"
2916 "#endif\n"
2917 "#endif\n"
2918 "float4 gl_FrontColor : COLOR,\n"
2919 "float4 TexCoordBoth : TEXCOORD0,\n"
2920 "#ifdef USELIGHTMAP\n"
2921 "float2 TexCoordLightmap : TEXCOORD1,\n"
2922 "#endif\n"
2923 "#ifdef USEEYEVECTOR\n"
2924 "float3 EyeVector : TEXCOORD2,\n"
2925 "#endif\n"
2926 "#ifdef USEREFLECTION\n"
2927 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2928 "#endif\n"
2929 "#ifdef USEFOG\n"
2930 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2931 "#endif\n"
2932 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2933 "float3 LightVector : TEXCOORD1,\n"
2934 "#endif\n"
2935 "#ifdef MODE_LIGHTSOURCE\n"
2936 "float3 CubeVector : TEXCOORD3,\n"
2937 "#endif\n"
2938 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2939 "float4 ModelViewPosition : TEXCOORD0,\n"
2940 "#endif\n"
2941 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2942 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2943 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2944 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2945 "#endif\n"
2946 "#ifdef USESHADOWMAPORTHO\n"
2947 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2948 "#endif\n"
2949 "\n"
2950 "uniform sampler Texture_Normal : register(s0),\n"
2951 "uniform sampler Texture_Color : register(s1),\n"
2952 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2953 "uniform sampler Texture_Gloss : register(s2),\n"
2954 "#endif\n"
2955 "#ifdef USEGLOW\n"
2956 "uniform sampler Texture_Glow : register(s3),\n"
2957 "#endif\n"
2958 "#ifdef USEVERTEXTEXTUREBLEND\n"
2959 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2960 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2961 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2962 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2963 "#endif\n"
2964 "#ifdef USEGLOW\n"
2965 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
2966 "#endif\n"
2967 "#endif\n"
2968 "#ifdef USECOLORMAPPING\n"
2969 "uniform sampler Texture_Pants : register(s4),\n"
2970 "uniform sampler Texture_Shirt : register(s7),\n"
2971 "#endif\n"
2972 "#ifdef USEFOG\n"
2973 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
2974 "uniform sampler Texture_FogMask : register(s8),\n"
2975 "#endif\n"
2976 "#ifdef USELIGHTMAP\n"
2977 "uniform sampler Texture_Lightmap : register(s9),\n"
2978 "#endif\n"
2979 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
2980 "uniform sampler Texture_Deluxemap : register(s10),\n"
2981 "#endif\n"
2982 "#ifdef USEREFLECTION\n"
2983 "uniform sampler Texture_Reflection : register(s7),\n"
2984 "#endif\n"
2985 "\n"
2986 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2987 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2988 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2989 "#endif\n"
2990 "#ifdef USEDEFERREDLIGHTMAP\n"
2991 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2992 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2993 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
2994 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
2995 "#endif\n"
2996 "\n"
2997 "#ifdef USECOLORMAPPING\n"
2998 "uniform half3 Color_Pants : register(c7),\n"
2999 "uniform half3 Color_Shirt : register(c8),\n"
3000 "#endif\n"
3001 "#ifdef USEFOG\n"
3002 "uniform float3 FogColor : register(c16),\n"
3003 "uniform float FogRangeRecip : register(c20),\n"
3004 "uniform float FogPlaneViewDist : register(c19),\n"
3005 "uniform float FogHeightFade : register(c17),\n"
3006 "#endif\n"
3007 "\n"
3008 "#ifdef USEOFFSETMAPPING\n"
3009 "uniform float OffsetMapping_Scale : register(c24),\n"
3010 "#endif\n"
3011 "\n"
3012 "#ifdef USEDEFERREDLIGHTMAP\n"
3013 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3014 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3015 "uniform half3 DeferredMod_Specular : register(c13),\n"
3016 "#endif\n"
3017 "uniform half3 Color_Ambient : register(c3),\n"
3018 "uniform half3 Color_Diffuse : register(c4),\n"
3019 "uniform half3 Color_Specular : register(c5),\n"
3020 "uniform half SpecularPower : register(c36),\n"
3021 "#ifdef USEGLOW\n"
3022 "uniform half3 Color_Glow : register(c6),\n"
3023 "#endif\n"
3024 "uniform half Alpha : register(c0),\n"
3025 "#ifdef USEREFLECTION\n"
3026 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3027 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3028 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3029 "uniform half4 ReflectColor : register(c26),\n"
3030 "#endif\n"
3031 "#ifdef USEREFLECTCUBE\n"
3032 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3033 "uniform sampler Texture_ReflectMask : register(s5),\n"
3034 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3035 "#endif\n"
3036 "#ifdef MODE_LIGHTDIRECTION\n"
3037 "uniform half3 LightColor : register(c21),\n"
3038 "#endif\n"
3039 "#ifdef MODE_LIGHTSOURCE\n"
3040 "uniform half3 LightColor : register(c21),\n"
3041 "#endif\n"
3042 "\n"
3043 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3044 "uniform sampler Texture_Attenuation : register(s9),\n"
3045 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3046 "#endif\n"
3047 "\n"
3048 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3049 "\n"
3050 "#ifdef USESHADOWMAP2D\n"
3051 "# ifdef USESHADOWSAMPLER\n"
3052 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3053 "# else\n"
3054 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3055 "# endif\n"
3056 "#endif\n"
3057 "\n"
3058 "#ifdef USESHADOWMAPVSDCT\n"
3059 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3060 "#endif\n"
3061 "\n"
3062 "#if defined(USESHADOWMAP2D)\n"
3063 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3064 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3065 "#endif\n"
3066 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3067 "\n"
3068 "out float4 gl_FragColor : COLOR\n"
3069 ")\n"
3070 "{\n"
3071 "       float2 TexCoord = TexCoordBoth.xy;\n"
3072 "#ifdef USEVERTEXTEXTUREBLEND\n"
3073 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3074 "#endif\n"
3075 "#ifdef USEOFFSETMAPPING\n"
3076 "       // apply offsetmapping\n"
3077 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3078 "#define TexCoord TexCoordOffset\n"
3079 "#endif\n"
3080 "\n"
3081 "       // combine the diffuse textures (base, pants, shirt)\n"
3082 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3083 "#ifdef USEALPHAKILL\n"
3084 "       if (color.a < 0.5)\n"
3085 "               discard;\n"
3086 "#endif\n"
3087 "       color.a *= Alpha;\n"
3088 "#ifdef USECOLORMAPPING\n"
3089 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3090 "#endif\n"
3091 "#ifdef USEVERTEXTEXTUREBLEND\n"
3092 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3093 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3094 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3095 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3096 "       color.a = 1.0;\n"
3097 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3098 "#endif\n"
3099 "\n"
3100 "       // get the surface normal\n"
3101 "#ifdef USEVERTEXTEXTUREBLEND\n"
3102 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3103 "#else\n"
3104 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3105 "#endif\n"
3106 "\n"
3107 "       // get the material colors\n"
3108 "       half3 diffusetex = color.rgb;\n"
3109 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3110 "# ifdef USEVERTEXTEXTUREBLEND\n"
3111 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3112 "# else\n"
3113 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3114 "# endif\n"
3115 "#endif\n"
3116 "\n"
3117 "#ifdef USEREFLECTCUBE\n"
3118 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3119 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3120 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3121 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3122 "#endif\n"
3123 "\n"
3124 "\n"
3125 "\n"
3126 "\n"
3127 "#ifdef MODE_LIGHTSOURCE\n"
3128 "       // light source\n"
3129 "#ifdef USEDIFFUSE\n"
3130 "       half3 lightnormal = half3(normalize(LightVector));\n"
3131 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3132 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3133 "#ifdef USESPECULAR\n"
3134 "#ifdef USEEXACTSPECULARMATH\n"
3135 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3136 "#else\n"
3137 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3138 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3139 "#endif\n"
3140 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3141 "#endif\n"
3142 "#else\n"
3143 "       color.rgb = diffusetex * Color_Ambient;\n"
3144 "#endif\n"
3145 "       color.rgb *= LightColor;\n"
3146 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3147 "#if defined(USESHADOWMAP2D)\n"
3148 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3149 "#ifdef USESHADOWMAPVSDCT\n"
3150 ", Texture_CubeProjection\n"
3151 "#endif\n"
3152 "       ));\n"
3153 "\n"
3154 "#endif\n"
3155 "# ifdef USECUBEFILTER\n"
3156 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3157 "# endif\n"
3158 "\n"
3159 "#ifdef USESHADOWMAP2D\n"
3160 "#ifdef USESHADOWMAPVSDCT\n"
3161 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3162 "#else\n"
3163 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3164 "#endif\n"
3165 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3166 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3167 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3168 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3169 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3170 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3171 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3172 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3173 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3174 "//     color.r = half(shadowmaptc.z);\n"
3175 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3176 "//     color.r = half(shadowmaptc.z);\n"
3177 "//     color.r = 1;\n"
3178 "//     color.rgb = abs(CubeVector);\n"
3179 "#endif\n"
3180 "//     color.rgb = half3(1,1,1);\n"
3181 "#endif // MODE_LIGHTSOURCE\n"
3182 "\n"
3183 "\n"
3184 "\n"
3185 "\n"
3186 "#ifdef MODE_LIGHTDIRECTION\n"
3187 "#define SHADING\n"
3188 "#ifdef USEDIFFUSE\n"
3189 "       half3 lightnormal = half3(normalize(LightVector));\n"
3190 "#endif\n"
3191 "#define lightcolor LightColor\n"
3192 "#endif // MODE_LIGHTDIRECTION\n"
3193 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3194 "#define SHADING\n"
3195 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3196 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3197 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3198 "       // convert modelspace light vector to tangentspace\n"
3199 "       half3 lightnormal;\n"
3200 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3201 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3202 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3203 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3204 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3205 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3206 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3207 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3208 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3209 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3210 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3211 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3212 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3213 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3214 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3215 "#define SHADING\n"
3216 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3217 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3218 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3219 "#endif\n"
3220 "\n"
3221 "\n"
3222 "\n"
3223 "\n"
3224 "#ifdef MODE_FAKELIGHT\n"
3225 "#define SHADING\n"
3226 "half3 lightnormal = half3(normalize(EyeVector));\n"
3227 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3228 "#endif // MODE_FAKELIGHT\n"
3229 "\n"
3230 "\n"
3231 "\n"
3232 "\n"
3233 "#ifdef MODE_LIGHTMAP\n"
3234 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3235 "#endif // MODE_LIGHTMAP\n"
3236 "#ifdef MODE_VERTEXCOLOR\n"
3237 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3238 "#endif // MODE_VERTEXCOLOR\n"
3239 "#ifdef MODE_FLATCOLOR\n"
3240 "       color.rgb = diffusetex * Color_Ambient;\n"
3241 "#endif // MODE_FLATCOLOR\n"
3242 "\n"
3243 "\n"
3244 "\n"
3245 "\n"
3246 "#ifdef SHADING\n"
3247 "# ifdef USEDIFFUSE\n"
3248 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3249 "#  ifdef USESPECULAR\n"
3250 "#   ifdef USEEXACTSPECULARMATH\n"
3251 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3252 "#   else\n"
3253 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3254 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3255 "#   endif\n"
3256 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3257 "#  else\n"
3258 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3259 "#  endif\n"
3260 "# else\n"
3261 "       color.rgb = diffusetex * Color_Ambient;\n"
3262 "# endif\n"
3263 "#endif\n"
3264 "\n"
3265 "#ifdef USESHADOWMAPORTHO\n"
3266 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3267 "#endif\n"
3268 "\n"
3269 "#ifdef USEDEFERREDLIGHTMAP\n"
3270 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3271 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3272 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3273 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3274 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3275 "#endif\n"
3276 "\n"
3277 "#ifdef USEGLOW\n"
3278 "#ifdef USEVERTEXTEXTUREBLEND\n"
3279 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3280 "#else\n"
3281 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3282 "#endif\n"
3283 "#endif\n"
3284 "\n"
3285 "#ifdef USEFOG\n"
3286 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3287 "#endif\n"
3288 "\n"
3289 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3290 "#ifdef USEREFLECTION\n"
3291 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3292 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3293 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3294 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3295 "       // FIXME temporary hack to detect the case that the reflection\n"
3296 "       // gets blackened at edges due to leaving the area that contains actual\n"
3297 "       // content.\n"
3298 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3299 "       // 'appening.\n"
3300 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3301 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3302 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3303 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3304 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3305 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3306 "#endif\n"
3307 "\n"
3308 "       gl_FragColor = float4(color);\n"
3309 "}\n"
3310 "#endif // FRAGMENT_SHADER\n"
3311 "\n"
3312 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3313 "#endif // !MODE_DEFERREDGEOMETRY\n"
3314 "#endif // !MODE_WATER\n"
3315 "#endif // !MODE_REFRACTION\n"
3316 "#endif // !MODE_BLOOMBLUR\n"
3317 "#endif // !MODE_GENERIC\n"
3318 "#endif // !MODE_POSTPROCESS\n"
3319 "#endif // !MODE_SHOWDEPTH\n"
3320 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3321 ;
3322
3323 char *glslshaderstring = NULL;
3324 char *cgshaderstring = NULL;
3325 char *hlslshaderstring = NULL;
3326
3327 //=======================================================================================================================================================
3328
3329 typedef struct shaderpermutationinfo_s
3330 {
3331         const char *pretext;
3332         const char *name;
3333 }
3334 shaderpermutationinfo_t;
3335
3336 typedef struct shadermodeinfo_s
3337 {
3338         const char *vertexfilename;
3339         const char *geometryfilename;
3340         const char *fragmentfilename;
3341         const char *pretext;
3342         const char *name;
3343 }
3344 shadermodeinfo_t;
3345
3346 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3347 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3348 {
3349         {"#define USEDIFFUSE\n", " diffuse"},
3350         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3351         {"#define USEVIEWTINT\n", " viewtint"},
3352         {"#define USECOLORMAPPING\n", " colormapping"},
3353         {"#define USESATURATION\n", " saturation"},
3354         {"#define USEFOGINSIDE\n", " foginside"},
3355         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3356         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3357         {"#define USEGAMMARAMPS\n", " gammaramps"},
3358         {"#define USECUBEFILTER\n", " cubefilter"},
3359         {"#define USEGLOW\n", " glow"},
3360         {"#define USEBLOOM\n", " bloom"},
3361         {"#define USESPECULAR\n", " specular"},
3362         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3363         {"#define USEREFLECTION\n", " reflection"},
3364         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3365         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3366         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3367         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3368         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3369         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3370         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3371         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3372         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3373         {"#define USEALPHAKILL\n", " alphakill"},
3374         {"#define USEREFLECTCUBE\n", " reflectcube"},
3375         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3376 };
3377
3378 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3379 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3380 {
3381         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3382         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3383         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3384         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3385         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3386         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3387         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3388         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3389         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3390         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3391         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3392         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3393         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3394         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3395         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3396         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3397 };
3398
3399 #ifdef SUPPORTCG
3400 shadermodeinfo_t cgshadermodeinfo[SHADERMODE_COUNT] =
3401 {
3402         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_GENERIC\n", " generic"},
3403         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_POSTPROCESS\n", " postprocess"},
3404         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3405         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FLATCOLOR\n", " flatcolor"},
3406         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3407         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTMAP\n", " lightmap"},
3408         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_FAKELIGHT\n", " fakelight"},
3409         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3410         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3411         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3412         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3413         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_REFRACTION\n", " refraction"},
3414         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_WATER\n", " water"},
3415         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_SHOWDEPTH\n", " showdepth"},
3416         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3417         {"cg/default.cg", NULL, "cg/default.cg", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3418 };
3419 #endif
3420
3421 #ifdef SUPPORTD3D
3422 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3423 {
3424         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3425         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3426         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3427         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3428         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3429         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3430         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3431         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3432         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3433         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3434         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3435         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3436         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3437         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3438         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3439         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3440 };
3441 #endif
3442
3443 struct r_glsl_permutation_s;
3444 typedef struct r_glsl_permutation_s
3445 {
3446         /// hash lookup data
3447         struct r_glsl_permutation_s *hashnext;
3448         unsigned int mode;
3449         unsigned int permutation;
3450
3451         /// indicates if we have tried compiling this permutation already
3452         qboolean compiled;
3453         /// 0 if compilation failed
3454         int program;
3455         /// locations of detected uniforms in program object, or -1 if not found
3456         int loc_Texture_First;
3457         int loc_Texture_Second;
3458         int loc_Texture_GammaRamps;
3459         int loc_Texture_Normal;
3460         int loc_Texture_Color;
3461         int loc_Texture_Gloss;
3462         int loc_Texture_Glow;
3463         int loc_Texture_SecondaryNormal;
3464         int loc_Texture_SecondaryColor;
3465         int loc_Texture_SecondaryGloss;
3466         int loc_Texture_SecondaryGlow;
3467         int loc_Texture_Pants;
3468         int loc_Texture_Shirt;
3469         int loc_Texture_FogHeightTexture;
3470         int loc_Texture_FogMask;
3471         int loc_Texture_Lightmap;
3472         int loc_Texture_Deluxemap;
3473         int loc_Texture_Attenuation;
3474         int loc_Texture_Cube;
3475         int loc_Texture_Refraction;
3476         int loc_Texture_Reflection;
3477         int loc_Texture_ShadowMap2D;
3478         int loc_Texture_CubeProjection;
3479         int loc_Texture_ScreenDepth;
3480         int loc_Texture_ScreenNormalMap;
3481         int loc_Texture_ScreenDiffuse;
3482         int loc_Texture_ScreenSpecular;
3483         int loc_Texture_ReflectMask;
3484         int loc_Texture_ReflectCube;
3485         int loc_Alpha;
3486         int loc_BloomBlur_Parameters;
3487         int loc_ClientTime;
3488         int loc_Color_Ambient;
3489         int loc_Color_Diffuse;
3490         int loc_Color_Specular;
3491         int loc_Color_Glow;
3492         int loc_Color_Pants;
3493         int loc_Color_Shirt;
3494         int loc_DeferredColor_Ambient;
3495         int loc_DeferredColor_Diffuse;
3496         int loc_DeferredColor_Specular;
3497         int loc_DeferredMod_Diffuse;
3498         int loc_DeferredMod_Specular;
3499         int loc_DistortScaleRefractReflect;
3500         int loc_EyePosition;
3501         int loc_FogColor;
3502         int loc_FogHeightFade;
3503         int loc_FogPlane;
3504         int loc_FogPlaneViewDist;
3505         int loc_FogRangeRecip;
3506         int loc_LightColor;
3507         int loc_LightDir;
3508         int loc_LightPosition;
3509         int loc_OffsetMapping_Scale;
3510         int loc_PixelSize;
3511         int loc_ReflectColor;
3512         int loc_ReflectFactor;
3513         int loc_ReflectOffset;
3514         int loc_RefractColor;
3515         int loc_Saturation;
3516         int loc_ScreenCenterRefractReflect;
3517         int loc_ScreenScaleRefractReflect;
3518         int loc_ScreenToDepth;
3519         int loc_ShadowMap_Parameters;
3520         int loc_ShadowMap_TextureScale;
3521         int loc_SpecularPower;
3522         int loc_UserVec1;
3523         int loc_UserVec2;
3524         int loc_UserVec3;
3525         int loc_UserVec4;
3526         int loc_ViewTintColor;
3527         int loc_ViewToLight;
3528         int loc_ModelToLight;
3529         int loc_TexMatrix;
3530         int loc_BackgroundTexMatrix;
3531         int loc_ModelViewProjectionMatrix;
3532         int loc_ModelViewMatrix;
3533         int loc_PixelToScreenTexCoord;
3534         int loc_ModelToReflectCube;
3535         int loc_ShadowMapMatrix;
3536         int loc_BloomColorSubtract;
3537         int loc_NormalmapScrollBlend;
3538 }
3539 r_glsl_permutation_t;
3540
3541 #define SHADERPERMUTATION_HASHSIZE 256
3542
3543
3544 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3545 // these can NOT degrade! only use for simple stuff
3546 enum
3547 {
3548         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3549         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3550         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3551         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3552         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3553         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3554 };
3555 #define SHADERSTATICPARMS_COUNT 6
3556
3557 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3558 static int shaderstaticparms_count = 0;
3559
3560 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3561 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3562 qboolean R_CompileShader_CheckStaticParms(void)
3563 {
3564         static int r_compileshader_staticparms_save[1];
3565         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3566         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3567
3568         // detect all
3569         if (r_glsl_saturation_redcompensate.integer)
3570                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3571         if (r_shadow_glossexact.integer)
3572                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3573         if (r_glsl_postprocess.integer)
3574         {
3575                 if (r_glsl_postprocess_uservec1_enable.integer)
3576                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3577                 if (r_glsl_postprocess_uservec2_enable.integer)
3578                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3579                 if (r_glsl_postprocess_uservec3_enable.integer)
3580                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3581                 if (r_glsl_postprocess_uservec4_enable.integer)
3582                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3583         }
3584         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3585 }
3586
3587 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3588         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3589                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3590         else \
3591                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3592 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3593 {
3594         shaderstaticparms_count = 0;
3595
3596         // emit all
3597         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3598         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3599         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3600         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3601         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3602         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3603 }
3604
3605 /// information about each possible shader permutation
3606 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3607 /// currently selected permutation
3608 r_glsl_permutation_t *r_glsl_permutation;
3609 /// storage for permutations linked in the hash table
3610 memexpandablearray_t r_glsl_permutationarray;
3611
3612 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3613 {
3614         //unsigned int hashdepth = 0;
3615         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3616         r_glsl_permutation_t *p;
3617         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3618         {
3619                 if (p->mode == mode && p->permutation == permutation)
3620                 {
3621                         //if (hashdepth > 10)
3622                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3623                         return p;
3624                 }
3625                 //hashdepth++;
3626         }
3627         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3628         p->mode = mode;
3629         p->permutation = permutation;
3630         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3631         r_glsl_permutationhash[mode][hashindex] = p;
3632         //if (hashdepth > 10)
3633         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3634         return p;
3635 }
3636
3637 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3638 {
3639         char *shaderstring;
3640         if (!filename || !filename[0])
3641                 return NULL;
3642         if (!strcmp(filename, "glsl/default.glsl"))
3643         {
3644                 if (!glslshaderstring)
3645                 {
3646                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3647                         if (glslshaderstring)
3648                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3649                         else
3650                                 glslshaderstring = (char *)builtinshaderstring;
3651                 }
3652                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3653                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3654                 return shaderstring;
3655         }
3656         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3657         if (shaderstring)
3658         {
3659                 if (printfromdisknotice)
3660                         Con_DPrintf("from disk %s... ", filename);
3661                 return shaderstring;
3662         }
3663         return shaderstring;
3664 }
3665
3666 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3667 {
3668         int i;
3669         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3670         char *vertexstring, *geometrystring, *fragmentstring;
3671         char permutationname[256];
3672         int vertstrings_count = 0;
3673         int geomstrings_count = 0;
3674         int fragstrings_count = 0;
3675         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3676         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3677         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3678
3679         if (p->compiled)
3680                 return;
3681         p->compiled = true;
3682         p->program = 0;
3683
3684         permutationname[0] = 0;
3685         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3686         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3687         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3688
3689         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3690
3691         // the first pretext is which type of shader to compile as
3692         // (later these will all be bound together as a program object)
3693         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3694         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3695         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3696
3697         // the second pretext is the mode (for example a light source)
3698         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3699         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3700         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3701         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3702
3703         // now add all the permutation pretexts
3704         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3705         {
3706                 if (permutation & (1<<i))
3707                 {
3708                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3709                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3710                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3711                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3712                 }
3713                 else
3714                 {
3715                         // keep line numbers correct
3716                         vertstrings_list[vertstrings_count++] = "\n";
3717                         geomstrings_list[geomstrings_count++] = "\n";
3718                         fragstrings_list[fragstrings_count++] = "\n";
3719                 }
3720         }
3721
3722         // add static parms
3723         R_CompileShader_AddStaticParms(mode, permutation);
3724         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3725         vertstrings_count += shaderstaticparms_count;
3726         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3727         geomstrings_count += shaderstaticparms_count;
3728         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3729         fragstrings_count += shaderstaticparms_count;
3730
3731         // now append the shader text itself
3732         vertstrings_list[vertstrings_count++] = vertexstring;
3733         geomstrings_list[geomstrings_count++] = geometrystring;
3734         fragstrings_list[fragstrings_count++] = fragmentstring;
3735
3736         // if any sources were NULL, clear the respective list
3737         if (!vertexstring)
3738                 vertstrings_count = 0;
3739         if (!geometrystring)
3740                 geomstrings_count = 0;
3741         if (!fragmentstring)
3742                 fragstrings_count = 0;
3743
3744         // compile the shader program
3745         if (vertstrings_count + geomstrings_count + fragstrings_count)
3746                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3747         if (p->program)
3748         {
3749                 CHECKGLERROR
3750                 qglUseProgramObjectARB(p->program);CHECKGLERROR
3751                 // look up all the uniform variable names we care about, so we don't
3752                 // have to look them up every time we set them
3753
3754                 p->loc_Texture_First              = qglGetUniformLocationARB(p->program, "Texture_First");
3755                 p->loc_Texture_Second             = qglGetUniformLocationARB(p->program, "Texture_Second");
3756                 p->loc_Texture_GammaRamps         = qglGetUniformLocationARB(p->program, "Texture_GammaRamps");
3757                 p->loc_Texture_Normal             = qglGetUniformLocationARB(p->program, "Texture_Normal");
3758                 p->loc_Texture_Color              = qglGetUniformLocationARB(p->program, "Texture_Color");
3759                 p->loc_Texture_Gloss              = qglGetUniformLocationARB(p->program, "Texture_Gloss");
3760                 p->loc_Texture_Glow               = qglGetUniformLocationARB(p->program, "Texture_Glow");
3761                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocationARB(p->program, "Texture_SecondaryNormal");
3762                 p->loc_Texture_SecondaryColor     = qglGetUniformLocationARB(p->program, "Texture_SecondaryColor");
3763                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocationARB(p->program, "Texture_SecondaryGloss");
3764                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocationARB(p->program, "Texture_SecondaryGlow");
3765                 p->loc_Texture_Pants              = qglGetUniformLocationARB(p->program, "Texture_Pants");
3766                 p->loc_Texture_Shirt              = qglGetUniformLocationARB(p->program, "Texture_Shirt");
3767                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocationARB(p->program, "Texture_FogHeightTexture");
3768                 p->loc_Texture_FogMask            = qglGetUniformLocationARB(p->program, "Texture_FogMask");
3769                 p->loc_Texture_Lightmap           = qglGetUniformLocationARB(p->program, "Texture_Lightmap");
3770                 p->loc_Texture_Deluxemap          = qglGetUniformLocationARB(p->program, "Texture_Deluxemap");
3771                 p->loc_Texture_Attenuation        = qglGetUniformLocationARB(p->program, "Texture_Attenuation");
3772                 p->loc_Texture_Cube               = qglGetUniformLocationARB(p->program, "Texture_Cube");
3773                 p->loc_Texture_Refraction         = qglGetUniformLocationARB(p->program, "Texture_Refraction");
3774                 p->loc_Texture_Reflection         = qglGetUniformLocationARB(p->program, "Texture_Reflection");
3775                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocationARB(p->program, "Texture_ShadowMap2D");
3776                 p->loc_Texture_CubeProjection     = qglGetUniformLocationARB(p->program, "Texture_CubeProjection");
3777                 p->loc_Texture_ScreenDepth        = qglGetUniformLocationARB(p->program, "Texture_ScreenDepth");
3778                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocationARB(p->program, "Texture_ScreenNormalMap");
3779                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocationARB(p->program, "Texture_ScreenDiffuse");
3780                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocationARB(p->program, "Texture_ScreenSpecular");
3781                 p->loc_Texture_ReflectMask        = qglGetUniformLocationARB(p->program, "Texture_ReflectMask");
3782                 p->loc_Texture_ReflectCube        = qglGetUniformLocationARB(p->program, "Texture_ReflectCube");
3783                 p->loc_Alpha                      = qglGetUniformLocationARB(p->program, "Alpha");
3784                 p->loc_BloomBlur_Parameters       = qglGetUniformLocationARB(p->program, "BloomBlur_Parameters");
3785                 p->loc_ClientTime                 = qglGetUniformLocationARB(p->program, "ClientTime");
3786                 p->loc_Color_Ambient              = qglGetUniformLocationARB(p->program, "Color_Ambient");
3787                 p->loc_Color_Diffuse              = qglGetUniformLocationARB(p->program, "Color_Diffuse");
3788                 p->loc_Color_Specular             = qglGetUniformLocationARB(p->program, "Color_Specular");
3789                 p->loc_Color_Glow                 = qglGetUniformLocationARB(p->program, "Color_Glow");
3790                 p->loc_Color_Pants                = qglGetUniformLocationARB(p->program, "Color_Pants");
3791                 p->loc_Color_Shirt                = qglGetUniformLocationARB(p->program, "Color_Shirt");
3792                 p->loc_DeferredColor_Ambient      = qglGetUniformLocationARB(p->program, "DeferredColor_Ambient");
3793                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocationARB(p->program, "DeferredColor_Diffuse");
3794                 p->loc_DeferredColor_Specular     = qglGetUniformLocationARB(p->program, "DeferredColor_Specular");
3795                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocationARB(p->program, "DeferredMod_Diffuse");
3796                 p->loc_DeferredMod_Specular       = qglGetUniformLocationARB(p->program, "DeferredMod_Specular");
3797                 p->loc_DistortScaleRefractReflect = qglGetUniformLocationARB(p->program, "DistortScaleRefractReflect");
3798                 p->loc_EyePosition                = qglGetUniformLocationARB(p->program, "EyePosition");
3799                 p->loc_FogColor                   = qglGetUniformLocationARB(p->program, "FogColor");
3800                 p->loc_FogHeightFade              = qglGetUniformLocationARB(p->program, "FogHeightFade");
3801                 p->loc_FogPlane                   = qglGetUniformLocationARB(p->program, "FogPlane");
3802                 p->loc_FogPlaneViewDist           = qglGetUniformLocationARB(p->program, "FogPlaneViewDist");
3803                 p->loc_FogRangeRecip              = qglGetUniformLocationARB(p->program, "FogRangeRecip");
3804                 p->loc_LightColor                 = qglGetUniformLocationARB(p->program, "LightColor");
3805                 p->loc_LightDir                   = qglGetUniformLocationARB(p->program, "LightDir");
3806                 p->loc_LightPosition              = qglGetUniformLocationARB(p->program, "LightPosition");
3807                 p->loc_OffsetMapping_Scale        = qglGetUniformLocationARB(p->program, "OffsetMapping_Scale");
3808                 p->loc_PixelSize                  = qglGetUniformLocationARB(p->program, "PixelSize");
3809                 p->loc_ReflectColor               = qglGetUniformLocationARB(p->program, "ReflectColor");
3810                 p->loc_ReflectFactor              = qglGetUniformLocationARB(p->program, "ReflectFactor");
3811                 p->loc_ReflectOffset              = qglGetUniformLocationARB(p->program, "ReflectOffset");
3812                 p->loc_RefractColor               = qglGetUniformLocationARB(p->program, "RefractColor");
3813                 p->loc_Saturation                 = qglGetUniformLocationARB(p->program, "Saturation");
3814                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocationARB(p->program, "ScreenCenterRefractReflect");
3815                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocationARB(p->program, "ScreenScaleRefractReflect");
3816                 p->loc_ScreenToDepth              = qglGetUniformLocationARB(p->program, "ScreenToDepth");
3817                 p->loc_ShadowMap_Parameters       = qglGetUniformLocationARB(p->program, "ShadowMap_Parameters");
3818                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocationARB(p->program, "ShadowMap_TextureScale");
3819                 p->loc_SpecularPower              = qglGetUniformLocationARB(p->program, "SpecularPower");
3820                 p->loc_UserVec1                   = qglGetUniformLocationARB(p->program, "UserVec1");
3821                 p->loc_UserVec2                   = qglGetUniformLocationARB(p->program, "UserVec2");
3822                 p->loc_UserVec3                   = qglGetUniformLocationARB(p->program, "UserVec3");
3823                 p->loc_UserVec4                   = qglGetUniformLocationARB(p->program, "UserVec4");
3824                 p->loc_ViewTintColor              = qglGetUniformLocationARB(p->program, "ViewTintColor");
3825                 p->loc_ViewToLight                = qglGetUniformLocationARB(p->program, "ViewToLight");
3826                 p->loc_ModelToLight               = qglGetUniformLocationARB(p->program, "ModelToLight");
3827                 p->loc_TexMatrix                  = qglGetUniformLocationARB(p->program, "TexMatrix");
3828                 p->loc_BackgroundTexMatrix        = qglGetUniformLocationARB(p->program, "BackgroundTexMatrix");
3829                 p->loc_ModelViewMatrix            = qglGetUniformLocationARB(p->program, "ModelViewMatrix");
3830                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocationARB(p->program, "ModelViewProjectionMatrix");
3831                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocationARB(p->program, "PixelToScreenTexCoord");
3832                 p->loc_ModelToReflectCube         = qglGetUniformLocationARB(p->program, "ModelToReflectCube");
3833                 p->loc_ShadowMapMatrix            = qglGetUniformLocationARB(p->program, "ShadowMapMatrix");
3834                 p->loc_BloomColorSubtract         = qglGetUniformLocationARB(p->program, "BloomColorSubtract");
3835                 p->loc_NormalmapScrollBlend       = qglGetUniformLocationARB(p->program, "NormalmapScrollBlend");
3836                 // initialize the samplers to refer to the texture units we use
3837                 if (p->loc_Texture_First           >= 0) qglUniform1iARB(p->loc_Texture_First          , GL20TU_FIRST);
3838                 if (p->loc_Texture_Second          >= 0) qglUniform1iARB(p->loc_Texture_Second         , GL20TU_SECOND);
3839                 if (p->loc_Texture_GammaRamps      >= 0) qglUniform1iARB(p->loc_Texture_GammaRamps     , GL20TU_GAMMARAMPS);
3840                 if (p->loc_Texture_Normal          >= 0) qglUniform1iARB(p->loc_Texture_Normal         , GL20TU_NORMAL);
3841                 if (p->loc_Texture_Color           >= 0) qglUniform1iARB(p->loc_Texture_Color          , GL20TU_COLOR);
3842                 if (p->loc_Texture_Gloss           >= 0) qglUniform1iARB(p->loc_Texture_Gloss          , GL20TU_GLOSS);
3843                 if (p->loc_Texture_Glow            >= 0) qglUniform1iARB(p->loc_Texture_Glow           , GL20TU_GLOW);
3844                 if (p->loc_Texture_SecondaryNormal >= 0) qglUniform1iARB(p->loc_Texture_SecondaryNormal, GL20TU_SECONDARY_NORMAL);
3845                 if (p->loc_Texture_SecondaryColor  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryColor , GL20TU_SECONDARY_COLOR);
3846                 if (p->loc_Texture_SecondaryGloss  >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGloss , GL20TU_SECONDARY_GLOSS);
3847                 if (p->loc_Texture_SecondaryGlow   >= 0) qglUniform1iARB(p->loc_Texture_SecondaryGlow  , GL20TU_SECONDARY_GLOW);
3848                 if (p->loc_Texture_Pants           >= 0) qglUniform1iARB(p->loc_Texture_Pants          , GL20TU_PANTS);
3849                 if (p->loc_Texture_Shirt           >= 0) qglUniform1iARB(p->loc_Texture_Shirt          , GL20TU_SHIRT);
3850                 if (p->loc_Texture_FogHeightTexture>= 0) qglUniform1iARB(p->loc_Texture_FogHeightTexture, GL20TU_FOGHEIGHTTEXTURE);
3851                 if (p->loc_Texture_FogMask         >= 0) qglUniform1iARB(p->loc_Texture_FogMask        , GL20TU_FOGMASK);
3852                 if (p->loc_Texture_Lightmap        >= 0) qglUniform1iARB(p->loc_Texture_Lightmap       , GL20TU_LIGHTMAP);
3853                 if (p->loc_Texture_Deluxemap       >= 0) qglUniform1iARB(p->loc_Texture_Deluxemap      , GL20TU_DELUXEMAP);
3854                 if (p->loc_Texture_Attenuation     >= 0) qglUniform1iARB(p->loc_Texture_Attenuation    , GL20TU_ATTENUATION);
3855                 if (p->loc_Texture_Cube            >= 0) qglUniform1iARB(p->loc_Texture_Cube           , GL20TU_CUBE);
3856                 if (p->loc_Texture_Refraction      >= 0) qglUniform1iARB(p->loc_Texture_Refraction     , GL20TU_REFRACTION);
3857                 if (p->loc_Texture_Reflection      >= 0) qglUniform1iARB(p->loc_Texture_Reflection     , GL20TU_REFLECTION);
3858                 if (p->loc_Texture_ShadowMap2D     >= 0) qglUniform1iARB(p->loc_Texture_ShadowMap2D    , GL20TU_SHADOWMAP2D);
3859                 if (p->loc_Texture_CubeProjection  >= 0) qglUniform1iARB(p->loc_Texture_CubeProjection , GL20TU_CUBEPROJECTION);
3860                 if (p->loc_Texture_ScreenDepth     >= 0) qglUniform1iARB(p->loc_Texture_ScreenDepth    , GL20TU_SCREENDEPTH);
3861                 if (p->loc_Texture_ScreenNormalMap >= 0) qglUniform1iARB(p->loc_Texture_ScreenNormalMap, GL20TU_SCREENNORMALMAP);
3862                 if (p->loc_Texture_ScreenDiffuse   >= 0) qglUniform1iARB(p->loc_Texture_ScreenDiffuse  , GL20TU_SCREENDIFFUSE);
3863                 if (p->loc_Texture_ScreenSpecular  >= 0) qglUniform1iARB(p->loc_Texture_ScreenSpecular , GL20TU_SCREENSPECULAR);
3864                 if (p->loc_Texture_ReflectMask     >= 0) qglUniform1iARB(p->loc_Texture_ReflectMask    , GL20TU_REFLECTMASK);
3865                 if (p->loc_Texture_ReflectCube     >= 0) qglUniform1iARB(p->loc_Texture_ReflectCube    , GL20TU_REFLECTCUBE);
3866                 CHECKGLERROR
3867                 Con_DPrintf("^5GLSL shader %s compiled.\n", permutationname);
3868         }
3869         else
3870                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3871
3872         // free the strings
3873         if (vertexstring)
3874                 Mem_Free(vertexstring);
3875         if (geometrystring)
3876                 Mem_Free(geometrystring);
3877         if (fragmentstring)
3878                 Mem_Free(fragmentstring);
3879 }
3880
3881 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3882 {
3883         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3884         if (r_glsl_permutation != perm)
3885         {
3886                 r_glsl_permutation = perm;
3887                 if (!r_glsl_permutation->program)
3888                 {
3889                         if (!r_glsl_permutation->compiled)
3890                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3891                         if (!r_glsl_permutation->program)
3892                         {
3893                                 // remove features until we find a valid permutation
3894                                 int i;
3895                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3896                                 {
3897                                         // reduce i more quickly whenever it would not remove any bits
3898                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3899                                         if (!(permutation & j))
3900                                                 continue;
3901                                         permutation -= j;
3902                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3903                                         if (!r_glsl_permutation->compiled)
3904                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3905                                         if (r_glsl_permutation->program)
3906                                                 break;
3907                                 }
3908                                 if (i >= SHADERPERMUTATION_COUNT)
3909                                 {
3910                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3911                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3912                                         qglUseProgramObjectARB(0);CHECKGLERROR
3913                                         return; // no bit left to clear, entire mode is broken
3914                                 }
3915                         }
3916                 }
3917                 CHECKGLERROR
3918                 qglUseProgramObjectARB(r_glsl_permutation->program);CHECKGLERROR
3919         }
3920         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
3921         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
3922         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1fARB(r_glsl_permutation->loc_ClientTime, cl.time);
3923 }
3924
3925 #ifdef SUPPORTCG
3926 #include <Cg/cgGL.h>
3927 struct r_cg_permutation_s;
3928 typedef struct r_cg_permutation_s
3929 {
3930         /// hash lookup data
3931         struct r_cg_permutation_s *hashnext;
3932         unsigned int mode;
3933         unsigned int permutation;
3934
3935         /// indicates if we have tried compiling this permutation already
3936         qboolean compiled;
3937         /// 0 if compilation failed
3938         CGprogram vprogram;
3939         CGprogram fprogram;
3940         /// locations of detected parameters in programs, or NULL if not found
3941         CGparameter vp_EyePosition;
3942         CGparameter vp_FogPlane;
3943         CGparameter vp_LightDir;
3944         CGparameter vp_LightPosition;
3945         CGparameter vp_ModelToLight;
3946         CGparameter vp_TexMatrix;
3947         CGparameter vp_BackgroundTexMatrix;
3948         CGparameter vp_ModelViewProjectionMatrix;
3949         CGparameter vp_ModelViewMatrix;
3950         CGparameter vp_ShadowMapMatrix;
3951
3952         CGparameter fp_Texture_First;
3953         CGparameter fp_Texture_Second;
3954         CGparameter fp_Texture_GammaRamps;
3955         CGparameter fp_Texture_Normal;
3956         CGparameter fp_Texture_Color;
3957         CGparameter fp_Texture_Gloss;
3958         CGparameter fp_Texture_Glow;
3959         CGparameter fp_Texture_SecondaryNormal;
3960         CGparameter fp_Texture_SecondaryColor;
3961         CGparameter fp_Texture_SecondaryGloss;
3962         CGparameter fp_Texture_SecondaryGlow;
3963         CGparameter fp_Texture_Pants;
3964         CGparameter fp_Texture_Shirt;
3965         CGparameter fp_Texture_FogHeightTexture;
3966         CGparameter fp_Texture_FogMask;
3967         CGparameter fp_Texture_Lightmap;
3968         CGparameter fp_Texture_Deluxemap;
3969         CGparameter fp_Texture_Attenuation;
3970         CGparameter fp_Texture_Cube;
3971         CGparameter fp_Texture_Refraction;
3972         CGparameter fp_Texture_Reflection;
3973         CGparameter fp_Texture_ShadowMap2D;
3974         CGparameter fp_Texture_CubeProjection;
3975         CGparameter fp_Texture_ScreenDepth;
3976         CGparameter fp_Texture_ScreenNormalMap;
3977         CGparameter fp_Texture_ScreenDiffuse;
3978         CGparameter fp_Texture_ScreenSpecular;
3979         CGparameter fp_Texture_ReflectMask;
3980         CGparameter fp_Texture_ReflectCube;
3981         CGparameter fp_Alpha;
3982         CGparameter fp_BloomBlur_Parameters;
3983         CGparameter fp_ClientTime;
3984         CGparameter fp_Color_Ambient;
3985         CGparameter fp_Color_Diffuse;
3986         CGparameter fp_Color_Specular;
3987         CGparameter fp_Color_Glow;
3988         CGparameter fp_Color_Pants;
3989         CGparameter fp_Color_Shirt;
3990         CGparameter fp_DeferredColor_Ambient;
3991         CGparameter fp_DeferredColor_Diffuse;
3992         CGparameter fp_DeferredColor_Specular;
3993         CGparameter fp_DeferredMod_Diffuse;
3994         CGparameter fp_DeferredMod_Specular;
3995         CGparameter fp_DistortScaleRefractReflect;
3996         CGparameter fp_EyePosition;
3997         CGparameter fp_FogColor;
3998         CGparameter fp_FogHeightFade;
3999         CGparameter fp_FogPlane;
4000         CGparameter fp_FogPlaneViewDist;
4001         CGparameter fp_FogRangeRecip;
4002         CGparameter fp_LightColor;
4003         CGparameter fp_LightDir;
4004         CGparameter fp_LightPosition;
4005         CGparameter fp_OffsetMapping_Scale;
4006         CGparameter fp_PixelSize;
4007         CGparameter fp_ReflectColor;
4008         CGparameter fp_ReflectFactor;
4009         CGparameter fp_ReflectOffset;
4010         CGparameter fp_RefractColor;
4011         CGparameter fp_Saturation;
4012         CGparameter fp_ScreenCenterRefractReflect;
4013         CGparameter fp_ScreenScaleRefractReflect;
4014         CGparameter fp_ScreenToDepth;
4015         CGparameter fp_ShadowMap_Parameters;
4016         CGparameter fp_ShadowMap_TextureScale;
4017         CGparameter fp_SpecularPower;
4018         CGparameter fp_UserVec1;
4019         CGparameter fp_UserVec2;
4020         CGparameter fp_UserVec3;
4021         CGparameter fp_UserVec4;
4022         CGparameter fp_ViewTintColor;
4023         CGparameter fp_ViewToLight;
4024         CGparameter fp_PixelToScreenTexCoord;
4025         CGparameter fp_ModelToReflectCube;
4026         CGparameter fp_BloomColorSubtract;
4027         CGparameter fp_NormalmapScrollBlend;
4028 }
4029 r_cg_permutation_t;
4030
4031 /// information about each possible shader permutation
4032 r_cg_permutation_t *r_cg_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4033 /// currently selected permutation
4034 r_cg_permutation_t *r_cg_permutation;
4035 /// storage for permutations linked in the hash table
4036 memexpandablearray_t r_cg_permutationarray;
4037
4038 #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));}}
4039
4040 static r_cg_permutation_t *R_CG_FindPermutation(unsigned int mode, unsigned int permutation)
4041 {
4042         //unsigned int hashdepth = 0;
4043         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4044         r_cg_permutation_t *p;
4045         for (p = r_cg_permutationhash[mode][hashindex];p;p = p->hashnext)
4046         {
4047                 if (p->mode == mode && p->permutation == permutation)
4048                 {
4049                         //if (hashdepth > 10)
4050                         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4051                         return p;
4052                 }
4053                 //hashdepth++;
4054         }
4055         p = (r_cg_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_cg_permutationarray);
4056         p->mode = mode;
4057         p->permutation = permutation;
4058         p->hashnext = r_cg_permutationhash[mode][hashindex];
4059         r_cg_permutationhash[mode][hashindex] = p;
4060         //if (hashdepth > 10)
4061         //      Con_Printf("R_CG_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4062         return p;
4063 }
4064
4065 static char *R_CG_GetText(const char *filename, qboolean printfromdisknotice)
4066 {
4067         char *shaderstring;
4068         if (!filename || !filename[0])
4069                 return NULL;
4070         if (!strcmp(filename, "cg/default.cg"))
4071         {
4072                 if (!cgshaderstring)
4073                 {
4074                         cgshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4075                         if (cgshaderstring)
4076                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4077                         else
4078                                 cgshaderstring = (char *)builtincgshaderstring;
4079                 }
4080                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(cgshaderstring) + 1);
4081                 memcpy(shaderstring, cgshaderstring, strlen(cgshaderstring) + 1);
4082                 return shaderstring;
4083         }
4084         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4085         if (shaderstring)
4086         {
4087                 if (printfromdisknotice)
4088                         Con_DPrintf("from disk %s... ", filename);
4089                 return shaderstring;
4090         }
4091         return shaderstring;
4092 }
4093
4094 static void R_CG_CacheShader(r_cg_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4095 {
4096         // TODO: load or create .fp and .vp shader files
4097 }
4098
4099 static void R_CG_CompilePermutation(r_cg_permutation_t *p, unsigned int mode, unsigned int permutation)
4100 {
4101         int i;
4102         shadermodeinfo_t *modeinfo = cgshadermodeinfo + mode;
4103         int vertstring_length = 0;
4104         int geomstring_length = 0;
4105         int fragstring_length = 0;
4106         char *t;
4107         char *vertexstring, *geometrystring, *fragmentstring;
4108         char *vertstring, *geomstring, *fragstring;
4109         char permutationname[256];
4110         char cachename[256];
4111         CGprofile vertexProfile;
4112         CGprofile fragmentProfile;
4113         int vertstrings_count = 0;
4114         int geomstrings_count = 0;
4115         int fragstrings_count = 0;
4116         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4117         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4118         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4119
4120         if (p->compiled)
4121                 return;
4122         p->compiled = true;
4123         p->vprogram = NULL;
4124         p->fprogram = NULL;
4125
4126         permutationname[0] = 0;
4127         cachename[0] = 0;
4128         vertexstring   = R_CG_GetText(modeinfo->vertexfilename, true);
4129         geometrystring = R_CG_GetText(modeinfo->geometryfilename, false);
4130         fragmentstring = R_CG_GetText(modeinfo->fragmentfilename, false);
4131
4132         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4133         strlcat(cachename, "cg/", sizeof(cachename));
4134
4135         // the first pretext is which type of shader to compile as
4136         // (later these will all be bound together as a program object)
4137         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4138         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4139         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4140
4141         // the second pretext is the mode (for example a light source)
4142         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4143         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4144         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4145         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4146         strlcat(cachename, modeinfo->name, sizeof(cachename));
4147
4148         // now add all the permutation pretexts
4149         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4150         {
4151                 if (permutation & (1<<i))
4152                 {
4153                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4154                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4155                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4156                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4157                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4158                 }
4159                 else
4160                 {
4161                         // keep line numbers correct
4162                         vertstrings_list[vertstrings_count++] = "\n";
4163                         geomstrings_list[geomstrings_count++] = "\n";
4164                         fragstrings_list[fragstrings_count++] = "\n";
4165                 }
4166         }
4167
4168         // add static parms
4169         R_CompileShader_AddStaticParms(mode, permutation);
4170         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4171         vertstrings_count += shaderstaticparms_count;
4172         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4173         geomstrings_count += shaderstaticparms_count;
4174         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4175         fragstrings_count += shaderstaticparms_count;
4176
4177         // replace spaces in the cachename with _ characters
4178         for (i = 0;cachename[i];i++)
4179                 if (cachename[i] == ' ')
4180                         cachename[i] = '_';
4181
4182         // now append the shader text itself
4183         vertstrings_list[vertstrings_count++] = vertexstring;
4184         geomstrings_list[geomstrings_count++] = geometrystring;
4185         fragstrings_list[fragstrings_count++] = fragmentstring;
4186
4187         // if any sources were NULL, clear the respective list
4188         if (!vertexstring)
4189                 vertstrings_count = 0;
4190         if (!geometrystring)
4191                 geomstrings_count = 0;
4192         if (!fragmentstring)
4193                 fragstrings_count = 0;
4194
4195         vertstring_length = 0;
4196         for (i = 0;i < vertstrings_count;i++)
4197                 vertstring_length += strlen(vertstrings_list[i]);
4198         vertstring = t = Mem_Alloc(tempmempool, vertstring_length + 1);
4199         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4200                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4201
4202         geomstring_length = 0;
4203         for (i = 0;i < geomstrings_count;i++)
4204                 geomstring_length += strlen(geomstrings_list[i]);
4205         geomstring = t = Mem_Alloc(tempmempool, geomstring_length + 1);
4206         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4207                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4208
4209         fragstring_length = 0;
4210         for (i = 0;i < fragstrings_count;i++)
4211                 fragstring_length += strlen(fragstrings_list[i]);
4212         fragstring = t = Mem_Alloc(tempmempool, fragstring_length + 1);
4213         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4214                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4215
4216         CHECKGLERROR
4217         CHECKCGERROR
4218         //vertexProfile = CG_PROFILE_ARBVP1;
4219         //fragmentProfile = CG_PROFILE_ARBFP1;
4220         vertexProfile = cgGLGetLatestProfile(CG_GL_VERTEX);CHECKCGERROR
4221         fragmentProfile = cgGLGetLatestProfile(CG_GL_FRAGMENT);CHECKCGERROR
4222         //cgGLSetOptimalOptions(vertexProfile);CHECKCGERROR
4223         //cgGLSetOptimalOptions(fragmentProfile);CHECKCGERROR
4224         //cgSetAutoCompile(vid.cgcontext, CG_COMPILE_MANUAL);CHECKCGERROR
4225         CHECKGLERROR
4226
4227         // try to load the cached shader, or generate one
4228         R_CG_CacheShader(p, cachename, vertstring, fragstring);
4229
4230         // if caching failed, do a dynamic compile for now
4231         CHECKCGERROR
4232         if (vertstring[0] && !p->vprogram)
4233                 p->vprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, vertstring, vertexProfile, NULL, NULL);
4234         CHECKCGERROR
4235         if (fragstring[0] && !p->fprogram)
4236                 p->fprogram = cgCreateProgram(vid.cgcontext, CG_SOURCE, fragstring, fragmentProfile, NULL, NULL);
4237         CHECKCGERROR
4238
4239         // look up all the uniform variable names we care about, so we don't
4240         // have to look them up every time we set them
4241         if (p->vprogram)
4242         {
4243                 CHECKCGERROR
4244                 cgGLLoadProgram(p->vprogram);CHECKCGERROR CHECKGLERROR
4245                 cgGLEnableProfile(vertexProfile);CHECKCGERROR CHECKGLERROR
4246                 p->vp_EyePosition                = cgGetNamedParameter(p->vprogram, "EyePosition");
4247                 p->vp_FogPlane                   = cgGetNamedParameter(p->vprogram, "FogPlane");
4248                 p->vp_LightDir                   = cgGetNamedParameter(p->vprogram, "LightDir");
4249                 p->vp_LightPosition              = cgGetNamedParameter(p->vprogram, "LightPosition");
4250                 p->vp_ModelToLight               = cgGetNamedParameter(p->vprogram, "ModelToLight");
4251                 p->vp_TexMatrix                  = cgGetNamedParameter(p->vprogram, "TexMatrix");
4252                 p->vp_BackgroundTexMatrix        = cgGetNamedParameter(p->vprogram, "BackgroundTexMatrix");
4253                 p->vp_ModelViewProjectionMatrix  = cgGetNamedParameter(p->vprogram, "ModelViewProjectionMatrix");
4254                 p->vp_ModelViewMatrix            = cgGetNamedParameter(p->vprogram, "ModelViewMatrix");
4255                 p->vp_ShadowMapMatrix            = cgGetNamedParameter(p->vprogram, "ShadowMapMatrix");
4256                 CHECKCGERROR
4257         }
4258         if (p->fprogram)
4259         {
4260                 CHECKCGERROR
4261                 cgGLLoadProgram(p->fprogram);CHECKCGERROR CHECKGLERROR
4262                 cgGLEnableProfile(fragmentProfile);CHECKCGERROR CHECKGLERROR
4263                 p->fp_Texture_First              = cgGetNamedParameter(p->fprogram, "Texture_First");
4264                 p->fp_Texture_Second             = cgGetNamedParameter(p->fprogram, "Texture_Second");
4265                 p->fp_Texture_GammaRamps         = cgGetNamedParameter(p->fprogram, "Texture_GammaRamps");
4266                 p->fp_Texture_Normal             = cgGetNamedParameter(p->fprogram, "Texture_Normal");
4267                 p->fp_Texture_Color              = cgGetNamedParameter(p->fprogram, "Texture_Color");
4268                 p->fp_Texture_Gloss              = cgGetNamedParameter(p->fprogram, "Texture_Gloss");
4269                 p->fp_Texture_Glow               = cgGetNamedParameter(p->fprogram, "Texture_Glow");
4270                 p->fp_Texture_SecondaryNormal    = cgGetNamedParameter(p->fprogram, "Texture_SecondaryNormal");
4271                 p->fp_Texture_SecondaryColor     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryColor");
4272                 p->fp_Texture_SecondaryGloss     = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGloss");
4273                 p->fp_Texture_SecondaryGlow      = cgGetNamedParameter(p->fprogram, "Texture_SecondaryGlow");
4274                 p->fp_Texture_Pants              = cgGetNamedParameter(p->fprogram, "Texture_Pants");
4275                 p->fp_Texture_Shirt              = cgGetNamedParameter(p->fprogram, "Texture_Shirt");
4276                 p->fp_Texture_FogHeightTexture   = cgGetNamedParameter(p->fprogram, "Texture_FogHeightTexture");
4277                 p->fp_Texture_FogMask            = cgGetNamedParameter(p->fprogram, "Texture_FogMask");
4278                 p->fp_Texture_Lightmap           = cgGetNamedParameter(p->fprogram, "Texture_Lightmap");
4279                 p->fp_Texture_Deluxemap          = cgGetNamedParameter(p->fprogram, "Texture_Deluxemap");
4280                 p->fp_Texture_Attenuation        = cgGetNamedParameter(p->fprogram, "Texture_Attenuation");
4281                 p->fp_Texture_Cube               = cgGetNamedParameter(p->fprogram, "Texture_Cube");
4282                 p->fp_Texture_Refraction         = cgGetNamedParameter(p->fprogram, "Texture_Refraction");
4283                 p->fp_Texture_Reflection         = cgGetNamedParameter(p->fprogram, "Texture_Reflection");
4284                 p->fp_Texture_ShadowMap2D        = cgGetNamedParameter(p->fprogram, "Texture_ShadowMap2D");
4285                 p->fp_Texture_CubeProjection     = cgGetNamedParameter(p->fprogram, "Texture_CubeProjection");
4286                 p->fp_Texture_ScreenDepth        = cgGetNamedParameter(p->fprogram, "Texture_ScreenDepth");
4287                 p->fp_Texture_ScreenNormalMap    = cgGetNamedParameter(p->fprogram, "Texture_ScreenNormalMap");
4288                 p->fp_Texture_ScreenDiffuse      = cgGetNamedParameter(p->fprogram, "Texture_ScreenDiffuse");
4289                 p->fp_Texture_ScreenSpecular     = cgGetNamedParameter(p->fprogram, "Texture_ScreenSpecular");
4290                 p->fp_Texture_ReflectMask        = cgGetNamedParameter(p->fprogram, "Texture_ReflectMask");
4291                 p->fp_Texture_ReflectCube        = cgGetNamedParameter(p->fprogram, "Texture_ReflectCube");
4292                 p->fp_Alpha                      = cgGetNamedParameter(p->fprogram, "Alpha");
4293                 p->fp_BloomBlur_Parameters       = cgGetNamedParameter(p->fprogram, "BloomBlur_Parameters");
4294                 p->fp_ClientTime                 = cgGetNamedParameter(p->fprogram, "ClientTime");
4295                 p->fp_Color_Ambient              = cgGetNamedParameter(p->fprogram, "Color_Ambient");
4296                 p->fp_Color_Diffuse              = cgGetNamedParameter(p->fprogram, "Color_Diffuse");
4297                 p->fp_Color_Specular             = cgGetNamedParameter(p->fprogram, "Color_Specular");
4298                 p->fp_Color_Glow                 = cgGetNamedParameter(p->fprogram, "Color_Glow");
4299                 p->fp_Color_Pants                = cgGetNamedParameter(p->fprogram, "Color_Pants");
4300                 p->fp_Color_Shirt                = cgGetNamedParameter(p->fprogram, "Color_Shirt");
4301                 p->fp_DeferredColor_Ambient      = cgGetNamedParameter(p->fprogram, "DeferredColor_Ambient");
4302                 p->fp_DeferredColor_Diffuse      = cgGetNamedParameter(p->fprogram, "DeferredColor_Diffuse");
4303                 p->fp_DeferredColor_Specular     = cgGetNamedParameter(p->fprogram, "DeferredColor_Specular");
4304                 p->fp_DeferredMod_Diffuse        = cgGetNamedParameter(p->fprogram, "DeferredMod_Diffuse");
4305                 p->fp_DeferredMod_Specular       = cgGetNamedParameter(p->fprogram, "DeferredMod_Specular");
4306                 p->fp_DistortScaleRefractReflect = cgGetNamedParameter(p->fprogram, "DistortScaleRefractReflect");
4307                 p->fp_EyePosition                = cgGetNamedParameter(p->fprogram, "EyePosition");
4308                 p->fp_FogColor                   = cgGetNamedParameter(p->fprogram, "FogColor");
4309                 p->fp_FogHeightFade              = cgGetNamedParameter(p->fprogram, "FogHeightFade");
4310                 p->fp_FogPlane                   = cgGetNamedParameter(p->fprogram, "FogPlane");
4311                 p->fp_FogPlaneViewDist           = cgGetNamedParameter(p->fprogram, "FogPlaneViewDist");
4312                 p->fp_FogRangeRecip              = cgGetNamedParameter(p->fprogram, "FogRangeRecip");
4313                 p->fp_LightColor                 = cgGetNamedParameter(p->fprogram, "LightColor");
4314                 p->fp_LightDir                   = cgGetNamedParameter(p->fprogram, "LightDir");
4315                 p->fp_LightPosition              = cgGetNamedParameter(p->fprogram, "LightPosition");
4316                 p->fp_OffsetMapping_Scale        = cgGetNamedParameter(p->fprogram, "OffsetMapping_Scale");
4317                 p->fp_PixelSize                  = cgGetNamedParameter(p->fprogram, "PixelSize");
4318                 p->fp_ReflectColor               = cgGetNamedParameter(p->fprogram, "ReflectColor");
4319                 p->fp_ReflectFactor              = cgGetNamedParameter(p->fprogram, "ReflectFactor");
4320                 p->fp_ReflectOffset              = cgGetNamedParameter(p->fprogram, "ReflectOffset");
4321                 p->fp_RefractColor               = cgGetNamedParameter(p->fprogram, "RefractColor");
4322                 p->fp_Saturation                 = cgGetNamedParameter(p->fprogram, "Saturation");
4323                 p->fp_ScreenCenterRefractReflect = cgGetNamedParameter(p->fprogram, "ScreenCenterRefractReflect");
4324                 p->fp_ScreenScaleRefractReflect  = cgGetNamedParameter(p->fprogram, "ScreenScaleRefractReflect");
4325                 p->fp_ScreenToDepth              = cgGetNamedParameter(p->fprogram, "ScreenToDepth");
4326                 p->fp_ShadowMap_Parameters       = cgGetNamedParameter(p->fprogram, "ShadowMap_Parameters");
4327                 p->fp_ShadowMap_TextureScale     = cgGetNamedParameter(p->fprogram, "ShadowMap_TextureScale");
4328                 p->fp_SpecularPower              = cgGetNamedParameter(p->fprogram, "SpecularPower");
4329                 p->fp_UserVec1                   = cgGetNamedParameter(p->fprogram, "UserVec1");
4330                 p->fp_UserVec2                   = cgGetNamedParameter(p->fprogram, "UserVec2");
4331                 p->fp_UserVec3                   = cgGetNamedParameter(p->fprogram, "UserVec3");
4332                 p->fp_UserVec4                   = cgGetNamedParameter(p->fprogram, "UserVec4");
4333                 p->fp_ViewTintColor              = cgGetNamedParameter(p->fprogram, "ViewTintColor");
4334                 p->fp_ViewToLight                = cgGetNamedParameter(p->fprogram, "ViewToLight");
4335                 p->fp_PixelToScreenTexCoord      = cgGetNamedParameter(p->fprogram, "PixelToScreenTexCoord");
4336                 p->fp_ModelToReflectCube         = cgGetNamedParameter(p->fprogram, "ModelToReflectCube");
4337                 p->fp_BloomColorSubtract         = cgGetNamedParameter(p->fprogram, "BloomColorSubtract");
4338                 p->fp_NormalmapScrollBlend       = cgGetNamedParameter(p->fprogram, "NormalmapScrollBlend");
4339                 CHECKCGERROR
4340         }
4341
4342         if ((p->vprogram || !vertstring[0]) && (p->fprogram || !fragstring[0]))
4343                 Con_DPrintf("^5CG shader %s compiled.\n", permutationname);
4344         else
4345                 Con_Printf("^1CG shader %s failed!  some features may not work properly.\n", permutationname);
4346
4347         // free the strings
4348         if (vertstring)
4349                 Mem_Free(vertstring);
4350         if (geomstring)
4351                 Mem_Free(geomstring);
4352         if (fragstring)
4353                 Mem_Free(fragstring);
4354         if (vertexstring)
4355                 Mem_Free(vertexstring);
4356         if (geometrystring)
4357                 Mem_Free(geometrystring);
4358         if (fragmentstring)
4359                 Mem_Free(fragmentstring);
4360 }
4361
4362 void R_SetupShader_SetPermutationCG(unsigned int mode, unsigned int permutation)
4363 {
4364         r_cg_permutation_t *perm = R_CG_FindPermutation(mode, permutation);
4365         CHECKGLERROR
4366         CHECKCGERROR
4367         if (r_cg_permutation != perm)
4368         {
4369                 r_cg_permutation = perm;
4370                 if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4371                 {
4372                         if (!r_cg_permutation->compiled)
4373                                 R_CG_CompilePermutation(perm, mode, permutation);
4374                         if (!r_cg_permutation->vprogram && !r_cg_permutation->fprogram)
4375                         {
4376                                 // remove features until we find a valid permutation
4377                                 int i;
4378                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4379                                 {
4380                                         // reduce i more quickly whenever it would not remove any bits
4381                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4382                                         if (!(permutation & j))
4383                                                 continue;
4384                                         permutation -= j;
4385                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4386                                         if (!r_cg_permutation->compiled)
4387                                                 R_CG_CompilePermutation(perm, mode, permutation);
4388                                         if (r_cg_permutation->vprogram || r_cg_permutation->fprogram)
4389                                                 break;
4390                                 }
4391                                 if (i >= SHADERPERMUTATION_COUNT)
4392                                 {
4393                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4394                                         r_cg_permutation = R_CG_FindPermutation(mode, permutation);
4395                                         return; // no bit left to clear, entire mode is broken
4396                                 }
4397                         }
4398                 }
4399                 CHECKGLERROR
4400                 CHECKCGERROR
4401                 if (r_cg_permutation->vprogram)
4402                 {
4403                         cgGLLoadProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4404                         cgGLBindProgram(r_cg_permutation->vprogram);CHECKCGERROR CHECKGLERROR
4405                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4406                 }
4407                 else
4408                 {
4409                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4410                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4411                 }
4412                 if (r_cg_permutation->fprogram)
4413                 {
4414                         cgGLLoadProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4415                         cgGLBindProgram(r_cg_permutation->fprogram);CHECKCGERROR CHECKGLERROR
4416                         cgGLEnableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4417                 }
4418                 else
4419                 {
4420                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4421                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4422                 }
4423         }
4424         CHECKCGERROR
4425         if (r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
4426         if (r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
4427         if (r_cg_permutation->fp_ClientTime) cgGLSetParameter1f(r_cg_permutation->fp_ClientTime, cl.time);CHECKCGERROR
4428 }
4429
4430 void CG_BindTexture(CGparameter param, rtexture_t *tex)
4431 {
4432         cgGLSetTextureParameter(param, R_GetTexture(tex));
4433         cgGLEnableTextureParameter(param);
4434 }
4435 #endif
4436
4437 #ifdef SUPPORTD3D
4438
4439 #ifdef SUPPORTD3D
4440 #include <d3d9.h>
4441 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4442 extern D3DCAPS9 vid_d3d9caps;
4443 #endif
4444
4445 struct r_hlsl_permutation_s;
4446 typedef struct r_hlsl_permutation_s
4447 {
4448         /// hash lookup data
4449         struct r_hlsl_permutation_s *hashnext;
4450         unsigned int mode;
4451         unsigned int permutation;
4452
4453         /// indicates if we have tried compiling this permutation already
4454         qboolean compiled;
4455         /// NULL if compilation failed
4456         IDirect3DVertexShader9 *vertexshader;
4457         IDirect3DPixelShader9 *pixelshader;
4458 }
4459 r_hlsl_permutation_t;
4460
4461 typedef enum D3DVSREGISTER_e
4462 {
4463         D3DVSREGISTER_TexMatrix = 0, // float4x4
4464         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4465         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4466         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4467         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4468         D3DVSREGISTER_ModelToLight = 20, // float4x4
4469         D3DVSREGISTER_EyePosition = 24,
4470         D3DVSREGISTER_FogPlane = 25,
4471         D3DVSREGISTER_LightDir = 26,
4472         D3DVSREGISTER_LightPosition = 27,
4473 }
4474 D3DVSREGISTER_t;
4475
4476 typedef enum D3DPSREGISTER_e
4477 {
4478         D3DPSREGISTER_Alpha = 0,
4479         D3DPSREGISTER_BloomBlur_Parameters = 1,
4480         D3DPSREGISTER_ClientTime = 2,
4481         D3DPSREGISTER_Color_Ambient = 3,
4482         D3DPSREGISTER_Color_Diffuse = 4,
4483         D3DPSREGISTER_Color_Specular = 5,
4484         D3DPSREGISTER_Color_Glow = 6,
4485         D3DPSREGISTER_Color_Pants = 7,
4486         D3DPSREGISTER_Color_Shirt = 8,
4487         D3DPSREGISTER_DeferredColor_Ambient = 9,
4488         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4489         D3DPSREGISTER_DeferredColor_Specular = 11,
4490         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4491         D3DPSREGISTER_DeferredMod_Specular = 13,
4492         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4493         D3DPSREGISTER_EyePosition = 15, // unused
4494         D3DPSREGISTER_FogColor = 16,
4495         D3DPSREGISTER_FogHeightFade = 17,
4496         D3DPSREGISTER_FogPlane = 18,
4497         D3DPSREGISTER_FogPlaneViewDist = 19,
4498         D3DPSREGISTER_FogRangeRecip = 20,
4499         D3DPSREGISTER_LightColor = 21,
4500         D3DPSREGISTER_LightDir = 22, // unused
4501         D3DPSREGISTER_LightPosition = 23,
4502         D3DPSREGISTER_OffsetMapping_Scale = 24,
4503         D3DPSREGISTER_PixelSize = 25,
4504         D3DPSREGISTER_ReflectColor = 26,
4505         D3DPSREGISTER_ReflectFactor = 27,
4506         D3DPSREGISTER_ReflectOffset = 28,
4507         D3DPSREGISTER_RefractColor = 29,
4508         D3DPSREGISTER_Saturation = 30,
4509         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4510         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4511         D3DPSREGISTER_ScreenToDepth = 33,
4512         D3DPSREGISTER_ShadowMap_Parameters = 34,
4513         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4514         D3DPSREGISTER_SpecularPower = 36,
4515         D3DPSREGISTER_UserVec1 = 37,
4516         D3DPSREGISTER_UserVec2 = 38,
4517         D3DPSREGISTER_UserVec3 = 39,
4518         D3DPSREGISTER_UserVec4 = 40,
4519         D3DPSREGISTER_ViewTintColor = 41,
4520         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4521         D3DPSREGISTER_BloomColorSubtract = 43,
4522         D3DPSREGISTER_ViewToLight = 44, // float4x4
4523         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4524         D3DPSREGISTER_NormalmapScrollBlend = 52,
4525         // next at 53
4526 }
4527 D3DPSREGISTER_t;
4528
4529 /// information about each possible shader permutation
4530 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4531 /// currently selected permutation
4532 r_hlsl_permutation_t *r_hlsl_permutation;
4533 /// storage for permutations linked in the hash table
4534 memexpandablearray_t r_hlsl_permutationarray;
4535
4536 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4537 {
4538         //unsigned int hashdepth = 0;
4539         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4540         r_hlsl_permutation_t *p;
4541         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4542         {
4543                 if (p->mode == mode && p->permutation == permutation)
4544                 {
4545                         //if (hashdepth > 10)
4546                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4547                         return p;
4548                 }
4549                 //hashdepth++;
4550         }
4551         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4552         p->mode = mode;
4553         p->permutation = permutation;
4554         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4555         r_hlsl_permutationhash[mode][hashindex] = p;
4556         //if (hashdepth > 10)
4557         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4558         return p;
4559 }
4560
4561 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4562 {
4563         char *shaderstring;
4564         if (!filename || !filename[0])
4565                 return NULL;
4566         if (!strcmp(filename, "hlsl/default.hlsl"))
4567         {
4568                 if (!hlslshaderstring)
4569                 {
4570                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4571                         if (hlslshaderstring)
4572                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4573                         else
4574                                 hlslshaderstring = (char *)builtincgshaderstring;
4575                 }
4576                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4577                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4578                 return shaderstring;
4579         }
4580         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4581         if (shaderstring)
4582         {
4583                 if (printfromdisknotice)
4584                         Con_DPrintf("from disk %s... ", filename);
4585                 return shaderstring;
4586         }
4587         return shaderstring;
4588 }
4589
4590 #include <d3dx9.h>
4591 //#include <d3dx9shader.h>
4592 //#include <d3dx9mesh.h>
4593
4594 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4595 {
4596         DWORD *vsbin = NULL;
4597         DWORD *psbin = NULL;
4598         fs_offset_t vsbinsize;
4599         fs_offset_t psbinsize;
4600 //      IDirect3DVertexShader9 *vs = NULL;
4601 //      IDirect3DPixelShader9 *ps = NULL;
4602         ID3DXBuffer *vslog = NULL;
4603         ID3DXBuffer *vsbuffer = NULL;
4604         ID3DXConstantTable *vsconstanttable = NULL;
4605         ID3DXBuffer *pslog = NULL;
4606         ID3DXBuffer *psbuffer = NULL;
4607         ID3DXConstantTable *psconstanttable = NULL;
4608         int vsresult = 0;
4609         int psresult = 0;
4610         char temp[MAX_INPUTLINE];
4611         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4612         qboolean debugshader = gl_paranoid.integer != 0;
4613         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4614         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4615         if (!debugshader)
4616         {
4617                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4618                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4619         }
4620         if ((!vsbin && vertstring) || (!psbin && fragstring))
4621         {
4622                 const char* dllnames_d3dx9 [] =
4623                 {
4624                         "d3dx9_43.dll",
4625                         "d3dx9_42.dll",
4626                         "d3dx9_41.dll",
4627                         "d3dx9_40.dll",
4628                         "d3dx9_39.dll",
4629                         "d3dx9_38.dll",
4630                         "d3dx9_37.dll",
4631                         "d3dx9_36.dll",
4632                         "d3dx9_35.dll",
4633                         "d3dx9_34.dll",
4634                         "d3dx9_33.dll",
4635                         "d3dx9_32.dll",
4636                         "d3dx9_31.dll",
4637                         "d3dx9_30.dll",
4638                         "d3dx9_29.dll",
4639                         "d3dx9_28.dll",
4640                         "d3dx9_27.dll",
4641                         "d3dx9_26.dll",
4642                         "d3dx9_25.dll",
4643                         "d3dx9_24.dll",
4644                         NULL
4645                 };
4646                 dllhandle_t d3dx9_dll = NULL;
4647                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4648                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4649                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4650                 dllfunction_t d3dx9_dllfuncs[] =
4651                 {
4652                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4653                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4654                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4655                         {NULL, NULL}
4656                 };
4657                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4658                 {
4659                         DWORD shaderflags = 0;
4660                         if (debugshader)
4661                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4662                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4663                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4664                         if (vertstring && vertstring[0])
4665                         {
4666                                 if (debugshader)
4667                                 {
4668 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4669 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4670                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4671                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4672                                 }
4673                                 else
4674                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4675                                 if (vsbuffer)
4676                                 {
4677                                         vsbinsize = vsbuffer->GetBufferSize();
4678                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4679                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4680                                         vsbuffer->Release();
4681                                 }
4682                                 if (vslog)
4683                                 {
4684                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4685                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4686                                         vslog->Release();
4687                                 }
4688                         }
4689                         if (fragstring && fragstring[0])
4690                         {
4691                                 if (debugshader)
4692                                 {
4693 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4694 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4695                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4696                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4697                                 }
4698                                 else
4699                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4700                                 if (psbuffer)
4701                                 {
4702                                         psbinsize = psbuffer->GetBufferSize();
4703                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4704                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4705                                         psbuffer->Release();
4706                                 }
4707                                 if (pslog)
4708                                 {
4709                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4710                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4711                                         pslog->Release();
4712                                 }
4713                         }
4714                         Sys_UnloadLibrary(&d3dx9_dll);
4715                 }
4716                 else
4717                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4718         }
4719         if (vsbin && psbin)
4720         {
4721                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4722                 if (FAILED(vsresult))
4723                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4724                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4725                 if (FAILED(psresult))
4726                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4727         }
4728         // free the shader data
4729         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4730         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4731 }
4732
4733 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4734 {
4735         int i;
4736         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4737         int vertstring_length = 0;
4738         int geomstring_length = 0;
4739         int fragstring_length = 0;
4740         char *t;
4741         char *vertexstring, *geometrystring, *fragmentstring;
4742         char *vertstring, *geomstring, *fragstring;
4743         char permutationname[256];
4744         char cachename[256];
4745         int vertstrings_count = 0;
4746         int geomstrings_count = 0;
4747         int fragstrings_count = 0;
4748         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4749         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4750         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4751
4752         if (p->compiled)
4753                 return;
4754         p->compiled = true;
4755         p->vertexshader = NULL;
4756         p->pixelshader = NULL;
4757
4758         permutationname[0] = 0;
4759         cachename[0] = 0;
4760         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4761         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4762         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4763
4764         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4765         strlcat(cachename, "hlsl/", sizeof(cachename));
4766
4767         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4768         vertstrings_count = 0;
4769         geomstrings_count = 0;
4770         fragstrings_count = 0;
4771         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4772         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4773         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4774
4775         // the first pretext is which type of shader to compile as
4776         // (later these will all be bound together as a program object)
4777         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4778         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4779         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4780
4781         // the second pretext is the mode (for example a light source)
4782         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4783         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4784         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4785         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4786         strlcat(cachename, modeinfo->name, sizeof(cachename));
4787
4788         // now add all the permutation pretexts
4789         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4790         {
4791                 if (permutation & (1<<i))
4792                 {
4793                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4794                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4795                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4796                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4797                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4798                 }
4799                 else
4800                 {
4801                         // keep line numbers correct
4802                         vertstrings_list[vertstrings_count++] = "\n";
4803                         geomstrings_list[geomstrings_count++] = "\n";
4804                         fragstrings_list[fragstrings_count++] = "\n";
4805                 }
4806         }
4807
4808         // add static parms
4809         R_CompileShader_AddStaticParms(mode, permutation);
4810         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4811         vertstrings_count += shaderstaticparms_count;
4812         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4813         geomstrings_count += shaderstaticparms_count;
4814         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4815         fragstrings_count += shaderstaticparms_count;
4816
4817         // replace spaces in the cachename with _ characters
4818         for (i = 0;cachename[i];i++)
4819                 if (cachename[i] == ' ')
4820                         cachename[i] = '_';
4821
4822         // now append the shader text itself
4823         vertstrings_list[vertstrings_count++] = vertexstring;
4824         geomstrings_list[geomstrings_count++] = geometrystring;
4825         fragstrings_list[fragstrings_count++] = fragmentstring;
4826
4827         // if any sources were NULL, clear the respective list
4828         if (!vertexstring)
4829                 vertstrings_count = 0;
4830         if (!geometrystring)
4831                 geomstrings_count = 0;
4832         if (!fragmentstring)
4833                 fragstrings_count = 0;
4834
4835         vertstring_length = 0;
4836         for (i = 0;i < vertstrings_count;i++)
4837                 vertstring_length += strlen(vertstrings_list[i]);
4838         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4839         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4840                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4841
4842         geomstring_length = 0;
4843         for (i = 0;i < geomstrings_count;i++)
4844                 geomstring_length += strlen(geomstrings_list[i]);
4845         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4846         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4847                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4848
4849         fragstring_length = 0;
4850         for (i = 0;i < fragstrings_count;i++)
4851                 fragstring_length += strlen(fragstrings_list[i]);
4852         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4853         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4854                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4855
4856         // try to load the cached shader, or generate one
4857         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4858
4859         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4860                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4861         else
4862                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4863
4864         // free the strings
4865         if (vertstring)
4866                 Mem_Free(vertstring);
4867         if (geomstring)
4868                 Mem_Free(geomstring);
4869         if (fragstring)
4870                 Mem_Free(fragstring);
4871         if (vertexstring)
4872                 Mem_Free(vertexstring);
4873         if (geometrystring)
4874                 Mem_Free(geometrystring);
4875         if (fragmentstring)
4876                 Mem_Free(fragmentstring);
4877 }
4878
4879 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4880 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4881 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);}
4882 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);}
4883 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);}
4884 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);}
4885
4886 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4887 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4888 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);}
4889 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);}
4890 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);}
4891 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);}
4892
4893 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4894 {
4895         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4896         if (r_hlsl_permutation != perm)
4897         {
4898                 r_hlsl_permutation = perm;
4899                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4900                 {
4901                         if (!r_hlsl_permutation->compiled)
4902                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4903                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4904                         {
4905                                 // remove features until we find a valid permutation
4906                                 int i;
4907                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4908                                 {
4909                                         // reduce i more quickly whenever it would not remove any bits
4910                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4911                                         if (!(permutation & j))
4912                                                 continue;
4913                                         permutation -= j;
4914                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4915                                         if (!r_hlsl_permutation->compiled)
4916                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4917                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4918                                                 break;
4919                                 }
4920                                 if (i >= SHADERPERMUTATION_COUNT)
4921                                 {
4922                                         //Con_Printf("Could not find a working Cg shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4923                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4924                                         return; // no bit left to clear, entire mode is broken
4925                                 }
4926                         }
4927                 }
4928                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4929                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4930         }
4931         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4932         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4933         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4934 }
4935 #endif
4936
4937 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4938 {
4939         DPSOFTRAST_SetShader(mode, permutation);
4940         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4941         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4942         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4943 }
4944
4945 void R_GLSL_Restart_f(void)
4946 {
4947         unsigned int i, limit;
4948         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4949                 Mem_Free(glslshaderstring);
4950         glslshaderstring = NULL;
4951         if (cgshaderstring && cgshaderstring != builtincgshaderstring)
4952                 Mem_Free(cgshaderstring);
4953         cgshaderstring = NULL;
4954         if (hlslshaderstring && hlslshaderstring != builtincgshaderstring)
4955                 Mem_Free(hlslshaderstring);
4956         hlslshaderstring = NULL;
4957         switch(vid.renderpath)
4958         {
4959         case RENDERPATH_D3D9:
4960 #ifdef SUPPORTD3D
4961                 {
4962                         r_hlsl_permutation_t *p;
4963                         r_hlsl_permutation = NULL;
4964 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4965 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
4966 //                      cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4967 //                      cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
4968                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4969                         for (i = 0;i < limit;i++)
4970                         {
4971                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4972                                 {
4973                                         if (p->vertexshader)
4974                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4975                                         if (p->pixelshader)
4976                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4977                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4978                                 }
4979                         }
4980                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4981                 }
4982 #endif
4983                 break;
4984         case RENDERPATH_D3D10:
4985                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4986                 break;
4987         case RENDERPATH_D3D11:
4988                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4989                 break;
4990         case RENDERPATH_GL20:
4991                 {
4992                         r_glsl_permutation_t *p;
4993                         r_glsl_permutation = NULL;
4994                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4995                         for (i = 0;i < limit;i++)
4996                         {
4997                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4998                                 {
4999                                         GL_Backend_FreeProgram(p->program);
5000                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
5001                                 }
5002                         }
5003                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
5004                 }
5005                 break;
5006         case RENDERPATH_CGGL:
5007 #ifdef SUPPORTCG
5008                 {
5009                         r_cg_permutation_t *p;
5010                         r_cg_permutation = NULL;
5011                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5012                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_VERTEX));CHECKCGERROR CHECKGLERROR
5013                         cgGLDisableProfile(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5014                         cgGLUnbindProgram(cgGLGetLatestProfile(CG_GL_FRAGMENT));CHECKCGERROR CHECKGLERROR
5015                         limit = Mem_ExpandableArray_IndexRange(&r_cg_permutationarray);
5016                         for (i = 0;i < limit;i++)
5017                         {
5018                                 if ((p = (r_cg_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_cg_permutationarray, i)))
5019                                 {
5020                                         if (p->vprogram)
5021                                                 cgDestroyProgram(p->vprogram);
5022                                         if (p->fprogram)
5023                                                 cgDestroyProgram(p->fprogram);
5024                                         Mem_ExpandableArray_FreeRecord(&r_cg_permutationarray, (void*)p);
5025                                 }
5026                         }
5027                         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
5028                 }
5029 #endif
5030                 break;
5031         case RENDERPATH_GL13:
5032         case RENDERPATH_GL11:
5033                 break;
5034         case RENDERPATH_SOFT:
5035                 break;
5036         }
5037 }
5038
5039 void R_GLSL_DumpShader_f(void)
5040 {
5041         int i;
5042         qfile_t *file;
5043
5044         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
5045         if (file)
5046         {
5047                 FS_Print(file, "/* The engine may define the following macros:\n");
5048                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5049                 for (i = 0;i < SHADERMODE_COUNT;i++)
5050                         FS_Print(file, glslshadermodeinfo[i].pretext);
5051                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5052                         FS_Print(file, shaderpermutationinfo[i].pretext);
5053                 FS_Print(file, "*/\n");
5054                 FS_Print(file, builtinshaderstring);
5055                 FS_Close(file);
5056                 Con_Printf("glsl/default.glsl written\n");
5057         }
5058         else
5059                 Con_Printf("failed to write to glsl/default.glsl\n");
5060
5061 #ifdef SUPPORTCG
5062         file = FS_OpenRealFile("cg/default.cg", "w", false);
5063         if (file)
5064         {
5065                 FS_Print(file, "/* The engine may define the following macros:\n");
5066                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5067                 for (i = 0;i < SHADERMODE_COUNT;i++)
5068                         FS_Print(file, cgshadermodeinfo[i].pretext);
5069                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5070                         FS_Print(file, shaderpermutationinfo[i].pretext);
5071                 FS_Print(file, "*/\n");
5072                 FS_Print(file, builtincgshaderstring);
5073                 FS_Close(file);
5074                 Con_Printf("cg/default.cg written\n");
5075         }
5076         else
5077                 Con_Printf("failed to write to cg/default.cg\n");
5078 #endif
5079
5080 #ifdef SUPPORTD3D
5081         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
5082         if (file)
5083         {
5084                 FS_Print(file, "/* The engine may define the following macros:\n");
5085                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
5086                 for (i = 0;i < SHADERMODE_COUNT;i++)
5087                         FS_Print(file, hlslshadermodeinfo[i].pretext);
5088                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
5089                         FS_Print(file, shaderpermutationinfo[i].pretext);
5090                 FS_Print(file, "*/\n");
5091                 FS_Print(file, builtincgshaderstring);
5092                 FS_Close(file);
5093                 Con_Printf("hlsl/default.hlsl written\n");
5094         }
5095         else
5096                 Con_Printf("failed to write to hlsl/default.hlsl\n");
5097 #endif
5098 }
5099
5100 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
5101 {
5102         if (!second)
5103                 texturemode = GL_MODULATE;
5104         switch (vid.renderpath)
5105         {
5106         case RENDERPATH_D3D9:
5107 #ifdef SUPPORTD3D
5108                 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))));
5109                 R_Mesh_TexBind(GL20TU_FIRST , first );
5110                 R_Mesh_TexBind(GL20TU_SECOND, second);
5111 #endif
5112                 break;
5113         case RENDERPATH_D3D10:
5114                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5115                 break;
5116         case RENDERPATH_D3D11:
5117                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5118                 break;
5119         case RENDERPATH_GL20:
5120                 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))));
5121                 R_Mesh_TexBind(GL20TU_FIRST , first );
5122                 R_Mesh_TexBind(GL20TU_SECOND, second);
5123                 break;
5124         case RENDERPATH_CGGL:
5125 #ifdef SUPPORTCG
5126                 CHECKCGERROR
5127                 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))));
5128                 if (r_cg_permutation->fp_Texture_First ) CG_BindTexture(r_cg_permutation->fp_Texture_First , first );CHECKCGERROR
5129                 if (r_cg_permutation->fp_Texture_Second) CG_BindTexture(r_cg_permutation->fp_Texture_Second, second);CHECKCGERROR
5130 #endif
5131                 break;
5132         case RENDERPATH_GL13:
5133                 R_Mesh_TexBind(0, first );
5134                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
5135                 R_Mesh_TexBind(1, second);
5136                 if (second)
5137                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
5138                 break;
5139         case RENDERPATH_GL11:
5140                 R_Mesh_TexBind(0, first );
5141                 break;
5142         case RENDERPATH_SOFT:
5143                 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))));
5144                 R_Mesh_TexBind(GL20TU_FIRST , first );
5145                 R_Mesh_TexBind(GL20TU_SECOND, second);
5146                 break;
5147         }
5148 }
5149
5150 void R_SetupShader_DepthOrShadow(void)
5151 {
5152         switch (vid.renderpath)
5153         {
5154         case RENDERPATH_D3D9:
5155 #ifdef SUPPORTD3D
5156                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5157 #endif
5158                 break;
5159         case RENDERPATH_D3D10:
5160                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5161                 break;
5162         case RENDERPATH_D3D11:
5163                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5164                 break;
5165         case RENDERPATH_GL20:
5166                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
5167                 break;
5168         case RENDERPATH_CGGL:
5169 #ifdef SUPPORTCG
5170                 R_SetupShader_SetPermutationCG(SHADERMODE_DEPTH_OR_SHADOW, 0);
5171 #endif
5172                 break;
5173         case RENDERPATH_GL13:
5174                 R_Mesh_TexBind(0, 0);
5175                 R_Mesh_TexBind(1, 0);
5176                 break;
5177         case RENDERPATH_GL11:
5178                 R_Mesh_TexBind(0, 0);
5179                 break;
5180         case RENDERPATH_SOFT:
5181                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
5182                 break;
5183         }
5184 }
5185
5186 void R_SetupShader_ShowDepth(void)
5187 {
5188         switch (vid.renderpath)
5189         {
5190         case RENDERPATH_D3D9:
5191 #ifdef SUPPORTHLSL
5192                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
5193 #endif
5194                 break;
5195         case RENDERPATH_D3D10:
5196                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5197                 break;
5198         case RENDERPATH_D3D11:
5199                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5200                 break;
5201         case RENDERPATH_GL20:
5202                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
5203                 break;
5204         case RENDERPATH_CGGL:
5205 #ifdef SUPPORTCG
5206                 R_SetupShader_SetPermutationCG(SHADERMODE_SHOWDEPTH, 0);
5207 #endif
5208                 break;
5209         case RENDERPATH_GL13:
5210                 break;
5211         case RENDERPATH_GL11:
5212                 break;
5213         case RENDERPATH_SOFT:
5214                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
5215                 break;
5216         }
5217 }
5218
5219 extern qboolean r_shadow_usingdeferredprepass;
5220 extern cvar_t r_shadow_deferred_8bitrange;
5221 extern rtexture_t *r_shadow_attenuationgradienttexture;
5222 extern rtexture_t *r_shadow_attenuation2dtexture;
5223 extern rtexture_t *r_shadow_attenuation3dtexture;
5224 extern qboolean r_shadow_usingshadowmap2d;
5225 extern qboolean r_shadow_usingshadowmaportho;
5226 extern float r_shadow_shadowmap_texturescale[2];
5227 extern float r_shadow_shadowmap_parameters[4];
5228 extern qboolean r_shadow_shadowmapvsdct;
5229 extern qboolean r_shadow_shadowmapsampler;
5230 extern int r_shadow_shadowmappcf;
5231 extern rtexture_t *r_shadow_shadowmap2dtexture;
5232 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
5233 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
5234 extern matrix4x4_t r_shadow_shadowmapmatrix;
5235 extern int r_shadow_shadowmaplod; // changes for each light based on distance
5236 extern int r_shadow_prepass_width;
5237 extern int r_shadow_prepass_height;
5238 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
5239 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
5240 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
5241 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
5242 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
5243 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
5244 {
5245         // a blendfunc allows colormod if:
5246         // a) it can never keep the destination pixel invariant, or
5247         // b) it can keep the destination pixel invariant, and still can do so if colormodded
5248         // this is to prevent unintended side effects from colormod
5249
5250         // in formulas:
5251         // IF there is a (s, sa) for which for all (d, da),
5252         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5253         // THEN, for this (s, sa) and all (colormod, d, da):
5254         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
5255         // OBVIOUSLY, this means that
5256         //   s*colormod * src(s*colormod, d, sa, da) = 0
5257         //   dst(s*colormod, d, sa, da)              = 1
5258
5259         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
5260
5261         // main condition to leave dst color invariant:
5262         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
5263         //   src == GL_ZERO:
5264         //     s * 0 + d * dst(s, d, sa, da) == d
5265         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5266         //       => colormod is a problem for GL_SRC_COLOR only
5267         //   src == GL_ONE:
5268         //     s + d * dst(s, d, sa, da) == d
5269         //       => s == 0
5270         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5271         //       => colormod is never problematic for these
5272         //   src == GL_SRC_COLOR:
5273         //     s*s + d * dst(s, d, sa, da) == d
5274         //       => s == 0
5275         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5276         //       => colormod is never problematic for these
5277         //   src == GL_ONE_MINUS_SRC_COLOR:
5278         //     s*(1-s) + d * dst(s, d, sa, da) == d
5279         //       => s == 0 or s == 1
5280         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5281         //       => colormod is a problem for GL_SRC_COLOR only
5282         //   src == GL_DST_COLOR
5283         //     s*d + d * dst(s, d, sa, da) == d
5284         //       => s == 1
5285         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5286         //       => colormod is always a problem
5287         //     or
5288         //       => s == 0
5289         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5290         //       => colormod is never problematic for these
5291         //       => BUT, we do not know s! We must assume it is problematic
5292         //       then... except in GL_ONE case, where we know all invariant
5293         //       cases are fine
5294         //   src == GL_ONE_MINUS_DST_COLOR
5295         //     s*(1-d) + d * dst(s, d, sa, da) == d
5296         //       => s == 0 (1-d is impossible to handle for our desired result)
5297         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5298         //       => colormod is never problematic for these
5299         //   src == GL_SRC_ALPHA
5300         //     s*sa + d * dst(s, d, sa, da) == d
5301         //       => s == 0, or sa == 0
5302         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5303         //       => colormod breaks in the case GL_SRC_COLOR only
5304         //   src == GL_ONE_MINUS_SRC_ALPHA
5305         //     s*(1-sa) + d * dst(s, d, sa, da) == d
5306         //       => s == 0, or sa == 1
5307         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5308         //       => colormod breaks in the case GL_SRC_COLOR only
5309         //   src == GL_DST_ALPHA
5310         //     s*da + d * dst(s, d, sa, da) == d
5311         //       => s == 0
5312         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
5313         //       => colormod is never problematic for these
5314
5315         switch(src)
5316         {
5317                 case GL_ZERO:
5318                 case GL_ONE_MINUS_SRC_COLOR:
5319                 case GL_SRC_ALPHA:
5320                 case GL_ONE_MINUS_SRC_ALPHA:
5321                         if(dst == GL_SRC_COLOR)
5322                                 return false;
5323                         return true;
5324                 case GL_ONE:
5325                 case GL_SRC_COLOR:
5326                 case GL_ONE_MINUS_DST_COLOR:
5327                 case GL_DST_ALPHA:
5328                 case GL_ONE_MINUS_DST_ALPHA:
5329                         return true;
5330                 case GL_DST_COLOR:
5331                         if(dst == GL_ONE)
5332                                 return true;
5333                         return false;
5334                 default:
5335                         return false;
5336         }
5337 }
5338 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)
5339 {
5340         // select a permutation of the lighting shader appropriate to this
5341         // combination of texture, entity, light source, and fogging, only use the
5342         // minimum features necessary to avoid wasting rendering time in the
5343         // fragment shader on features that are not being used
5344         unsigned int permutation = 0;
5345         unsigned int mode = 0;
5346         qboolean allow_colormod;
5347         static float dummy_colormod[3] = {1, 1, 1};
5348         float *colormod = rsurface.colormod;
5349         float m16f[16];
5350         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
5351         if (rsurfacepass == RSURFPASS_BACKGROUND)
5352         {
5353                 // distorted background
5354                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
5355                 {
5356                         mode = SHADERMODE_WATER;
5357                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
5358                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
5359                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
5360                         {
5361                                 // this is the right thing to do for wateralpha
5362                                 GL_BlendFunc(GL_ONE, GL_ZERO);
5363                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5364                         }
5365                         else
5366                         {
5367                                 // this is the right thing to do for entity alpha
5368                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5369                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5370                         }
5371                 }
5372                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
5373                 {
5374                         mode = SHADERMODE_REFRACTION;
5375                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5376                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
5377                 }
5378                 else
5379                 {
5380                         mode = SHADERMODE_GENERIC;
5381                         permutation |= SHADERPERMUTATION_DIFFUSE;
5382                         GL_BlendFunc(GL_ONE, GL_ZERO);
5383                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5384                 }
5385                 GL_AlphaTest(false);
5386         }
5387         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
5388         {
5389                 if (r_glsl_offsetmapping.integer)
5390                 {
5391                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5392                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5393                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5394                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5395                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5396                         {
5397                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5398                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5399                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5400                         }
5401                 }
5402                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5403                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5404                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
5405                         permutation |= SHADERPERMUTATION_ALPHAKILL;
5406                 // normalmap (deferred prepass), may use alpha test on diffuse
5407                 mode = SHADERMODE_DEFERREDGEOMETRY;
5408                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5409                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5410                 GL_AlphaTest(false);
5411                 GL_BlendFunc(GL_ONE, GL_ZERO);
5412                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
5413         }
5414         else if (rsurfacepass == RSURFPASS_RTLIGHT)
5415         {
5416                 if (r_glsl_offsetmapping.integer)
5417                 {
5418                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5419                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5420                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5421                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5422                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5423                         {
5424                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5425                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5426                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5427                         }
5428                 }
5429                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5430                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5431                 // light source
5432                 mode = SHADERMODE_LIGHTSOURCE;
5433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5434                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5435                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
5436                         permutation |= SHADERPERMUTATION_CUBEFILTER;
5437                 if (diffusescale > 0)
5438                         permutation |= SHADERPERMUTATION_DIFFUSE;
5439                 if (specularscale > 0)
5440                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5441                 if (r_refdef.fogenabled)
5442                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5443                 if (rsurface.texture->colormapping)
5444                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5445                 if (r_shadow_usingshadowmap2d)
5446                 {
5447                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5448                         if(r_shadow_shadowmapvsdct)
5449                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5450
5451                         if (r_shadow_shadowmapsampler)
5452                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5453                         if (r_shadow_shadowmappcf > 1)
5454                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5455                         else if (r_shadow_shadowmappcf)
5456                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5457                 }
5458                 if (rsurface.texture->reflectmasktexture)
5459                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5460                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5461                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5462                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5463         }
5464         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5465         {
5466                 if (r_glsl_offsetmapping.integer)
5467                 {
5468                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5469                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5470                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5471                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5472                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5473                         {
5474                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5475                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5476                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5477                         }
5478                 }
5479                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5480                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5481                 // unshaded geometry (fullbright or ambient model lighting)
5482                 mode = SHADERMODE_FLATCOLOR;
5483                 ambientscale = diffusescale = specularscale = 0;
5484                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5485                         permutation |= SHADERPERMUTATION_GLOW;
5486                 if (r_refdef.fogenabled)
5487                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5488                 if (rsurface.texture->colormapping)
5489                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5490                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5491                 {
5492                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5493                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5494
5495                         if (r_shadow_shadowmapsampler)
5496                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5497                         if (r_shadow_shadowmappcf > 1)
5498                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5499                         else if (r_shadow_shadowmappcf)
5500                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5501                 }
5502                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5503                         permutation |= SHADERPERMUTATION_REFLECTION;
5504                 if (rsurface.texture->reflectmasktexture)
5505                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5506                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5507                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5508                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5509         }
5510         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5511         {
5512                 if (r_glsl_offsetmapping.integer)
5513                 {
5514                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5515                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5516                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5517                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5518                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5519                         {
5520                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5521                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5522                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5523                         }
5524                 }
5525                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5526                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5527                 // directional model lighting
5528                 mode = SHADERMODE_LIGHTDIRECTION;
5529                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5530                         permutation |= SHADERPERMUTATION_GLOW;
5531                 permutation |= SHADERPERMUTATION_DIFFUSE;
5532                 if (specularscale > 0)
5533                         permutation |= SHADERPERMUTATION_SPECULAR;
5534                 if (r_refdef.fogenabled)
5535                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5536                 if (rsurface.texture->colormapping)
5537                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5538                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5539                 {
5540                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5541                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5542
5543                         if (r_shadow_shadowmapsampler)
5544                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5545                         if (r_shadow_shadowmappcf > 1)
5546                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5547                         else if (r_shadow_shadowmappcf)
5548                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5549                 }
5550                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5551                         permutation |= SHADERPERMUTATION_REFLECTION;
5552                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5553                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5554                 if (rsurface.texture->reflectmasktexture)
5555                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5556                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5557                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5558                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5559         }
5560         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5561         {
5562                 if (r_glsl_offsetmapping.integer)
5563                 {
5564                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5565                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5566                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5567                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5568                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5569                         {
5570                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5571                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5572                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5573                         }
5574                 }
5575                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5576                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5577                 // ambient model lighting
5578                 mode = SHADERMODE_LIGHTDIRECTION;
5579                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5580                         permutation |= SHADERPERMUTATION_GLOW;
5581                 if (r_refdef.fogenabled)
5582                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5583                 if (rsurface.texture->colormapping)
5584                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5585                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5586                 {
5587                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5588                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5589
5590                         if (r_shadow_shadowmapsampler)
5591                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5592                         if (r_shadow_shadowmappcf > 1)
5593                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5594                         else if (r_shadow_shadowmappcf)
5595                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5596                 }
5597                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5598                         permutation |= SHADERPERMUTATION_REFLECTION;
5599                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5600                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5601                 if (rsurface.texture->reflectmasktexture)
5602                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5603                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5604                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5605                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5606         }
5607         else
5608         {
5609                 if (r_glsl_offsetmapping.integer)
5610                 {
5611                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5612                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5613                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5614                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5615                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5616                         {
5617                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5618                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5619                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5620                         }
5621                 }
5622                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5623                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5624                 // lightmapped wall
5625                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5626                         permutation |= SHADERPERMUTATION_GLOW;
5627                 if (r_refdef.fogenabled)
5628                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5629                 if (rsurface.texture->colormapping)
5630                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5631                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5632                 {
5633                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5634                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5635
5636                         if (r_shadow_shadowmapsampler)
5637                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5638                         if (r_shadow_shadowmappcf > 1)
5639                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5640                         else if (r_shadow_shadowmappcf)
5641                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5642                 }
5643                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5644                         permutation |= SHADERPERMUTATION_REFLECTION;
5645                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5646                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5647                 if (rsurface.texture->reflectmasktexture)
5648                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5649                 if (FAKELIGHT_ENABLED)
5650                 {
5651                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5652                         mode = SHADERMODE_FAKELIGHT;
5653                         permutation |= SHADERPERMUTATION_DIFFUSE;
5654                         if (specularscale > 0)
5655                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5656                 }
5657                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5658                 {
5659                         // deluxemapping (light direction texture)
5660                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5661                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5662                         else
5663                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5664                         permutation |= SHADERPERMUTATION_DIFFUSE;
5665                         if (specularscale > 0)
5666                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5667                 }
5668                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5669                 {
5670                         // fake deluxemapping (uniform light direction in tangentspace)
5671                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5672                         permutation |= SHADERPERMUTATION_DIFFUSE;
5673                         if (specularscale > 0)
5674                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5675                 }
5676                 else if (rsurface.uselightmaptexture)
5677                 {
5678                         // ordinary lightmapping (q1bsp, q3bsp)
5679                         mode = SHADERMODE_LIGHTMAP;
5680                 }
5681                 else
5682                 {
5683                         // ordinary vertex coloring (q3bsp)
5684                         mode = SHADERMODE_VERTEXCOLOR;
5685                 }
5686                 GL_AlphaTest((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
5687                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5688                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5689         }
5690         if(!allow_colormod)
5691                 colormod = dummy_colormod;
5692         switch(vid.renderpath)
5693         {
5694         case RENDERPATH_D3D9:
5695 #ifdef SUPPORTD3D
5696                 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);
5697                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5698                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5699                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5700                 if (mode == SHADERMODE_LIGHTSOURCE)
5701                 {
5702                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5703                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5704                 }
5705                 else
5706                 {
5707                         if (mode == SHADERMODE_LIGHTDIRECTION)
5708                         {
5709                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5710                         }
5711                 }
5712                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5713                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5714                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5715                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5716                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5717
5718                 if (mode == SHADERMODE_LIGHTSOURCE)
5719                 {
5720                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5721                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5722                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5723                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5724                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5725
5726                         // additive passes are only darkened by fog, not tinted
5727                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5728                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5729                 }
5730                 else
5731                 {
5732                         if (mode == SHADERMODE_FLATCOLOR)
5733                         {
5734                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5735                         }
5736                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5737                         {
5738                                 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]);
5739                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5740                                 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);
5741                                 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);
5742                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5743                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5744                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5745                         }
5746                         else
5747                         {
5748                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5749                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5750                                 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);
5751                                 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);
5752                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5753                         }
5754                         // additive passes are only darkened by fog, not tinted
5755                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5756                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5757                         else
5758                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5759                         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);
5760                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5761                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5762                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5763                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5764                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5765                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5766                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5767                         if (mode == SHADERMODE_WATER)
5768                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5769                 }
5770                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5771                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5772                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5773                 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));
5774                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5775                 if (rsurface.texture->pantstexture)
5776                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5777                 else
5778                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5779                 if (rsurface.texture->shirttexture)
5780                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5781                 else
5782                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5783                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5784                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5785                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5786                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5787                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5788                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5789                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5790
5791                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5792                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5793                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5794                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5795                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5796                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5797                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5798                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5799                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5800                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5801                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5802                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5803                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5804                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5805                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5806                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5807                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5808                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5809                 {
5810                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5811                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5812                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5813                 }
5814                 else
5815                 {
5816                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5817                 }
5818 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5819 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5820                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5821                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5822                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5823                 {
5824                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5825                         if (rsurface.rtlight)
5826                         {
5827                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5828                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5829                         }
5830                 }
5831 #endif
5832                 break;
5833         case RENDERPATH_D3D10:
5834                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5835                 break;
5836         case RENDERPATH_D3D11:
5837                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5838                 break;
5839         case RENDERPATH_GL20:
5840                 if (!vid.useinterleavedarrays)
5841                 {
5842                         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);
5843                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5844                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5845                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5846                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5847                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5848                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5849                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5850                 }
5851                 else
5852                 {
5853                         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);
5854                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5855                 }
5856                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5857                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5858                 if (mode == SHADERMODE_LIGHTSOURCE)
5859                 {
5860                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5861                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5862                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5863                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5864                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5865                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5866         
5867                         // additive passes are only darkened by fog, not tinted
5868                         if (r_glsl_permutation->loc_FogColor >= 0)
5869                                 qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5870                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5871                 }
5872                 else
5873                 {
5874                         if (mode == SHADERMODE_FLATCOLOR)
5875                         {
5876                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5877                         }
5878                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5879                         {
5880                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(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]);
5881                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5882                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(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);
5883                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(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);
5884                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5885                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3fARB(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]);
5886                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3fARB(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5887                         }
5888                         else
5889                         {
5890                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5891                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5892                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3fARB(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);
5893                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3fARB(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);
5894                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3fARB(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5895                         }
5896                         // additive passes are only darkened by fog, not tinted
5897                         if (r_glsl_permutation->loc_FogColor >= 0)
5898                         {
5899                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5900                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5901                                 else
5902                                         qglUniform3fARB(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5903                         }
5904                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4fARB(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);
5905                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5906                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4fARB(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5907                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4fARB(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]);
5908                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4fARB(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]);
5909                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5910                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1fARB(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5911                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1fARB(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5912                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2fARB(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5913                 }
5914                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5915                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5916                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fvARB(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5917                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2fARB(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5918                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4fARB(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]);
5919
5920                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3fARB(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5921                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1fARB(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));
5922                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3fARB(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5923                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5924                 {
5925                         if (rsurface.texture->pantstexture)
5926                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5927                         else
5928                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5929                 }
5930                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5931                 {
5932                         if (rsurface.texture->shirttexture)
5933                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5934                         else
5935                                 qglUniform3fARB(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5936                 }
5937                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4fARB(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5938                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5939                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5940                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1fARB(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5941                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1fARB(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5942                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2fARB(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5943                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5944
5945         //      if (r_glsl_permutation->loc_Texture_First           >= 0) R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
5946         //      if (r_glsl_permutation->loc_Texture_Second          >= 0) R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
5947         //      if (r_glsl_permutation->loc_Texture_GammaRamps      >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
5948                 if (r_glsl_permutation->loc_Texture_Normal          >= 0) R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5949                 if (r_glsl_permutation->loc_Texture_Color           >= 0) R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5950                 if (r_glsl_permutation->loc_Texture_Gloss           >= 0) R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5951                 if (r_glsl_permutation->loc_Texture_Glow            >= 0) R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5952                 if (r_glsl_permutation->loc_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5953                 if (r_glsl_permutation->loc_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5954                 if (r_glsl_permutation->loc_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5955                 if (r_glsl_permutation->loc_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5956                 if (r_glsl_permutation->loc_Texture_Pants           >= 0) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5957                 if (r_glsl_permutation->loc_Texture_Shirt           >= 0) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5958                 if (r_glsl_permutation->loc_Texture_ReflectMask     >= 0) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5959                 if (r_glsl_permutation->loc_Texture_ReflectCube     >= 0) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5960                 if (r_glsl_permutation->loc_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5961                 if (r_glsl_permutation->loc_Texture_FogMask         >= 0) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5962                 if (r_glsl_permutation->loc_Texture_Lightmap        >= 0) R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5963                 if (r_glsl_permutation->loc_Texture_Deluxemap       >= 0) R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5964                 if (r_glsl_permutation->loc_Texture_Attenuation     >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5965                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5966                 {
5967                         if(r_glsl_permutation->loc_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5968                         else if(r_glsl_permutation->loc_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5969                         if(r_glsl_permutation->loc_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5970                 }
5971                 else
5972                 {
5973                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5974                 }
5975 //              if (r_glsl_permutation->loc_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5976 //              if (r_glsl_permutation->loc_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5977                 if (r_glsl_permutation->loc_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5978                 if (r_glsl_permutation->loc_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5979                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5980                 {
5981                         if (r_glsl_permutation->loc_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
5982                         if (rsurface.rtlight)
5983                         {
5984                                 if (r_glsl_permutation->loc_Texture_Cube            >= 0) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5985                                 if (r_glsl_permutation->loc_Texture_CubeProjection  >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5986                         }
5987                 }
5988                 CHECKGLERROR
5989                 break;
5990         case RENDERPATH_CGGL:
5991 #ifdef SUPPORTCG
5992                 if (!vid.useinterleavedarrays)
5993                 {
5994                         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);
5995                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5996                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5997                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5998                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5999                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
6000                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
6001                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
6002                 }
6003                 else
6004                 {
6005                         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);
6006                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
6007                 }
6008                 R_SetupShader_SetPermutationCG(mode, permutation);
6009                 if (r_cg_permutation->fp_ModelToReflectCube) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->fp_ModelToReflectCube, m16f);}CHECKCGERROR
6010                 if (mode == SHADERMODE_LIGHTSOURCE)
6011                 {
6012                         if (r_cg_permutation->vp_ModelToLight) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelToLight, m16f);}CHECKCGERROR
6013                         if (r_cg_permutation->vp_LightPosition) cgGLSetParameter3f(r_cg_permutation->vp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6014                 }
6015                 else
6016                 {
6017                         if (mode == SHADERMODE_LIGHTDIRECTION)
6018                         {
6019                                 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
6020                         }
6021                 }
6022                 if (r_cg_permutation->vp_TexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_TexMatrix, m16f);}CHECKCGERROR
6023                 if (r_cg_permutation->vp_BackgroundTexMatrix) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_BackgroundTexMatrix, m16f);}CHECKCGERROR
6024                 if (r_cg_permutation->vp_ShadowMapMatrix) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);cgGLSetMatrixParameterfc(r_cg_permutation->vp_ShadowMapMatrix, m16f);}CHECKGLERROR
6025                 if (r_cg_permutation->vp_EyePosition) cgGLSetParameter3f(r_cg_permutation->vp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6026                 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
6027                 CHECKGLERROR
6028
6029                 if (mode == SHADERMODE_LIGHTSOURCE)
6030                 {
6031                         if (r_cg_permutation->fp_LightPosition) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);CHECKCGERROR
6032                         if (r_cg_permutation->fp_LightColor) cgGLSetParameter3f(r_cg_permutation->fp_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);CHECKCGERROR
6033                         if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);CHECKCGERROR
6034                         if (r_cg_permutation->fp_Color_Diffuse) cgGLSetParameter3f(r_cg_permutation->fp_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);CHECKCGERROR
6035                         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
6036
6037                         // additive passes are only darkened by fog, not tinted
6038                         if (r_cg_permutation->fp_FogColor) cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);CHECKCGERROR
6039                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6040                 }
6041                 else
6042                 {
6043                         if (mode == SHADERMODE_FLATCOLOR)
6044                         {
6045                                 if (r_cg_permutation->fp_Color_Ambient) cgGLSetParameter3f(r_cg_permutation->fp_Color_Ambient, colormod[0], colormod[1], colormod[2]);CHECKCGERROR
6046                         }
6047                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6048                         {
6049                                 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
6050                                 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
6051                                 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
6052                                 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
6053                                 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
6054                                 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
6055                                 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
6056                         }
6057                         else
6058                         {
6059                                 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
6060                                 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
6061                                 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
6062                                 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
6063                                 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
6064                         }
6065                         // additive passes are only darkened by fog, not tinted
6066                         if (r_cg_permutation->fp_FogColor)
6067                         {
6068                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6069                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, 0, 0, 0);
6070                                 else
6071                                         cgGLSetParameter3f(r_cg_permutation->fp_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6072                                 CHECKCGERROR
6073                         }
6074                         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
6075                         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
6076                         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
6077                         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
6078                         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
6079                         if (r_cg_permutation->fp_ReflectFactor) cgGLSetParameter1f(r_cg_permutation->fp_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);CHECKCGERROR
6080                         if (r_cg_permutation->fp_ReflectOffset) cgGLSetParameter1f(r_cg_permutation->fp_ReflectOffset, rsurface.texture->reflectmin);CHECKCGERROR
6081                         if (r_cg_permutation->fp_SpecularPower) cgGLSetParameter1f(r_cg_permutation->fp_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));CHECKCGERROR
6082                         if (r_cg_permutation->fp_NormalmapScrollBlend) cgGLSetParameter2f(r_cg_permutation->fp_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6083                 }
6084                 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
6085                 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
6086                 if (r_cg_permutation->fp_Color_Glow) cgGLSetParameter3f(r_cg_permutation->fp_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);CHECKCGERROR
6087                 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
6088                 if (r_cg_permutation->fp_EyePosition) cgGLSetParameter3f(r_cg_permutation->fp_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);CHECKCGERROR
6089                 if (r_cg_permutation->fp_Color_Pants)
6090                 {
6091                         if (rsurface.texture->pantstexture)
6092                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6093                         else
6094                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Pants, 0, 0, 0);
6095                         CHECKCGERROR
6096                 }
6097                 if (r_cg_permutation->fp_Color_Shirt)
6098                 {
6099                         if (rsurface.texture->shirttexture)
6100                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6101                         else
6102                                 cgGLSetParameter3f(r_cg_permutation->fp_Color_Shirt, 0, 0, 0);
6103                         CHECKCGERROR
6104                 }
6105                 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
6106                 if (r_cg_permutation->fp_FogPlaneViewDist) cgGLSetParameter1f(r_cg_permutation->fp_FogPlaneViewDist, rsurface.fogplaneviewdist);CHECKCGERROR
6107                 if (r_cg_permutation->fp_FogRangeRecip) cgGLSetParameter1f(r_cg_permutation->fp_FogRangeRecip, rsurface.fograngerecip);CHECKCGERROR
6108                 if (r_cg_permutation->fp_FogHeightFade) cgGLSetParameter1f(r_cg_permutation->fp_FogHeightFade, rsurface.fogheightfade);CHECKCGERROR
6109                 if (r_cg_permutation->fp_OffsetMapping_Scale) cgGLSetParameter1f(r_cg_permutation->fp_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);CHECKCGERROR
6110                 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
6111                 if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6112
6113         //      if (r_cg_permutation->fp_Texture_First          ) CG_BindTexture(r_cg_permutation->fp_Texture_First          , r_texture_white                                     );CHECKCGERROR
6114         //      if (r_cg_permutation->fp_Texture_Second         ) CG_BindTexture(r_cg_permutation->fp_Texture_Second         , r_texture_white                                     );CHECKCGERROR
6115         //      if (r_cg_permutation->fp_Texture_GammaRamps     ) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps     , r_texture_gammaramps                                );CHECKCGERROR
6116                 if (r_cg_permutation->fp_Texture_Normal         ) CG_BindTexture(r_cg_permutation->fp_Texture_Normal         , rsurface.texture->nmaptexture                       );CHECKCGERROR
6117                 if (r_cg_permutation->fp_Texture_Color          ) CG_BindTexture(r_cg_permutation->fp_Texture_Color          , rsurface.texture->basetexture                       );CHECKCGERROR
6118                 if (r_cg_permutation->fp_Texture_Gloss          ) CG_BindTexture(r_cg_permutation->fp_Texture_Gloss          , rsurface.texture->glosstexture                      );CHECKCGERROR
6119                 if (r_cg_permutation->fp_Texture_Glow           ) CG_BindTexture(r_cg_permutation->fp_Texture_Glow           , rsurface.texture->glowtexture                       );CHECKCGERROR
6120                 if (r_cg_permutation->fp_Texture_SecondaryNormal) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryNormal, rsurface.texture->backgroundnmaptexture             );CHECKCGERROR
6121                 if (r_cg_permutation->fp_Texture_SecondaryColor ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryColor , rsurface.texture->backgroundbasetexture             );CHECKCGERROR
6122                 if (r_cg_permutation->fp_Texture_SecondaryGloss ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGloss , rsurface.texture->backgroundglosstexture            );CHECKCGERROR
6123                 if (r_cg_permutation->fp_Texture_SecondaryGlow  ) CG_BindTexture(r_cg_permutation->fp_Texture_SecondaryGlow  , rsurface.texture->backgroundglowtexture             );CHECKCGERROR
6124                 if (r_cg_permutation->fp_Texture_Pants          ) CG_BindTexture(r_cg_permutation->fp_Texture_Pants          , rsurface.texture->pantstexture                      );CHECKCGERROR
6125                 if (r_cg_permutation->fp_Texture_Shirt          ) CG_BindTexture(r_cg_permutation->fp_Texture_Shirt          , rsurface.texture->shirttexture                      );CHECKCGERROR
6126                 if (r_cg_permutation->fp_Texture_ReflectMask    ) CG_BindTexture(r_cg_permutation->fp_Texture_ReflectMask    , rsurface.texture->reflectmasktexture                );CHECKCGERROR
6127                 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
6128                 if (r_cg_permutation->fp_Texture_FogHeightTexture) CG_BindTexture(r_cg_permutation->fp_Texture_FogHeightTexture, r_texture_fogheighttexture                         );CHECKCGERROR
6129                 if (r_cg_permutation->fp_Texture_FogMask        ) CG_BindTexture(r_cg_permutation->fp_Texture_FogMask        , r_texture_fogattenuation                            );CHECKCGERROR
6130                 if (r_cg_permutation->fp_Texture_Lightmap       ) CG_BindTexture(r_cg_permutation->fp_Texture_Lightmap       , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);CHECKCGERROR
6131                 if (r_cg_permutation->fp_Texture_Deluxemap      ) CG_BindTexture(r_cg_permutation->fp_Texture_Deluxemap      , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);CHECKCGERROR
6132                 if (r_cg_permutation->fp_Texture_Attenuation    ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6133                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6134                 {
6135                         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
6136                         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
6137                         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
6138                 }
6139                 else
6140                 {
6141                         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
6142                 }
6143                 if (r_cg_permutation->fp_Texture_ScreenDepth    ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6144                 if (r_cg_permutation->fp_Texture_ScreenNormalMap) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6145                 if (r_cg_permutation->fp_Texture_ScreenDiffuse  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDiffuse  , r_shadow_prepasslightingdiffusetexture              );CHECKCGERROR
6146                 if (r_cg_permutation->fp_Texture_ScreenSpecular ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenSpecular , r_shadow_prepasslightingspeculartexture             );CHECKCGERROR
6147                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6148                 {
6149                         if (r_cg_permutation->fp_Texture_ShadowMap2D    ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6150                         if (rsurface.rtlight)
6151                         {
6152                                 if (r_cg_permutation->fp_Texture_Cube           ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6153                                 if (r_cg_permutation->fp_Texture_CubeProjection ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6154                         }
6155                 }
6156
6157                 CHECKGLERROR
6158 #endif
6159                 break;
6160         case RENDERPATH_GL13:
6161         case RENDERPATH_GL11:
6162                 break;
6163         case RENDERPATH_SOFT:
6164                 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);
6165                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
6166                 R_SetupShader_SetPermutationSoft(mode, permutation);
6167                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
6168                 if (mode == SHADERMODE_LIGHTSOURCE)
6169                 {
6170                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
6171                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
6172                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
6173                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
6174                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
6175                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
6176         
6177                         // additive passes are only darkened by fog, not tinted
6178                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6179                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6180                 }
6181                 else
6182                 {
6183                         if (mode == SHADERMODE_FLATCOLOR)
6184                         {
6185                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
6186                         }
6187                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6188                         {
6189                                 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]);
6190                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
6191                                 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);
6192                                 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);
6193                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6194                                 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]);
6195                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
6196                         }
6197                         else
6198                         {
6199                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
6200                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
6201                                 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);
6202                                 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);
6203                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6204                         }
6205                         // additive passes are only darkened by fog, not tinted
6206                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
6207                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6208                         else
6209                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6210                         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);
6211                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
6212                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
6213                         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]);
6214                         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]);
6215                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
6216                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
6217                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6218                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6219                 }
6220                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
6221                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
6222                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
6223                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6224                 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]);
6225
6226                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
6227                 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));
6228                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
6229                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
6230                 {
6231                         if (rsurface.texture->pantstexture)
6232                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6233                         else
6234                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
6235                 }
6236                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
6237                 {
6238                         if (rsurface.texture->shirttexture)
6239                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6240                         else
6241                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
6242                 }
6243                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
6244                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
6245                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
6246                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
6247                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6248                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6249                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6250
6251                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
6252                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
6253                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
6254                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
6255                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
6256                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
6257                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
6258                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
6259                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
6260                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
6261                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
6262                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6263                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
6264                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
6265                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6266                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6267                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
6268                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6269                 {
6270                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6271                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6272                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6273                 }
6274                 else
6275                 {
6276                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6277                 }
6278 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6279 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6280                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6281                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6282                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6283                 {
6284                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
6285                         if (rsurface.rtlight)
6286                         {
6287                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6288                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6289                         }
6290                 }
6291                 break;
6292         }
6293 }
6294
6295 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6296 {
6297         // select a permutation of the lighting shader appropriate to this
6298         // combination of texture, entity, light source, and fogging, only use the
6299         // minimum features necessary to avoid wasting rendering time in the
6300         // fragment shader on features that are not being used
6301         unsigned int permutation = 0;
6302         unsigned int mode = 0;
6303         const float *lightcolorbase = rtlight->currentcolor;
6304         float ambientscale = rtlight->ambientscale;
6305         float diffusescale = rtlight->diffusescale;
6306         float specularscale = rtlight->specularscale;
6307         // this is the location of the light in view space
6308         vec3_t viewlightorigin;
6309         // this transforms from view space (camera) to light space (cubemap)
6310         matrix4x4_t viewtolight;
6311         matrix4x4_t lighttoview;
6312         float viewtolight16f[16];
6313         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6314         // light source
6315         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6316         if (rtlight->currentcubemap != r_texture_whitecube)
6317                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6318         if (diffusescale > 0)
6319                 permutation |= SHADERPERMUTATION_DIFFUSE;
6320         if (specularscale > 0)
6321                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6322         if (r_shadow_usingshadowmap2d)
6323         {
6324                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6325                 if (r_shadow_shadowmapvsdct)
6326                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6327
6328                 if (r_shadow_shadowmapsampler)
6329                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6330                 if (r_shadow_shadowmappcf > 1)
6331                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6332                 else if (r_shadow_shadowmappcf)
6333                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6334         }
6335         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6336         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6337         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6338         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6339         switch(vid.renderpath)
6340         {
6341         case RENDERPATH_D3D9:
6342 #ifdef SUPPORTD3D
6343                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6344                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6345                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6346                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6347                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6348                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6349                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6350                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6351                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6352                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6353                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6354
6355                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6356                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6357                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6358                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6359                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6360                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6361 #endif
6362                 break;
6363         case RENDERPATH_D3D10:
6364                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6365                 break;
6366         case RENDERPATH_D3D11:
6367                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6368                 break;
6369         case RENDERPATH_GL20:
6370                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6371                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6372                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6373                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6374                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6375                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3fARB(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6376                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6377                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4fARB(       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]);
6378                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1fARB(       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));
6379                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2fARB(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6380                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6381
6382                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6383                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6384                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6385                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6386                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6387                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6388                 break;
6389         case RENDERPATH_CGGL:
6390 #ifdef SUPPORTCG
6391                 R_SetupShader_SetPermutationCG(mode, permutation);
6392                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6393                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6394                 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
6395                 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
6396                 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
6397                 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
6398                 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
6399                 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
6400                 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
6401                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6402
6403                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6404                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6405                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6406                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6407                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6408                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6409 #endif
6410                 break;
6411         case RENDERPATH_GL13:
6412         case RENDERPATH_GL11:
6413                 break;
6414         case RENDERPATH_SOFT:
6415                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6416                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6417                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
6418                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6419                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6420                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6421                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6422                 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]);
6423                 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));
6424                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6425                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6426
6427                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6428                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6429                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6430                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6431                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6432                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6433                 break;
6434         }
6435 }
6436
6437 #define SKINFRAME_HASH 1024
6438
6439 typedef struct
6440 {
6441         int loadsequence; // incremented each level change
6442         memexpandablearray_t array;
6443         skinframe_t *hash[SKINFRAME_HASH];
6444 }
6445 r_skinframe_t;
6446 r_skinframe_t r_skinframe;
6447
6448 void R_SkinFrame_PrepareForPurge(void)
6449 {
6450         r_skinframe.loadsequence++;
6451         // wrap it without hitting zero
6452         if (r_skinframe.loadsequence >= 200)
6453                 r_skinframe.loadsequence = 1;
6454 }
6455
6456 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6457 {
6458         if (!skinframe)
6459                 return;
6460         // mark the skinframe as used for the purging code
6461         skinframe->loadsequence = r_skinframe.loadsequence;
6462 }
6463
6464 void R_SkinFrame_Purge(void)
6465 {
6466         int i;
6467         skinframe_t *s;
6468         for (i = 0;i < SKINFRAME_HASH;i++)
6469         {
6470                 for (s = r_skinframe.hash[i];s;s = s->next)
6471                 {
6472                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6473                         {
6474                                 if (s->merged == s->base)
6475                                         s->merged = NULL;
6476                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6477                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6478                                 R_PurgeTexture(s->merged);s->merged = NULL;
6479                                 R_PurgeTexture(s->base  );s->base   = NULL;
6480                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6481                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6482                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6483                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6484                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6485                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6486                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6487                                 s->loadsequence = 0;
6488                         }
6489                 }
6490         }
6491 }
6492
6493 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6494         skinframe_t *item;
6495         char basename[MAX_QPATH];
6496
6497         Image_StripImageExtension(name, basename, sizeof(basename));
6498
6499         if( last == NULL ) {
6500                 int hashindex;
6501                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6502                 item = r_skinframe.hash[hashindex];
6503         } else {
6504                 item = last->next;
6505         }
6506
6507         // linearly search through the hash bucket
6508         for( ; item ; item = item->next ) {
6509                 if( !strcmp( item->basename, basename ) ) {
6510                         return item;
6511                 }
6512         }
6513         return NULL;
6514 }
6515
6516 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6517 {
6518         skinframe_t *item;
6519         int hashindex;
6520         char basename[MAX_QPATH];
6521
6522         Image_StripImageExtension(name, basename, sizeof(basename));
6523
6524         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6525         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6526                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6527                         break;
6528
6529         if (!item) {
6530                 rtexture_t *dyntexture;
6531                 // check whether its a dynamic texture
6532                 dyntexture = CL_GetDynTexture( basename );
6533                 if (!add && !dyntexture)
6534                         return NULL;
6535                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6536                 memset(item, 0, sizeof(*item));
6537                 strlcpy(item->basename, basename, sizeof(item->basename));
6538                 item->base = dyntexture; // either NULL or dyntexture handle
6539                 item->textureflags = textureflags;
6540                 item->comparewidth = comparewidth;
6541                 item->compareheight = compareheight;
6542                 item->comparecrc = comparecrc;
6543                 item->next = r_skinframe.hash[hashindex];
6544                 r_skinframe.hash[hashindex] = item;
6545         }
6546         else if( item->base == NULL )
6547         {
6548                 rtexture_t *dyntexture;
6549                 // check whether its a dynamic texture
6550                 // 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]
6551                 dyntexture = CL_GetDynTexture( basename );
6552                 item->base = dyntexture; // either NULL or dyntexture handle
6553         }
6554
6555         R_SkinFrame_MarkUsed(item);
6556         return item;
6557 }
6558
6559 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6560         { \
6561                 unsigned long long avgcolor[5], wsum; \
6562                 int pix, comp, w; \
6563                 avgcolor[0] = 0; \
6564                 avgcolor[1] = 0; \
6565                 avgcolor[2] = 0; \
6566                 avgcolor[3] = 0; \
6567                 avgcolor[4] = 0; \
6568                 wsum = 0; \
6569                 for(pix = 0; pix < cnt; ++pix) \
6570                 { \
6571                         w = 0; \
6572                         for(comp = 0; comp < 3; ++comp) \
6573                                 w += getpixel; \
6574                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6575                         { \
6576                                 ++wsum; \
6577                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6578                                 w = getpixel; \
6579                                 for(comp = 0; comp < 3; ++comp) \
6580                                         avgcolor[comp] += getpixel * w; \
6581                                 avgcolor[3] += w; \
6582                         } \
6583                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6584                         avgcolor[4] += getpixel; \
6585                 } \
6586                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6587                         avgcolor[3] = 1; \
6588                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6589                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6590                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6591                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6592         }
6593
6594 extern cvar_t gl_picmip;
6595 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6596 {
6597         int j;
6598         unsigned char *pixels;
6599         unsigned char *bumppixels;
6600         unsigned char *basepixels = NULL;
6601         int basepixels_width = 0;
6602         int basepixels_height = 0;
6603         skinframe_t *skinframe;
6604         rtexture_t *ddsbase = NULL;
6605         qboolean ddshasalpha = false;
6606         float ddsavgcolor[4];
6607         char basename[MAX_QPATH];
6608         int miplevel = R_PicmipForFlags(textureflags);
6609         int savemiplevel = miplevel;
6610         int mymiplevel;
6611
6612         if (cls.state == ca_dedicated)
6613                 return NULL;
6614
6615         // return an existing skinframe if already loaded
6616         // if loading of the first image fails, don't make a new skinframe as it
6617         // would cause all future lookups of this to be missing
6618         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6619         if (skinframe && skinframe->base)
6620                 return skinframe;
6621
6622         Image_StripImageExtension(name, basename, sizeof(basename));
6623
6624         // check for DDS texture file first
6625         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6626         {
6627                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6628                 if (basepixels == NULL)
6629                         return NULL;
6630         }
6631
6632         // FIXME handle miplevel
6633
6634         if (developer_loading.integer)
6635                 Con_Printf("loading skin \"%s\"\n", name);
6636
6637         // we've got some pixels to store, so really allocate this new texture now
6638         if (!skinframe)
6639                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6640         skinframe->stain = NULL;
6641         skinframe->merged = NULL;
6642         skinframe->base = NULL;
6643         skinframe->pants = NULL;
6644         skinframe->shirt = NULL;
6645         skinframe->nmap = NULL;
6646         skinframe->gloss = NULL;
6647         skinframe->glow = NULL;
6648         skinframe->fog = NULL;
6649         skinframe->reflect = NULL;
6650         skinframe->hasalpha = false;
6651
6652         if (ddsbase)
6653         {
6654                 skinframe->base = ddsbase;
6655                 skinframe->hasalpha = ddshasalpha;
6656                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6657                 if (r_loadfog && skinframe->hasalpha)
6658                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6659                 //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]);
6660         }
6661         else
6662         {
6663                 basepixels_width = image_width;
6664                 basepixels_height = image_height;
6665                 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);
6666                 if (textureflags & TEXF_ALPHA)
6667                 {
6668                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6669                         {
6670                                 if (basepixels[j] < 255)
6671                                 {
6672                                         skinframe->hasalpha = true;
6673                                         break;
6674                                 }
6675                         }
6676                         if (r_loadfog && skinframe->hasalpha)
6677                         {
6678                                 // has transparent pixels
6679                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6680                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6681                                 {
6682                                         pixels[j+0] = 255;
6683                                         pixels[j+1] = 255;
6684                                         pixels[j+2] = 255;
6685                                         pixels[j+3] = basepixels[j+3];
6686                                 }
6687                                 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);
6688                                 Mem_Free(pixels);
6689                         }
6690                 }
6691                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6692                 //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]);
6693                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6694                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6695                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6696                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6697         }
6698
6699         if (r_loaddds)
6700         {
6701                 mymiplevel = savemiplevel;
6702                 if (r_loadnormalmap)
6703                         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);
6704                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6705                 if (r_loadgloss)
6706                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6707                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6708                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6709                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6710         }
6711
6712         // _norm is the name used by tenebrae and has been adopted as standard
6713         if (r_loadnormalmap && skinframe->nmap == NULL)
6714         {
6715                 mymiplevel = savemiplevel;
6716                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6717                 {
6718                         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);
6719                         Mem_Free(pixels);
6720                         pixels = NULL;
6721                 }
6722                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6723                 {
6724                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6725                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6726                         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);
6727                         Mem_Free(pixels);
6728                         Mem_Free(bumppixels);
6729                 }
6730                 else if (r_shadow_bumpscale_basetexture.value > 0)
6731                 {
6732                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6733                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6734                         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);
6735                         Mem_Free(pixels);
6736                 }
6737                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6738                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6739         }
6740
6741         // _luma is supported only for tenebrae compatibility
6742         // _glow is the preferred name
6743         mymiplevel = savemiplevel;
6744         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))))
6745         {
6746                 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);
6747                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6748                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6749                 Mem_Free(pixels);pixels = NULL;
6750         }
6751
6752         mymiplevel = savemiplevel;
6753         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6754         {
6755                 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);
6756                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6757                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6758                 Mem_Free(pixels);
6759                 pixels = NULL;
6760         }
6761
6762         mymiplevel = savemiplevel;
6763         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6764         {
6765                 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);
6766                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6767                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6768                 Mem_Free(pixels);
6769                 pixels = NULL;
6770         }
6771
6772         mymiplevel = savemiplevel;
6773         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6774         {
6775                 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);
6776                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6777                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6778                 Mem_Free(pixels);
6779                 pixels = NULL;
6780         }
6781
6782         mymiplevel = savemiplevel;
6783         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6784         {
6785                 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);
6786                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6787                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6788                 Mem_Free(pixels);
6789                 pixels = NULL;
6790         }
6791
6792         if (basepixels)
6793                 Mem_Free(basepixels);
6794
6795         return skinframe;
6796 }
6797
6798 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6799 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6800 {
6801         int i;
6802         unsigned char *temp1, *temp2;
6803         skinframe_t *skinframe;
6804
6805         if (cls.state == ca_dedicated)
6806                 return NULL;
6807
6808         // if already loaded just return it, otherwise make a new skinframe
6809         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6810         if (skinframe && skinframe->base)
6811                 return skinframe;
6812
6813         skinframe->stain = NULL;
6814         skinframe->merged = NULL;
6815         skinframe->base = NULL;
6816         skinframe->pants = NULL;
6817         skinframe->shirt = NULL;
6818         skinframe->nmap = NULL;
6819         skinframe->gloss = NULL;
6820         skinframe->glow = NULL;
6821         skinframe->fog = NULL;
6822         skinframe->reflect = NULL;
6823         skinframe->hasalpha = false;
6824
6825         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6826         if (!skindata)
6827                 return NULL;
6828
6829         if (developer_loading.integer)
6830                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6831
6832         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6833         {
6834                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6835                 temp2 = temp1 + width * height * 4;
6836                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6837                 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);
6838                 Mem_Free(temp1);
6839         }
6840         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6841         if (textureflags & TEXF_ALPHA)
6842         {
6843                 for (i = 3;i < width * height * 4;i += 4)
6844                 {
6845                         if (skindata[i] < 255)
6846                         {
6847                                 skinframe->hasalpha = true;
6848                                 break;
6849                         }
6850                 }
6851                 if (r_loadfog && skinframe->hasalpha)
6852                 {
6853                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6854                         memcpy(fogpixels, skindata, width * height * 4);
6855                         for (i = 0;i < width * height * 4;i += 4)
6856                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6857                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6858                         Mem_Free(fogpixels);
6859                 }
6860         }
6861
6862         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6863         //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]);
6864
6865         return skinframe;
6866 }
6867
6868 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6869 {
6870         int i;
6871         int featuresmask;
6872         skinframe_t *skinframe;
6873
6874         if (cls.state == ca_dedicated)
6875                 return NULL;
6876
6877         // if already loaded just return it, otherwise make a new skinframe
6878         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6879         if (skinframe && skinframe->base)
6880                 return skinframe;
6881
6882         skinframe->stain = NULL;
6883         skinframe->merged = NULL;
6884         skinframe->base = NULL;
6885         skinframe->pants = NULL;
6886         skinframe->shirt = NULL;
6887         skinframe->nmap = NULL;
6888         skinframe->gloss = NULL;
6889         skinframe->glow = NULL;
6890         skinframe->fog = NULL;
6891         skinframe->reflect = NULL;
6892         skinframe->hasalpha = false;
6893
6894         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6895         if (!skindata)
6896                 return NULL;
6897
6898         if (developer_loading.integer)
6899                 Con_Printf("loading quake skin \"%s\"\n", name);
6900
6901         // 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)
6902         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6903         memcpy(skinframe->qpixels, skindata, width*height);
6904         skinframe->qwidth = width;
6905         skinframe->qheight = height;
6906
6907         featuresmask = 0;
6908         for (i = 0;i < width * height;i++)
6909                 featuresmask |= palette_featureflags[skindata[i]];
6910
6911         skinframe->hasalpha = false;
6912         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6913         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6914         skinframe->qgeneratemerged = true;
6915         skinframe->qgeneratebase = skinframe->qhascolormapping;
6916         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6917
6918         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6919         //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]);
6920
6921         return skinframe;
6922 }
6923
6924 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6925 {
6926         int width;
6927         int height;
6928         unsigned char *skindata;
6929
6930         if (!skinframe->qpixels)
6931                 return;
6932
6933         if (!skinframe->qhascolormapping)
6934                 colormapped = false;
6935
6936         if (colormapped)
6937         {
6938                 if (!skinframe->qgeneratebase)
6939                         return;
6940         }
6941         else
6942         {
6943                 if (!skinframe->qgeneratemerged)
6944                         return;
6945         }
6946
6947         width = skinframe->qwidth;
6948         height = skinframe->qheight;
6949         skindata = skinframe->qpixels;
6950
6951         if (skinframe->qgeneratenmap)
6952         {
6953                 unsigned char *temp1, *temp2;
6954                 skinframe->qgeneratenmap = false;
6955                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6956                 temp2 = temp1 + width * height * 4;
6957                 // use either a custom palette or the quake palette
6958                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6959                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6960                 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);
6961                 Mem_Free(temp1);
6962         }
6963
6964         if (skinframe->qgenerateglow)
6965         {
6966                 skinframe->qgenerateglow = false;
6967                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6968         }
6969
6970         if (colormapped)
6971         {
6972                 skinframe->qgeneratebase = false;
6973                 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);
6974                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6975                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6976         }
6977         else
6978         {
6979                 skinframe->qgeneratemerged = false;
6980                 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);
6981         }
6982
6983         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6984         {
6985                 Mem_Free(skinframe->qpixels);
6986                 skinframe->qpixels = NULL;
6987         }
6988 }
6989
6990 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)
6991 {
6992         int i;
6993         skinframe_t *skinframe;
6994
6995         if (cls.state == ca_dedicated)
6996                 return NULL;
6997
6998         // if already loaded just return it, otherwise make a new skinframe
6999         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
7000         if (skinframe && skinframe->base)
7001                 return skinframe;
7002
7003         skinframe->stain = NULL;
7004         skinframe->merged = NULL;
7005         skinframe->base = NULL;
7006         skinframe->pants = NULL;
7007         skinframe->shirt = NULL;
7008         skinframe->nmap = NULL;
7009         skinframe->gloss = NULL;
7010         skinframe->glow = NULL;
7011         skinframe->fog = NULL;
7012         skinframe->reflect = NULL;
7013         skinframe->hasalpha = false;
7014
7015         // if no data was provided, then clearly the caller wanted to get a blank skinframe
7016         if (!skindata)
7017                 return NULL;
7018
7019         if (developer_loading.integer)
7020                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
7021
7022         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
7023         if (textureflags & TEXF_ALPHA)
7024         {
7025                 for (i = 0;i < width * height;i++)
7026                 {
7027                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
7028                         {
7029                                 skinframe->hasalpha = true;
7030                                 break;
7031                         }
7032                 }
7033                 if (r_loadfog && skinframe->hasalpha)
7034                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
7035         }
7036
7037         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
7038         //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]);
7039
7040         return skinframe;
7041 }
7042
7043 skinframe_t *R_SkinFrame_LoadMissing(void)
7044 {
7045         skinframe_t *skinframe;
7046
7047         if (cls.state == ca_dedicated)
7048                 return NULL;
7049
7050         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
7051         skinframe->stain = NULL;
7052         skinframe->merged = NULL;
7053         skinframe->base = NULL;
7054         skinframe->pants = NULL;
7055         skinframe->shirt = NULL;
7056         skinframe->nmap = NULL;
7057         skinframe->gloss = NULL;
7058         skinframe->glow = NULL;
7059         skinframe->fog = NULL;
7060         skinframe->reflect = NULL;
7061         skinframe->hasalpha = false;
7062
7063         skinframe->avgcolor[0] = rand() / RAND_MAX;
7064         skinframe->avgcolor[1] = rand() / RAND_MAX;
7065         skinframe->avgcolor[2] = rand() / RAND_MAX;
7066         skinframe->avgcolor[3] = 1;
7067
7068         return skinframe;
7069 }
7070
7071 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7072 typedef struct suffixinfo_s
7073 {
7074         const char *suffix;
7075         qboolean flipx, flipy, flipdiagonal;
7076 }
7077 suffixinfo_t;
7078 static suffixinfo_t suffix[3][6] =
7079 {
7080         {
7081                 {"px",   false, false, false},
7082                 {"nx",   false, false, false},
7083                 {"py",   false, false, false},
7084                 {"ny",   false, false, false},
7085                 {"pz",   false, false, false},
7086                 {"nz",   false, false, false}
7087         },
7088         {
7089                 {"posx", false, false, false},
7090                 {"negx", false, false, false},
7091                 {"posy", false, false, false},
7092                 {"negy", false, false, false},
7093                 {"posz", false, false, false},
7094                 {"negz", false, false, false}
7095         },
7096         {
7097                 {"rt",    true, false,  true},
7098                 {"lf",   false,  true,  true},
7099                 {"ft",    true,  true, false},
7100                 {"bk",   false, false, false},
7101                 {"up",    true, false,  true},
7102                 {"dn",    true, false,  true}
7103         }
7104 };
7105
7106 static int componentorder[4] = {0, 1, 2, 3};
7107
7108 rtexture_t *R_LoadCubemap(const char *basename)
7109 {
7110         int i, j, cubemapsize;
7111         unsigned char *cubemappixels, *image_buffer;
7112         rtexture_t *cubemaptexture;
7113         char name[256];
7114         // must start 0 so the first loadimagepixels has no requested width/height
7115         cubemapsize = 0;
7116         cubemappixels = NULL;
7117         cubemaptexture = NULL;
7118         // keep trying different suffix groups (posx, px, rt) until one loads
7119         for (j = 0;j < 3 && !cubemappixels;j++)
7120         {
7121                 // load the 6 images in the suffix group
7122                 for (i = 0;i < 6;i++)
7123                 {
7124                         // generate an image name based on the base and and suffix
7125                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7126                         // load it
7127                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7128                         {
7129                                 // an image loaded, make sure width and height are equal
7130                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7131                                 {
7132                                         // if this is the first image to load successfully, allocate the cubemap memory
7133                                         if (!cubemappixels && image_width >= 1)
7134                                         {
7135                                                 cubemapsize = image_width;
7136                                                 // note this clears to black, so unavailable sides are black
7137                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7138                                         }
7139                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7140                                         if (cubemappixels)
7141                                                 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);
7142                                 }
7143                                 else
7144                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7145                                 // free the image
7146                                 Mem_Free(image_buffer);
7147                         }
7148                 }
7149         }
7150         // if a cubemap loaded, upload it
7151         if (cubemappixels)
7152         {
7153                 if (developer_loading.integer)
7154                         Con_Printf("loading cubemap \"%s\"\n", basename);
7155
7156                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7157                 Mem_Free(cubemappixels);
7158         }
7159         else
7160         {
7161                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7162                 if (developer_loading.integer)
7163                 {
7164                         Con_Printf("(tried tried images ");
7165                         for (j = 0;j < 3;j++)
7166                                 for (i = 0;i < 6;i++)
7167                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7168                         Con_Print(" and was unable to find any of them).\n");
7169                 }
7170         }
7171         return cubemaptexture;
7172 }
7173
7174 rtexture_t *R_GetCubemap(const char *basename)
7175 {
7176         int i;
7177         for (i = 0;i < r_texture_numcubemaps;i++)
7178                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7179                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7180         if (i >= MAX_CUBEMAPS)
7181                 return r_texture_whitecube;
7182         r_texture_numcubemaps++;
7183         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7184         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7185         return r_texture_cubemaps[i].texture;
7186 }
7187
7188 void R_FreeCubemaps(void)
7189 {
7190         int i;
7191         for (i = 0;i < r_texture_numcubemaps;i++)
7192         {
7193                 if (developer_loading.integer)
7194                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7195                 if (r_texture_cubemaps[i].texture)
7196                         R_FreeTexture(r_texture_cubemaps[i].texture);
7197         }
7198         r_texture_numcubemaps = 0;
7199 }
7200
7201 void R_Main_FreeViewCache(void)
7202 {
7203         if (r_refdef.viewcache.entityvisible)
7204                 Mem_Free(r_refdef.viewcache.entityvisible);
7205         if (r_refdef.viewcache.world_pvsbits)
7206                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7207         if (r_refdef.viewcache.world_leafvisible)
7208                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7209         if (r_refdef.viewcache.world_surfacevisible)
7210                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7211         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7212 }
7213
7214 void R_Main_ResizeViewCache(void)
7215 {
7216         int numentities = r_refdef.scene.numentities;
7217         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7218         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7219         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7220         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7221         if (r_refdef.viewcache.maxentities < numentities)
7222         {
7223                 r_refdef.viewcache.maxentities = numentities;
7224                 if (r_refdef.viewcache.entityvisible)
7225                         Mem_Free(r_refdef.viewcache.entityvisible);
7226                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7227         }
7228         if (r_refdef.viewcache.world_numclusters != numclusters)
7229         {
7230                 r_refdef.viewcache.world_numclusters = numclusters;
7231                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7232                 if (r_refdef.viewcache.world_pvsbits)
7233                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7234                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7235         }
7236         if (r_refdef.viewcache.world_numleafs != numleafs)
7237         {
7238                 r_refdef.viewcache.world_numleafs = numleafs;
7239                 if (r_refdef.viewcache.world_leafvisible)
7240                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7241                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7242         }
7243         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7244         {
7245                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7246                 if (r_refdef.viewcache.world_surfacevisible)
7247                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7248                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7249         }
7250 }
7251
7252 extern rtexture_t *loadingscreentexture;
7253 void gl_main_start(void)
7254 {
7255         loadingscreentexture = NULL;
7256         r_texture_blanknormalmap = NULL;
7257         r_texture_white = NULL;
7258         r_texture_grey128 = NULL;
7259         r_texture_black = NULL;
7260         r_texture_whitecube = NULL;
7261         r_texture_normalizationcube = NULL;
7262         r_texture_fogattenuation = NULL;
7263         r_texture_fogheighttexture = NULL;
7264         r_texture_gammaramps = NULL;
7265         r_texture_numcubemaps = 0;
7266
7267         r_loaddds = r_texture_dds_load.integer != 0;
7268         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7269
7270         switch(vid.renderpath)
7271         {
7272         case RENDERPATH_GL20:
7273         case RENDERPATH_CGGL:
7274         case RENDERPATH_D3D9:
7275         case RENDERPATH_D3D10:
7276         case RENDERPATH_D3D11:
7277         case RENDERPATH_SOFT:
7278                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7279                 Cvar_SetValueQuick(&gl_combine, 1);
7280                 Cvar_SetValueQuick(&r_glsl, 1);
7281                 r_loadnormalmap = true;
7282                 r_loadgloss = true;
7283                 r_loadfog = false;
7284                 break;
7285         case RENDERPATH_GL13:
7286                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7287                 Cvar_SetValueQuick(&gl_combine, 1);
7288                 Cvar_SetValueQuick(&r_glsl, 0);
7289                 r_loadnormalmap = false;
7290                 r_loadgloss = false;
7291                 r_loadfog = true;
7292                 break;
7293         case RENDERPATH_GL11:
7294                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7295                 Cvar_SetValueQuick(&gl_combine, 0);
7296                 Cvar_SetValueQuick(&r_glsl, 0);
7297                 r_loadnormalmap = false;
7298                 r_loadgloss = false;
7299                 r_loadfog = true;
7300                 break;
7301         }
7302
7303         R_AnimCache_Free();
7304         R_FrameData_Reset();
7305
7306         r_numqueries = 0;
7307         r_maxqueries = 0;
7308         memset(r_queries, 0, sizeof(r_queries));
7309
7310         r_qwskincache = NULL;
7311         r_qwskincache_size = 0;
7312
7313         // set up r_skinframe loading system for textures
7314         memset(&r_skinframe, 0, sizeof(r_skinframe));
7315         r_skinframe.loadsequence = 1;
7316         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7317
7318         r_main_texturepool = R_AllocTexturePool();
7319         R_BuildBlankTextures();
7320         R_BuildNoTexture();
7321         if (vid.support.arb_texture_cube_map)
7322         {
7323                 R_BuildWhiteCube();
7324                 R_BuildNormalizationCube();
7325         }
7326         r_texture_fogattenuation = NULL;
7327         r_texture_fogheighttexture = NULL;
7328         r_texture_gammaramps = NULL;
7329         //r_texture_fogintensity = NULL;
7330         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7331         memset(&r_waterstate, 0, sizeof(r_waterstate));
7332         r_glsl_permutation = NULL;
7333         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7334         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7335         glslshaderstring = NULL;
7336 #ifdef SUPPORTCG
7337         r_cg_permutation = NULL;
7338         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7339         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7340         cgshaderstring = NULL;
7341 #endif
7342 #ifdef SUPPORTD3D
7343         r_hlsl_permutation = NULL;
7344         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7345         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7346         hlslshaderstring = NULL;
7347 #endif
7348         memset(&r_svbsp, 0, sizeof (r_svbsp));
7349
7350         r_refdef.fogmasktable_density = 0;
7351 }
7352
7353 void gl_main_shutdown(void)
7354 {
7355         R_AnimCache_Free();
7356         R_FrameData_Reset();
7357
7358         R_Main_FreeViewCache();
7359
7360         switch(vid.renderpath)
7361         {
7362         case RENDERPATH_GL11:
7363         case RENDERPATH_GL13:
7364         case RENDERPATH_GL20:
7365         case RENDERPATH_CGGL:
7366                 if (r_maxqueries)
7367                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7368                 break;
7369         case RENDERPATH_D3D9:
7370                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7371                 break;
7372         case RENDERPATH_D3D10:
7373                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7374                 break;
7375         case RENDERPATH_D3D11:
7376                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7377                 break;
7378         case RENDERPATH_SOFT:
7379                 break;
7380         }
7381
7382         r_numqueries = 0;
7383         r_maxqueries = 0;
7384         memset(r_queries, 0, sizeof(r_queries));
7385
7386         r_qwskincache = NULL;
7387         r_qwskincache_size = 0;
7388
7389         // clear out the r_skinframe state
7390         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7391         memset(&r_skinframe, 0, sizeof(r_skinframe));
7392
7393         if (r_svbsp.nodes)
7394                 Mem_Free(r_svbsp.nodes);
7395         memset(&r_svbsp, 0, sizeof (r_svbsp));
7396         R_FreeTexturePool(&r_main_texturepool);
7397         loadingscreentexture = NULL;
7398         r_texture_blanknormalmap = NULL;
7399         r_texture_white = NULL;
7400         r_texture_grey128 = NULL;
7401         r_texture_black = NULL;
7402         r_texture_whitecube = NULL;
7403         r_texture_normalizationcube = NULL;
7404         r_texture_fogattenuation = NULL;
7405         r_texture_fogheighttexture = NULL;
7406         r_texture_gammaramps = NULL;
7407         r_texture_numcubemaps = 0;
7408         //r_texture_fogintensity = NULL;
7409         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7410         memset(&r_waterstate, 0, sizeof(r_waterstate));
7411         R_GLSL_Restart_f();
7412
7413         r_glsl_permutation = NULL;
7414         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7415         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7416         glslshaderstring = NULL;
7417 #ifdef SUPPORTCG
7418         r_cg_permutation = NULL;
7419         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7420         Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7421         cgshaderstring = NULL;
7422 #endif
7423 #ifdef SUPPORTD3D
7424         r_hlsl_permutation = NULL;
7425         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7426         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7427         hlslshaderstring = NULL;
7428 #endif
7429 }
7430
7431 extern void CL_ParseEntityLump(char *entitystring);
7432 void gl_main_newmap(void)
7433 {
7434         // FIXME: move this code to client
7435         char *entities, entname[MAX_QPATH];
7436         if (r_qwskincache)
7437                 Mem_Free(r_qwskincache);
7438         r_qwskincache = NULL;
7439         r_qwskincache_size = 0;
7440         if (cl.worldmodel)
7441         {
7442                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7443                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7444                 {
7445                         CL_ParseEntityLump(entities);
7446                         Mem_Free(entities);
7447                         return;
7448                 }
7449                 if (cl.worldmodel->brush.entities)
7450                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7451         }
7452         R_Main_FreeViewCache();
7453
7454         R_FrameData_Reset();
7455 }
7456
7457 void GL_Main_Init(void)
7458 {
7459         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7460
7461         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7462         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7463         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7464         if (gamemode == GAME_NEHAHRA)
7465         {
7466                 Cvar_RegisterVariable (&gl_fogenable);
7467                 Cvar_RegisterVariable (&gl_fogdensity);
7468                 Cvar_RegisterVariable (&gl_fogred);
7469                 Cvar_RegisterVariable (&gl_foggreen);
7470                 Cvar_RegisterVariable (&gl_fogblue);
7471                 Cvar_RegisterVariable (&gl_fogstart);
7472                 Cvar_RegisterVariable (&gl_fogend);
7473                 Cvar_RegisterVariable (&gl_skyclip);
7474         }
7475         Cvar_RegisterVariable(&r_motionblur);
7476         Cvar_RegisterVariable(&r_motionblur_maxblur);
7477         Cvar_RegisterVariable(&r_motionblur_bmin);
7478         Cvar_RegisterVariable(&r_motionblur_vmin);
7479         Cvar_RegisterVariable(&r_motionblur_vmax);
7480         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7481         Cvar_RegisterVariable(&r_motionblur_randomize);
7482         Cvar_RegisterVariable(&r_damageblur);
7483         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7484         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7485         Cvar_RegisterVariable(&r_equalize_entities_by);
7486         Cvar_RegisterVariable(&r_equalize_entities_to);
7487         Cvar_RegisterVariable(&r_depthfirst);
7488         Cvar_RegisterVariable(&r_useinfinitefarclip);
7489         Cvar_RegisterVariable(&r_farclip_base);
7490         Cvar_RegisterVariable(&r_farclip_world);
7491         Cvar_RegisterVariable(&r_nearclip);
7492         Cvar_RegisterVariable(&r_showbboxes);
7493         Cvar_RegisterVariable(&r_showsurfaces);
7494         Cvar_RegisterVariable(&r_showtris);
7495         Cvar_RegisterVariable(&r_shownormals);
7496         Cvar_RegisterVariable(&r_showlighting);
7497         Cvar_RegisterVariable(&r_showshadowvolumes);
7498         Cvar_RegisterVariable(&r_showcollisionbrushes);
7499         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7500         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7501         Cvar_RegisterVariable(&r_showdisabledepthtest);
7502         Cvar_RegisterVariable(&r_drawportals);
7503         Cvar_RegisterVariable(&r_drawentities);
7504         Cvar_RegisterVariable(&r_draw2d);
7505         Cvar_RegisterVariable(&r_drawworld);
7506         Cvar_RegisterVariable(&r_cullentities_trace);
7507         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7508         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7509         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7510         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7511         Cvar_RegisterVariable(&r_drawviewmodel);
7512         Cvar_RegisterVariable(&r_drawexteriormodel);
7513         Cvar_RegisterVariable(&r_speeds);
7514         Cvar_RegisterVariable(&r_fullbrights);
7515         Cvar_RegisterVariable(&r_wateralpha);
7516         Cvar_RegisterVariable(&r_dynamic);
7517         Cvar_RegisterVariable(&r_fakelight);
7518         Cvar_RegisterVariable(&r_fakelight_intensity);
7519         Cvar_RegisterVariable(&r_fullbright);
7520         Cvar_RegisterVariable(&r_shadows);
7521         Cvar_RegisterVariable(&r_shadows_darken);
7522         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7523         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7524         Cvar_RegisterVariable(&r_shadows_throwdistance);
7525         Cvar_RegisterVariable(&r_shadows_throwdirection);
7526         Cvar_RegisterVariable(&r_shadows_focus);
7527         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7528         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7529         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7530         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7531         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7532         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7533         Cvar_RegisterVariable(&r_fog_exp2);
7534         Cvar_RegisterVariable(&r_drawfog);
7535         Cvar_RegisterVariable(&r_transparentdepthmasking);
7536         Cvar_RegisterVariable(&r_texture_dds_load);
7537         Cvar_RegisterVariable(&r_texture_dds_save);
7538         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7539         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7540         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7541         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7542         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7543         Cvar_RegisterVariable(&r_textureunits);
7544         Cvar_RegisterVariable(&gl_combine);
7545         Cvar_RegisterVariable(&r_glsl);
7546         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7547         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7548         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7549         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7550         Cvar_RegisterVariable(&r_glsl_postprocess);
7551         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7552         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7553         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7554         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7555         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7556         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7557         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7558         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7559
7560         Cvar_RegisterVariable(&r_water);
7561         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7562         Cvar_RegisterVariable(&r_water_clippingplanebias);
7563         Cvar_RegisterVariable(&r_water_refractdistort);
7564         Cvar_RegisterVariable(&r_water_reflectdistort);
7565         Cvar_RegisterVariable(&r_water_scissormode);
7566         Cvar_RegisterVariable(&r_lerpsprites);
7567         Cvar_RegisterVariable(&r_lerpmodels);
7568         Cvar_RegisterVariable(&r_lerplightstyles);
7569         Cvar_RegisterVariable(&r_waterscroll);
7570         Cvar_RegisterVariable(&r_bloom);
7571         Cvar_RegisterVariable(&r_bloom_colorscale);
7572         Cvar_RegisterVariable(&r_bloom_brighten);
7573         Cvar_RegisterVariable(&r_bloom_blur);
7574         Cvar_RegisterVariable(&r_bloom_resolution);
7575         Cvar_RegisterVariable(&r_bloom_colorexponent);
7576         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7577         Cvar_RegisterVariable(&r_hdr);
7578         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7579         Cvar_RegisterVariable(&r_hdr_glowintensity);
7580         Cvar_RegisterVariable(&r_hdr_range);
7581         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7582         Cvar_RegisterVariable(&developer_texturelogging);
7583         Cvar_RegisterVariable(&gl_lightmaps);
7584         Cvar_RegisterVariable(&r_test);
7585         Cvar_RegisterVariable(&r_glsl_saturation);
7586         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7587         Cvar_RegisterVariable(&r_framedatasize);
7588         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7589                 Cvar_SetValue("r_fullbrights", 0);
7590         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7591
7592         Cvar_RegisterVariable(&r_track_sprites);
7593         Cvar_RegisterVariable(&r_track_sprites_flags);
7594         Cvar_RegisterVariable(&r_track_sprites_scalew);
7595         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7596         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7597         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7598         Cvar_RegisterVariable(&r_overheadsprites_scalex);
7599         Cvar_RegisterVariable(&r_overheadsprites_scaley);
7600 }
7601
7602 extern void R_Textures_Init(void);
7603 extern void GL_Draw_Init(void);
7604 extern void GL_Main_Init(void);
7605 extern void R_Shadow_Init(void);
7606 extern void R_Sky_Init(void);
7607 extern void GL_Surf_Init(void);
7608 extern void R_Particles_Init(void);
7609 extern void R_Explosion_Init(void);
7610 extern void gl_backend_init(void);
7611 extern void Sbar_Init(void);
7612 extern void R_LightningBeams_Init(void);
7613 extern void Mod_RenderInit(void);
7614 extern void Font_Init(void);
7615
7616 void Render_Init(void)
7617 {
7618         gl_backend_init();
7619         R_Textures_Init();
7620         GL_Main_Init();
7621         Font_Init();
7622         GL_Draw_Init();
7623         R_Shadow_Init();
7624         R_Sky_Init();
7625         GL_Surf_Init();
7626         Sbar_Init();
7627         R_Particles_Init();
7628         R_Explosion_Init();
7629         R_LightningBeams_Init();
7630         Mod_RenderInit();
7631 }
7632
7633 /*
7634 ===============
7635 GL_Init
7636 ===============
7637 */
7638 extern char *ENGINE_EXTENSIONS;
7639 void GL_Init (void)
7640 {
7641         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7642         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7643         gl_version = (const char *)qglGetString(GL_VERSION);
7644         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7645
7646         if (!gl_extensions)
7647                 gl_extensions = "";
7648         if (!gl_platformextensions)
7649                 gl_platformextensions = "";
7650
7651         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7652         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7653         Con_Printf("GL_VERSION: %s\n", gl_version);
7654         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7655         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7656
7657         VID_CheckExtensions();
7658
7659         // LordHavoc: report supported extensions
7660         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7661
7662         // clear to black (loading plaque will be seen over this)
7663         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7664 }
7665
7666 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7667 {
7668         int i;
7669         mplane_t *p;
7670         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7671         {
7672                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7673                 if (i == 4)
7674                         continue;
7675                 p = r_refdef.view.frustum + i;
7676                 switch(p->signbits)
7677                 {
7678                 default:
7679                 case 0:
7680                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7681                                 return true;
7682                         break;
7683                 case 1:
7684                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7685                                 return true;
7686                         break;
7687                 case 2:
7688                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7689                                 return true;
7690                         break;
7691                 case 3:
7692                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7693                                 return true;
7694                         break;
7695                 case 4:
7696                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7697                                 return true;
7698                         break;
7699                 case 5:
7700                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7701                                 return true;
7702                         break;
7703                 case 6:
7704                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7705                                 return true;
7706                         break;
7707                 case 7:
7708                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7709                                 return true;
7710                         break;
7711                 }
7712         }
7713         return false;
7714 }
7715
7716 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7717 {
7718         int i;
7719         const mplane_t *p;
7720         for (i = 0;i < numplanes;i++)
7721         {
7722                 p = planes + i;
7723                 switch(p->signbits)
7724                 {
7725                 default:
7726                 case 0:
7727                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7728                                 return true;
7729                         break;
7730                 case 1:
7731                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7732                                 return true;
7733                         break;
7734                 case 2:
7735                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7736                                 return true;
7737                         break;
7738                 case 3:
7739                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7740                                 return true;
7741                         break;
7742                 case 4:
7743                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7744                                 return true;
7745                         break;
7746                 case 5:
7747                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7748                                 return true;
7749                         break;
7750                 case 6:
7751                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7752                                 return true;
7753                         break;
7754                 case 7:
7755                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7756                                 return true;
7757                         break;
7758                 }
7759         }
7760         return false;
7761 }
7762
7763 //==================================================================================
7764
7765 // LordHavoc: this stores temporary data used within the same frame
7766
7767 typedef struct r_framedata_mem_s
7768 {
7769         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7770         size_t size; // how much usable space
7771         size_t current; // how much space in use
7772         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7773         size_t wantedsize; // how much space was allocated
7774         unsigned char *data; // start of real data (16byte aligned)
7775 }
7776 r_framedata_mem_t;
7777
7778 static r_framedata_mem_t *r_framedata_mem;
7779
7780 void R_FrameData_Reset(void)
7781 {
7782         while (r_framedata_mem)
7783         {
7784                 r_framedata_mem_t *next = r_framedata_mem->purge;
7785                 Mem_Free(r_framedata_mem);
7786                 r_framedata_mem = next;
7787         }
7788 }
7789
7790 void R_FrameData_Resize(void)
7791 {
7792         size_t wantedsize;
7793         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7794         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7795         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7796         {
7797                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7798                 newmem->wantedsize = wantedsize;
7799                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7800                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7801                 newmem->current = 0;
7802                 newmem->mark = 0;
7803                 newmem->purge = r_framedata_mem;
7804                 r_framedata_mem = newmem;
7805         }
7806 }
7807
7808 void R_FrameData_NewFrame(void)
7809 {
7810         R_FrameData_Resize();
7811         if (!r_framedata_mem)
7812                 return;
7813         // if we ran out of space on the last frame, free the old memory now
7814         while (r_framedata_mem->purge)
7815         {
7816                 // repeatedly remove the second item in the list, leaving only head
7817                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7818                 Mem_Free(r_framedata_mem->purge);
7819                 r_framedata_mem->purge = next;
7820         }
7821         // reset the current mem pointer
7822         r_framedata_mem->current = 0;
7823         r_framedata_mem->mark = 0;
7824 }
7825
7826 void *R_FrameData_Alloc(size_t size)
7827 {
7828         void *data;
7829
7830         // align to 16 byte boundary - the data pointer is already aligned, so we
7831         // only need to ensure the size of every allocation is also aligned
7832         size = (size + 15) & ~15;
7833
7834         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7835         {
7836                 // emergency - we ran out of space, allocate more memory
7837                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7838                 R_FrameData_Resize();
7839         }
7840
7841         data = r_framedata_mem->data + r_framedata_mem->current;
7842         r_framedata_mem->current += size;
7843
7844         // count the usage for stats
7845         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7846         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7847
7848         return (void *)data;
7849 }
7850
7851 void *R_FrameData_Store(size_t size, void *data)
7852 {
7853         void *d = R_FrameData_Alloc(size);
7854         if (d && data)
7855                 memcpy(d, data, size);
7856         return d;
7857 }
7858
7859 void R_FrameData_SetMark(void)
7860 {
7861         if (!r_framedata_mem)
7862                 return;
7863         r_framedata_mem->mark = r_framedata_mem->current;
7864 }
7865
7866 void R_FrameData_ReturnToMark(void)
7867 {
7868         if (!r_framedata_mem)
7869                 return;
7870         r_framedata_mem->current = r_framedata_mem->mark;
7871 }
7872
7873 //==================================================================================
7874
7875 // LordHavoc: animcache originally written by Echon, rewritten since then
7876
7877 /**
7878  * Animation cache prevents re-generating mesh data for an animated model
7879  * multiple times in one frame for lighting, shadowing, reflections, etc.
7880  */
7881
7882 void R_AnimCache_Free(void)
7883 {
7884 }
7885
7886 void R_AnimCache_ClearCache(void)
7887 {
7888         int i;
7889         entity_render_t *ent;
7890
7891         for (i = 0;i < r_refdef.scene.numentities;i++)
7892         {
7893                 ent = r_refdef.scene.entities[i];
7894                 ent->animcache_vertex3f = NULL;
7895                 ent->animcache_normal3f = NULL;
7896                 ent->animcache_svector3f = NULL;
7897                 ent->animcache_tvector3f = NULL;
7898                 ent->animcache_vertexmesh = NULL;
7899                 ent->animcache_vertex3fbuffer = NULL;
7900                 ent->animcache_vertexmeshbuffer = NULL;
7901         }
7902 }
7903
7904 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7905 {
7906         int i;
7907
7908         // check if we need the meshbuffers
7909         if (!vid.useinterleavedarrays)
7910                 return;
7911
7912         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7913                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7914         // TODO: upload vertex3f buffer?
7915         if (ent->animcache_vertexmesh)
7916         {
7917                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7918                 for (i = 0;i < numvertices;i++)
7919                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7920                 if (ent->animcache_svector3f)
7921                         for (i = 0;i < numvertices;i++)
7922                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7923                 if (ent->animcache_tvector3f)
7924                         for (i = 0;i < numvertices;i++)
7925                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7926                 if (ent->animcache_normal3f)
7927                         for (i = 0;i < numvertices;i++)
7928                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7929                 // TODO: upload vertexmeshbuffer?
7930         }
7931 }
7932
7933 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7934 {
7935         dp_model_t *model = ent->model;
7936         int numvertices;
7937         // see if it's already cached this frame
7938         if (ent->animcache_vertex3f)
7939         {
7940                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7941                 if (wantnormals || wanttangents)
7942                 {
7943                         if (ent->animcache_normal3f)
7944                                 wantnormals = false;
7945                         if (ent->animcache_svector3f)
7946                                 wanttangents = false;
7947                         if (wantnormals || wanttangents)
7948                         {
7949                                 numvertices = model->surfmesh.num_vertices;
7950                                 if (wantnormals)
7951                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7952                                 if (wanttangents)
7953                                 {
7954                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7955                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7956                                 }
7957                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7958                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7959                         }
7960                 }
7961         }
7962         else
7963         {
7964                 // see if this ent is worth caching
7965                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7966                         return false;
7967                 // get some memory for this entity and generate mesh data
7968                 numvertices = model->surfmesh.num_vertices;
7969                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7970                 if (wantnormals)
7971                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7972                 if (wanttangents)
7973                 {
7974                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7975                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7976                 }
7977                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7978                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7979         }
7980         return true;
7981 }
7982
7983 void R_AnimCache_CacheVisibleEntities(void)
7984 {
7985         int i;
7986         qboolean wantnormals = true;
7987         qboolean wanttangents = !r_showsurfaces.integer;
7988
7989         switch(vid.renderpath)
7990         {
7991         case RENDERPATH_GL20:
7992         case RENDERPATH_CGGL:
7993         case RENDERPATH_D3D9:
7994         case RENDERPATH_D3D10:
7995         case RENDERPATH_D3D11:
7996                 break;
7997         case RENDERPATH_GL13:
7998         case RENDERPATH_GL11:
7999                 wanttangents = false;
8000                 break;
8001         case RENDERPATH_SOFT:
8002                 break;
8003         }
8004
8005         if (r_shownormals.integer)
8006                 wanttangents = wantnormals = true;
8007
8008         // TODO: thread this
8009         // NOTE: R_PrepareRTLights() also caches entities
8010
8011         for (i = 0;i < r_refdef.scene.numentities;i++)
8012                 if (r_refdef.viewcache.entityvisible[i])
8013                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
8014 }
8015
8016 //==================================================================================
8017
8018 static void R_View_UpdateEntityLighting (void)
8019 {
8020         int i;
8021         entity_render_t *ent;
8022         vec3_t tempdiffusenormal, avg;
8023         vec_t f, fa, fd, fdd;
8024         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
8025
8026         for (i = 0;i < r_refdef.scene.numentities;i++)
8027         {
8028                 ent = r_refdef.scene.entities[i];
8029
8030                 // skip unseen models
8031                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
8032                         continue;
8033
8034                 // skip bsp models
8035                 if (ent->model && ent->model->brush.num_leafs)
8036                 {
8037                         // TODO: use modellight for r_ambient settings on world?
8038                         VectorSet(ent->modellight_ambient, 0, 0, 0);
8039                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
8040                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
8041                         continue;
8042                 }
8043
8044                 // fetch the lighting from the worldmodel data
8045                 VectorClear(ent->modellight_ambient);
8046                 VectorClear(ent->modellight_diffuse);
8047                 VectorClear(tempdiffusenormal);
8048                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
8049                 {
8050                         vec3_t org;
8051                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8052
8053                         // complete lightning for lit sprites
8054                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
8055                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
8056                         {
8057                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
8058                                         org[2] = org[2] + r_overheadsprites_pushback.value;
8059                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
8060                         }
8061                         else
8062                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
8063
8064                         if(ent->flags & RENDER_EQUALIZE)
8065                         {
8066                                 // first fix up ambient lighting...
8067                                 if(r_equalize_entities_minambient.value > 0)
8068                                 {
8069                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8070                                         if(fd > 0)
8071                                         {
8072                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
8073                                                 if(fa < r_equalize_entities_minambient.value * fd)
8074                                                 {
8075                                                         // solve:
8076                                                         //   fa'/fd' = minambient
8077                                                         //   fa'+0.25*fd' = fa+0.25*fd
8078                                                         //   ...
8079                                                         //   fa' = fd' * minambient
8080                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
8081                                                         //   ...
8082                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
8083                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
8084                                                         //   ...
8085                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
8086                                                         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
8087                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
8088                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
8089                                                 }
8090                                         }
8091                                 }
8092
8093                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
8094                                 {
8095                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
8096                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8097                                         f = fa + 0.25 * fd;
8098                                         if(f > 0)
8099                                         {
8100                                                 // adjust brightness and saturation to target
8101                                                 avg[0] = avg[1] = avg[2] = fa / f;
8102                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
8103                                                 avg[0] = avg[1] = avg[2] = fd / f;
8104                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
8105                                         }
8106                                 }
8107                         }
8108                 }
8109                 else // highly rare
8110                         VectorSet(ent->modellight_ambient, 1, 1, 1);
8111
8112                 // move the light direction into modelspace coordinates for lighting code
8113                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8114                 if(VectorLength2(ent->modellight_lightdir) == 0)
8115                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8116                 VectorNormalize(ent->modellight_lightdir);
8117         }
8118 }
8119
8120 #define MAX_LINEOFSIGHTTRACES 64
8121
8122 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8123 {
8124         int i;
8125         vec3_t boxmins, boxmaxs;
8126         vec3_t start;
8127         vec3_t end;
8128         dp_model_t *model = r_refdef.scene.worldmodel;
8129
8130         if (!model || !model->brush.TraceLineOfSight)
8131                 return true;
8132
8133         // expand the box a little
8134         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8135         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8136         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8137         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8138         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8139         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8140
8141         // return true if eye is inside enlarged box
8142         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8143                 return true;
8144
8145         // try center
8146         VectorCopy(eye, start);
8147         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8148         if (model->brush.TraceLineOfSight(model, start, end))
8149                 return true;
8150
8151         // try various random positions
8152         for (i = 0;i < numsamples;i++)
8153         {
8154                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8155                 if (model->brush.TraceLineOfSight(model, start, end))
8156                         return true;
8157         }
8158
8159         return false;
8160 }
8161
8162
8163 static void R_View_UpdateEntityVisible (void)
8164 {
8165         int i;
8166         int renderimask;
8167         int samples;
8168         entity_render_t *ent;
8169
8170         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8171                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8172                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8173                 :                                                          RENDER_EXTERIORMODEL;
8174         if (!r_drawviewmodel.integer)
8175                 renderimask |= RENDER_VIEWMODEL;
8176         if (!r_drawexteriormodel.integer)
8177                 renderimask |= RENDER_EXTERIORMODEL;
8178         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8179         {
8180                 // worldmodel can check visibility
8181                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8182                 for (i = 0;i < r_refdef.scene.numentities;i++)
8183                 {
8184                         ent = r_refdef.scene.entities[i];
8185                         if (!(ent->flags & renderimask))
8186                         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)))
8187                         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))
8188                                 r_refdef.viewcache.entityvisible[i] = true;
8189                 }
8190                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8191                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8192                 {
8193                         for (i = 0;i < r_refdef.scene.numentities;i++)
8194                         {
8195                                 ent = r_refdef.scene.entities[i];
8196                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8197                                 {
8198                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8199                                         if (samples < 0)
8200                                                 continue; // temp entities do pvs only
8201                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8202                                                 ent->last_trace_visibility = realtime;
8203                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8204                                                 r_refdef.viewcache.entityvisible[i] = 0;
8205                                 }
8206                         }
8207                 }
8208         }
8209         else
8210         {
8211                 // no worldmodel or it can't check visibility
8212                 for (i = 0;i < r_refdef.scene.numentities;i++)
8213                 {
8214                         ent = r_refdef.scene.entities[i];
8215                         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));
8216                 }
8217         }
8218 }
8219
8220 /// only used if skyrendermasked, and normally returns false
8221 int R_DrawBrushModelsSky (void)
8222 {
8223         int i, sky;
8224         entity_render_t *ent;
8225
8226         sky = false;
8227         for (i = 0;i < r_refdef.scene.numentities;i++)
8228         {
8229                 if (!r_refdef.viewcache.entityvisible[i])
8230                         continue;
8231                 ent = r_refdef.scene.entities[i];
8232                 if (!ent->model || !ent->model->DrawSky)
8233                         continue;
8234                 ent->model->DrawSky(ent);
8235                 sky = true;
8236         }
8237         return sky;
8238 }
8239
8240 static void R_DrawNoModel(entity_render_t *ent);
8241 static void R_DrawModels(void)
8242 {
8243         int i;
8244         entity_render_t *ent;
8245
8246         for (i = 0;i < r_refdef.scene.numentities;i++)
8247         {
8248                 if (!r_refdef.viewcache.entityvisible[i])
8249                         continue;
8250                 ent = r_refdef.scene.entities[i];
8251                 r_refdef.stats.entities++;
8252                 if (ent->model && ent->model->Draw != NULL)
8253                         ent->model->Draw(ent);
8254                 else
8255                         R_DrawNoModel(ent);
8256         }
8257 }
8258
8259 static void R_DrawModelsDepth(void)
8260 {
8261         int i;
8262         entity_render_t *ent;
8263
8264         for (i = 0;i < r_refdef.scene.numentities;i++)
8265         {
8266                 if (!r_refdef.viewcache.entityvisible[i])
8267                         continue;
8268                 ent = r_refdef.scene.entities[i];
8269                 if (ent->model && ent->model->DrawDepth != NULL)
8270                         ent->model->DrawDepth(ent);
8271         }
8272 }
8273
8274 static void R_DrawModelsDebug(void)
8275 {
8276         int i;
8277         entity_render_t *ent;
8278
8279         for (i = 0;i < r_refdef.scene.numentities;i++)
8280         {
8281                 if (!r_refdef.viewcache.entityvisible[i])
8282                         continue;
8283                 ent = r_refdef.scene.entities[i];
8284                 if (ent->model && ent->model->DrawDebug != NULL)
8285                         ent->model->DrawDebug(ent);
8286         }
8287 }
8288
8289 static void R_DrawModelsAddWaterPlanes(void)
8290 {
8291         int i;
8292         entity_render_t *ent;
8293
8294         for (i = 0;i < r_refdef.scene.numentities;i++)
8295         {
8296                 if (!r_refdef.viewcache.entityvisible[i])
8297                         continue;
8298                 ent = r_refdef.scene.entities[i];
8299                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8300                         ent->model->DrawAddWaterPlanes(ent);
8301         }
8302 }
8303
8304 static void R_View_SetFrustum(const int *scissor)
8305 {
8306         int i;
8307         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8308         vec3_t forward, left, up, origin, v;
8309
8310         if(scissor)
8311         {
8312                 // flipped x coordinates (because x points left here)
8313                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8314                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8315
8316                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8317                 switch(vid.renderpath)
8318                 {
8319                         case RENDERPATH_D3D9:
8320                         case RENDERPATH_D3D10:
8321                         case RENDERPATH_D3D11:
8322                         case RENDERPATH_SOFT:
8323                                 // non-flipped y coordinates
8324                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8325                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8326                                 break;
8327                         case RENDERPATH_GL11:
8328                         case RENDERPATH_GL13:
8329                         case RENDERPATH_GL20:
8330                         case RENDERPATH_CGGL:
8331                                 // non-flipped y coordinates
8332                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8333                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8334                                 break;
8335                 }
8336         }
8337
8338         // we can't trust r_refdef.view.forward and friends in reflected scenes
8339         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8340
8341 #if 0
8342         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8343         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8344         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8345         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8346         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8347         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8348         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8349         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8350         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8351         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8352         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8353         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8354 #endif
8355
8356 #if 0
8357         zNear = r_refdef.nearclip;
8358         nudge = 1.0 - 1.0 / (1<<23);
8359         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8360         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8361         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8362         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8363         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8364         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8365         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8366         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8367 #endif
8368
8369
8370
8371 #if 0
8372         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8373         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8374         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8375         r_refdef.view.frustum[0].dist = m[15] - m[12];
8376
8377         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8378         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8379         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8380         r_refdef.view.frustum[1].dist = m[15] + m[12];
8381
8382         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8383         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8384         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8385         r_refdef.view.frustum[2].dist = m[15] - m[13];
8386
8387         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8388         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8389         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8390         r_refdef.view.frustum[3].dist = m[15] + m[13];
8391
8392         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8393         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8394         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8395         r_refdef.view.frustum[4].dist = m[15] - m[14];
8396
8397         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8398         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8399         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8400         r_refdef.view.frustum[5].dist = m[15] + m[14];
8401 #endif
8402
8403         if (r_refdef.view.useperspective)
8404         {
8405                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8406                 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]);
8407                 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]);
8408                 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]);
8409                 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]);
8410
8411                 // then the normals from the corners relative to origin
8412                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8413                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8414                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8415                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8416
8417                 // in a NORMAL view, forward cross left == up
8418                 // in a REFLECTED view, forward cross left == down
8419                 // so our cross products above need to be adjusted for a left handed coordinate system
8420                 CrossProduct(forward, left, v);
8421                 if(DotProduct(v, up) < 0)
8422                 {
8423                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8424                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8425                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8426                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8427                 }
8428
8429                 // Leaving those out was a mistake, those were in the old code, and they
8430                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8431                 // I couldn't reproduce it after adding those normalizations. --blub
8432                 VectorNormalize(r_refdef.view.frustum[0].normal);
8433                 VectorNormalize(r_refdef.view.frustum[1].normal);
8434                 VectorNormalize(r_refdef.view.frustum[2].normal);
8435                 VectorNormalize(r_refdef.view.frustum[3].normal);
8436
8437                 // make the corners absolute
8438                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8439                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8440                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8441                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8442
8443                 // one more normal
8444                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8445
8446                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8447                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8448                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8449                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8450                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8451         }
8452         else
8453         {
8454                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8455                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8456                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8457                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8458                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8459                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8460                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8461                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8462                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8463                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8464         }
8465         r_refdef.view.numfrustumplanes = 5;
8466
8467         if (r_refdef.view.useclipplane)
8468         {
8469                 r_refdef.view.numfrustumplanes = 6;
8470                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8471         }
8472
8473         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8474                 PlaneClassify(r_refdef.view.frustum + i);
8475
8476         // LordHavoc: note to all quake engine coders, Quake had a special case
8477         // for 90 degrees which assumed a square view (wrong), so I removed it,
8478         // Quake2 has it disabled as well.
8479
8480         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8481         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8482         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8483         //PlaneClassify(&frustum[0]);
8484
8485         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8486         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8487         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8488         //PlaneClassify(&frustum[1]);
8489
8490         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8491         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8492         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8493         //PlaneClassify(&frustum[2]);
8494
8495         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8496         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8497         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8498         //PlaneClassify(&frustum[3]);
8499
8500         // nearclip plane
8501         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8502         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8503         //PlaneClassify(&frustum[4]);
8504 }
8505
8506 void R_View_UpdateWithScissor(const int *myscissor)
8507 {
8508         R_Main_ResizeViewCache();
8509         R_View_SetFrustum(myscissor);
8510         R_View_WorldVisibility(r_refdef.view.useclipplane);
8511         R_View_UpdateEntityVisible();
8512         R_View_UpdateEntityLighting();
8513 }
8514
8515 void R_View_Update(void)
8516 {
8517         R_Main_ResizeViewCache();
8518         R_View_SetFrustum(NULL);
8519         R_View_WorldVisibility(r_refdef.view.useclipplane);
8520         R_View_UpdateEntityVisible();
8521         R_View_UpdateEntityLighting();
8522 }
8523
8524 void R_SetupView(qboolean allowwaterclippingplane)
8525 {
8526         const float *customclipplane = NULL;
8527         float plane[4];
8528         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8529         {
8530                 // LordHavoc: couldn't figure out how to make this approach the
8531                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8532                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8533                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8534                         dist = r_refdef.view.clipplane.dist;
8535                 plane[0] = r_refdef.view.clipplane.normal[0];
8536                 plane[1] = r_refdef.view.clipplane.normal[1];
8537                 plane[2] = r_refdef.view.clipplane.normal[2];
8538                 plane[3] = dist;
8539                 customclipplane = plane;
8540         }
8541
8542         if (!r_refdef.view.useperspective)
8543                 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);
8544         else if (vid.stencil && r_useinfinitefarclip.integer)
8545                 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);
8546         else
8547                 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);
8548         R_SetViewport(&r_refdef.view.viewport);
8549 }
8550
8551 void R_EntityMatrix(const matrix4x4_t *matrix)
8552 {
8553         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8554         {
8555                 gl_modelmatrixchanged = false;
8556                 gl_modelmatrix = *matrix;
8557                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8558                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8559                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8560                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8561                 CHECKGLERROR
8562                 switch(vid.renderpath)
8563                 {
8564                 case RENDERPATH_D3D9:
8565 #ifdef SUPPORTD3D
8566                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8567                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8568 #endif
8569                         break;
8570                 case RENDERPATH_D3D10:
8571                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8572                         break;
8573                 case RENDERPATH_D3D11:
8574                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8575                         break;
8576                 case RENDERPATH_GL20:
8577                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8578                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8579                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8580                         break;
8581                 case RENDERPATH_CGGL:
8582 #ifdef SUPPORTCG
8583                         CHECKCGERROR
8584                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8585                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8586                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8587 #endif
8588                         break;
8589                 case RENDERPATH_GL13:
8590                 case RENDERPATH_GL11:
8591                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8592                         break;
8593                 case RENDERPATH_SOFT:
8594                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
8595                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
8596                         break;
8597                 }
8598         }
8599 }
8600
8601 void R_ResetViewRendering2D(void)
8602 {
8603         r_viewport_t viewport;
8604         DrawQ_Finish();
8605
8606         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8607         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);
8608         R_SetViewport(&viewport);
8609         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8610         GL_Color(1, 1, 1, 1);
8611         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8612         GL_BlendFunc(GL_ONE, GL_ZERO);
8613         GL_AlphaTest(false);
8614         GL_ScissorTest(false);
8615         GL_DepthMask(false);
8616         GL_DepthRange(0, 1);
8617         GL_DepthTest(false);
8618         GL_DepthFunc(GL_LEQUAL);
8619         R_EntityMatrix(&identitymatrix);
8620         R_Mesh_ResetTextureState();
8621         GL_PolygonOffset(0, 0);
8622         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8623         switch(vid.renderpath)
8624         {
8625         case RENDERPATH_GL11:
8626         case RENDERPATH_GL13:
8627         case RENDERPATH_GL20:
8628         case RENDERPATH_CGGL:
8629                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8630                 break;
8631         case RENDERPATH_D3D9:
8632         case RENDERPATH_D3D10:
8633         case RENDERPATH_D3D11:
8634         case RENDERPATH_SOFT:
8635                 break;
8636         }
8637         GL_CullFace(GL_NONE);
8638 }
8639
8640 void R_ResetViewRendering3D(void)
8641 {
8642         DrawQ_Finish();
8643
8644         R_SetupView(true);
8645         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8646         GL_Color(1, 1, 1, 1);
8647         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8648         GL_BlendFunc(GL_ONE, GL_ZERO);
8649         GL_AlphaTest(false);
8650         GL_ScissorTest(true);
8651         GL_DepthMask(true);
8652         GL_DepthRange(0, 1);
8653         GL_DepthTest(true);
8654         GL_DepthFunc(GL_LEQUAL);
8655         R_EntityMatrix(&identitymatrix);
8656         R_Mesh_ResetTextureState();
8657         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8658         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8659         switch(vid.renderpath)
8660         {
8661         case RENDERPATH_GL11:
8662         case RENDERPATH_GL13:
8663         case RENDERPATH_GL20:
8664         case RENDERPATH_CGGL:
8665                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8666                 break;
8667         case RENDERPATH_D3D9:
8668         case RENDERPATH_D3D10:
8669         case RENDERPATH_D3D11:
8670         case RENDERPATH_SOFT:
8671                 break;
8672         }
8673         GL_CullFace(r_refdef.view.cullface_back);
8674 }
8675
8676 /*
8677 ================
8678 R_RenderView_UpdateViewVectors
8679 ================
8680 */
8681 static void R_RenderView_UpdateViewVectors(void)
8682 {
8683         // break apart the view matrix into vectors for various purposes
8684         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8685         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8686         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8687         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8688         // make an inverted copy of the view matrix for tracking sprites
8689         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8690 }
8691
8692 void R_RenderScene(void);
8693 void R_RenderWaterPlanes(void);
8694
8695 static void R_Water_StartFrame(void)
8696 {
8697         int i;
8698         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8699         r_waterstate_waterplane_t *p;
8700
8701         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8702                 return;
8703
8704         switch(vid.renderpath)
8705         {
8706         case RENDERPATH_GL20:
8707         case RENDERPATH_CGGL:
8708         case RENDERPATH_D3D9:
8709         case RENDERPATH_D3D10:
8710         case RENDERPATH_D3D11:
8711         case RENDERPATH_SOFT:
8712                 break;
8713         case RENDERPATH_GL13:
8714         case RENDERPATH_GL11:
8715                 return;
8716         }
8717
8718         // set waterwidth and waterheight to the water resolution that will be
8719         // used (often less than the screen resolution for faster rendering)
8720         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8721         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8722
8723         // calculate desired texture sizes
8724         // can't use water if the card does not support the texture size
8725         if (!r_water.integer || r_showsurfaces.integer)
8726                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8727         else if (vid.support.arb_texture_non_power_of_two)
8728         {
8729                 texturewidth = waterwidth;
8730                 textureheight = waterheight;
8731                 camerawidth = waterwidth;
8732                 cameraheight = waterheight;
8733         }
8734         else
8735         {
8736                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8737                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8738                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8739                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8740         }
8741
8742         // allocate textures as needed
8743         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8744         {
8745                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8746                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8747                 {
8748                         if (p->texture_refraction)
8749                                 R_FreeTexture(p->texture_refraction);
8750                         p->texture_refraction = NULL;
8751                         if (p->texture_reflection)
8752                                 R_FreeTexture(p->texture_reflection);
8753                         p->texture_reflection = NULL;
8754                         if (p->texture_camera)
8755                                 R_FreeTexture(p->texture_camera);
8756                         p->texture_camera = NULL;
8757                 }
8758                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8759                 r_waterstate.texturewidth = texturewidth;
8760                 r_waterstate.textureheight = textureheight;
8761                 r_waterstate.camerawidth = camerawidth;
8762                 r_waterstate.cameraheight = cameraheight;
8763         }
8764
8765         if (r_waterstate.texturewidth)
8766         {
8767                 r_waterstate.enabled = true;
8768
8769                 // when doing a reduced render (HDR) we want to use a smaller area
8770                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8771                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8772
8773                 // set up variables that will be used in shader setup
8774                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8775                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8776                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8777                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8778         }
8779
8780         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8781         r_waterstate.numwaterplanes = 0;
8782 }
8783
8784 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8785 {
8786         int triangleindex, planeindex;
8787         const int *e;
8788         vec3_t vert[3];
8789         vec3_t normal;
8790         vec3_t center;
8791         mplane_t plane;
8792         r_waterstate_waterplane_t *p;
8793         texture_t *t = R_GetCurrentTexture(surface->texture);
8794
8795         // just use the first triangle with a valid normal for any decisions
8796         VectorClear(normal);
8797         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8798         {
8799                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8800                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8801                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8802                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8803                 if (VectorLength2(normal) >= 0.001)
8804                         break;
8805         }
8806
8807         VectorCopy(normal, plane.normal);
8808         VectorNormalize(plane.normal);
8809         plane.dist = DotProduct(vert[0], plane.normal);
8810         PlaneClassify(&plane);
8811         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8812         {
8813                 // skip backfaces (except if nocullface is set)
8814                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8815                         return;
8816                 VectorNegate(plane.normal, plane.normal);
8817                 plane.dist *= -1;
8818                 PlaneClassify(&plane);
8819         }
8820
8821
8822         // find a matching plane if there is one
8823         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8824                 if(p->camera_entity == t->camera_entity)
8825                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8826                                 break;
8827         if (planeindex >= r_waterstate.maxwaterplanes)
8828                 return; // nothing we can do, out of planes
8829
8830         // if this triangle does not fit any known plane rendered this frame, add one
8831         if (planeindex >= r_waterstate.numwaterplanes)
8832         {
8833                 // store the new plane
8834                 r_waterstate.numwaterplanes++;
8835                 p->plane = plane;
8836                 // clear materialflags and pvs
8837                 p->materialflags = 0;
8838                 p->pvsvalid = false;
8839                 p->camera_entity = t->camera_entity;
8840                 VectorCopy(surface->mins, p->mins);
8841                 VectorCopy(surface->maxs, p->maxs);
8842         }
8843         else
8844         {
8845                 // merge mins/maxs
8846                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8847                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8848                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8849                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8850                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8851                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8852         }
8853         // merge this surface's materialflags into the waterplane
8854         p->materialflags |= t->currentmaterialflags;
8855         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8856         {
8857                 // merge this surface's PVS into the waterplane
8858                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8859                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8860                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8861                 {
8862                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8863                         p->pvsvalid = true;
8864                 }
8865         }
8866 }
8867
8868 static void R_Water_ProcessPlanes(void)
8869 {
8870         int myscissor[4];
8871         r_refdef_view_t originalview;
8872         r_refdef_view_t myview;
8873         int planeindex;
8874         r_waterstate_waterplane_t *p;
8875         vec3_t visorigin;
8876
8877         originalview = r_refdef.view;
8878
8879         // make sure enough textures are allocated
8880         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8881         {
8882                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8883                 {
8884                         if (!p->texture_refraction)
8885                                 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);
8886                         if (!p->texture_refraction)
8887                                 goto error;
8888                 }
8889                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8890                 {
8891                         if (!p->texture_camera)
8892                                 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);
8893                         if (!p->texture_camera)
8894                                 goto error;
8895                 }
8896
8897                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8898                 {
8899                         if (!p->texture_reflection)
8900                                 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);
8901                         if (!p->texture_reflection)
8902                                 goto error;
8903                 }
8904         }
8905
8906         // render views
8907         r_refdef.view = originalview;
8908         r_refdef.view.showdebug = false;
8909         r_refdef.view.width = r_waterstate.waterwidth;
8910         r_refdef.view.height = r_waterstate.waterheight;
8911         r_refdef.view.useclipplane = true;
8912         myview = r_refdef.view;
8913         r_waterstate.renderingscene = true;
8914         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8915         {
8916                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8917                 {
8918                         r_refdef.view = myview;
8919                         if(r_water_scissormode.integer)
8920                         {
8921                                 R_SetupView(true);
8922                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8923                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8924                         }
8925
8926                         // render reflected scene and copy into texture
8927                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8928                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8929                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8930                         r_refdef.view.clipplane = p->plane;
8931
8932                         // reverse the cullface settings for this render
8933                         r_refdef.view.cullface_front = GL_FRONT;
8934                         r_refdef.view.cullface_back = GL_BACK;
8935                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8936                         {
8937                                 r_refdef.view.usecustompvs = true;
8938                                 if (p->pvsvalid)
8939                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8940                                 else
8941                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8942                         }
8943
8944                         R_ResetViewRendering3D();
8945                         R_ClearScreen(r_refdef.fogenabled);
8946                         if(r_water_scissormode.integer & 2)
8947                                 R_View_UpdateWithScissor(myscissor);
8948                         else
8949                                 R_View_Update();
8950                         if(r_water_scissormode.integer & 1)
8951                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8952                         R_RenderScene();
8953
8954                         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);
8955                 }
8956
8957                 // render the normal view scene and copy into texture
8958                 // (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)
8959                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8960                 {
8961                         r_refdef.view = myview;
8962                         if(r_water_scissormode.integer)
8963                         {
8964                                 R_SetupView(true);
8965                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8966                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8967                         }
8968
8969                         r_waterstate.renderingrefraction = true;
8970
8971                         r_refdef.view.clipplane = p->plane;
8972                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8973                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8974
8975                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8976                         {
8977                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8978                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8979                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8980                                 R_RenderView_UpdateViewVectors();
8981                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8982                                 {
8983                                         r_refdef.view.usecustompvs = true;
8984                                         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);
8985                                 }
8986                         }
8987
8988                         PlaneClassify(&r_refdef.view.clipplane);
8989
8990                         R_ResetViewRendering3D();
8991                         R_ClearScreen(r_refdef.fogenabled);
8992                         if(r_water_scissormode.integer & 2)
8993                                 R_View_UpdateWithScissor(myscissor);
8994                         else
8995                                 R_View_Update();
8996                         if(r_water_scissormode.integer & 1)
8997                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8998                         R_RenderScene();
8999
9000                         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);
9001                         r_waterstate.renderingrefraction = false;
9002                 }
9003                 else if (p->materialflags & MATERIALFLAG_CAMERA)
9004                 {
9005                         r_refdef.view = myview;
9006
9007                         r_refdef.view.clipplane = p->plane;
9008                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
9009                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
9010
9011                         r_refdef.view.width = r_waterstate.camerawidth;
9012                         r_refdef.view.height = r_waterstate.cameraheight;
9013                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
9014                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
9015
9016                         if(p->camera_entity)
9017                         {
9018                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
9019                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
9020                         }
9021
9022                         // note: all of the view is used for displaying... so
9023                         // there is no use in scissoring
9024
9025                         // reverse the cullface settings for this render
9026                         r_refdef.view.cullface_front = GL_FRONT;
9027                         r_refdef.view.cullface_back = GL_BACK;
9028                         // also reverse the view matrix
9029                         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
9030                         R_RenderView_UpdateViewVectors();
9031                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
9032                         {
9033                                 r_refdef.view.usecustompvs = true;
9034                                 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);
9035                         }
9036                         
9037                         // camera needs no clipplane
9038                         r_refdef.view.useclipplane = false;
9039
9040                         PlaneClassify(&r_refdef.view.clipplane);
9041
9042                         R_ResetViewRendering3D();
9043                         R_ClearScreen(r_refdef.fogenabled);
9044                         R_View_Update();
9045                         R_RenderScene();
9046
9047                         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);
9048                         r_waterstate.renderingrefraction = false;
9049                 }
9050
9051         }
9052         r_waterstate.renderingscene = false;
9053         r_refdef.view = originalview;
9054         R_ResetViewRendering3D();
9055         R_ClearScreen(r_refdef.fogenabled);
9056         R_View_Update();
9057         return;
9058 error:
9059         r_refdef.view = originalview;
9060         r_waterstate.renderingscene = false;
9061         Cvar_SetValueQuick(&r_water, 0);
9062         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
9063         return;
9064 }
9065
9066 void R_Bloom_StartFrame(void)
9067 {
9068         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
9069
9070         switch(vid.renderpath)
9071         {
9072         case RENDERPATH_GL20:
9073         case RENDERPATH_CGGL:
9074         case RENDERPATH_D3D9:
9075         case RENDERPATH_D3D10:
9076         case RENDERPATH_D3D11:
9077         case RENDERPATH_SOFT:
9078                 break;
9079         case RENDERPATH_GL13:
9080         case RENDERPATH_GL11:
9081                 return;
9082         }
9083
9084         // set bloomwidth and bloomheight to the bloom resolution that will be
9085         // used (often less than the screen resolution for faster rendering)
9086         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
9087         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
9088         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
9089         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
9090         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
9091
9092         // calculate desired texture sizes
9093         if (vid.support.arb_texture_non_power_of_two)
9094         {
9095                 screentexturewidth = r_refdef.view.width;
9096                 screentextureheight = r_refdef.view.height;
9097                 bloomtexturewidth = r_bloomstate.bloomwidth;
9098                 bloomtextureheight = r_bloomstate.bloomheight;
9099         }
9100         else
9101         {
9102                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
9103                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
9104                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
9105                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
9106         }
9107
9108         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))
9109         {
9110                 Cvar_SetValueQuick(&r_hdr, 0);
9111                 Cvar_SetValueQuick(&r_bloom, 0);
9112                 Cvar_SetValueQuick(&r_motionblur, 0);
9113                 Cvar_SetValueQuick(&r_damageblur, 0);
9114         }
9115
9116         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)))
9117                 screentexturewidth = screentextureheight = 0;
9118         if (!r_hdr.integer && !r_bloom.integer)
9119                 bloomtexturewidth = bloomtextureheight = 0;
9120
9121         // allocate textures as needed
9122         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
9123         {
9124                 if (r_bloomstate.texture_screen)
9125                         R_FreeTexture(r_bloomstate.texture_screen);
9126                 r_bloomstate.texture_screen = NULL;
9127                 r_bloomstate.screentexturewidth = screentexturewidth;
9128                 r_bloomstate.screentextureheight = screentextureheight;
9129                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
9130                         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);
9131         }
9132         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
9133         {
9134                 if (r_bloomstate.texture_bloom)
9135                         R_FreeTexture(r_bloomstate.texture_bloom);
9136                 r_bloomstate.texture_bloom = NULL;
9137                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9138                 r_bloomstate.bloomtextureheight = bloomtextureheight;
9139                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9140                         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);
9141         }
9142
9143         // when doing a reduced render (HDR) we want to use a smaller area
9144         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9145         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9146         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9147         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9148         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9149
9150         // set up a texcoord array for the full resolution screen image
9151         // (we have to keep this around to copy back during final render)
9152         r_bloomstate.screentexcoord2f[0] = 0;
9153         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9154         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9155         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9156         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9157         r_bloomstate.screentexcoord2f[5] = 0;
9158         r_bloomstate.screentexcoord2f[6] = 0;
9159         r_bloomstate.screentexcoord2f[7] = 0;
9160
9161         // set up a texcoord array for the reduced resolution bloom image
9162         // (which will be additive blended over the screen image)
9163         r_bloomstate.bloomtexcoord2f[0] = 0;
9164         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9165         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9166         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9167         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9168         r_bloomstate.bloomtexcoord2f[5] = 0;
9169         r_bloomstate.bloomtexcoord2f[6] = 0;
9170         r_bloomstate.bloomtexcoord2f[7] = 0;
9171
9172         switch(vid.renderpath)
9173         {
9174         case RENDERPATH_GL11:
9175         case RENDERPATH_GL13:
9176         case RENDERPATH_GL20:
9177         case RENDERPATH_CGGL:
9178         case RENDERPATH_SOFT:
9179                 break;
9180         case RENDERPATH_D3D9:
9181         case RENDERPATH_D3D10:
9182         case RENDERPATH_D3D11:
9183                 {
9184                         int i;
9185                         for (i = 0;i < 4;i++)
9186                         {
9187                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9188                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9189                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9190                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9191                         }
9192                 }
9193                 break;
9194         }
9195
9196         if (r_hdr.integer || r_bloom.integer)
9197         {
9198                 r_bloomstate.enabled = true;
9199                 r_bloomstate.hdr = r_hdr.integer != 0;
9200         }
9201
9202         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);
9203 }
9204
9205 void R_Bloom_CopyBloomTexture(float colorscale)
9206 {
9207         r_refdef.stats.bloom++;
9208
9209         // scale down screen texture to the bloom texture size
9210         CHECKGLERROR
9211         R_SetViewport(&r_bloomstate.viewport);
9212         GL_BlendFunc(GL_ONE, GL_ZERO);
9213         GL_Color(colorscale, colorscale, colorscale, 1);
9214         // 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...
9215         switch(vid.renderpath)
9216         {
9217         case RENDERPATH_GL11:
9218         case RENDERPATH_GL13:
9219         case RENDERPATH_GL20:
9220         case RENDERPATH_CGGL:
9221         case RENDERPATH_SOFT:
9222                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9223                 break;
9224         case RENDERPATH_D3D9:
9225         case RENDERPATH_D3D10:
9226         case RENDERPATH_D3D11:
9227                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9228                 break;
9229         }
9230         // TODO: do boxfilter scale-down in shader?
9231         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9232         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9233         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9234
9235         // we now have a bloom image in the framebuffer
9236         // copy it into the bloom image texture for later processing
9237         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);
9238         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9239 }
9240
9241 void R_Bloom_CopyHDRTexture(void)
9242 {
9243         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);
9244         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9245 }
9246
9247 void R_Bloom_MakeTexture(void)
9248 {
9249         int x, range, dir;
9250         float xoffset, yoffset, r, brighten;
9251
9252         r_refdef.stats.bloom++;
9253
9254         R_ResetViewRendering2D();
9255
9256         // we have a bloom image in the framebuffer
9257         CHECKGLERROR
9258         R_SetViewport(&r_bloomstate.viewport);
9259
9260         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9261         {
9262                 x *= 2;
9263                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9264                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9265                 GL_Color(r,r,r,1);
9266                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9267                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9268                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9269                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9270
9271                 // copy the vertically blurred bloom view to a texture
9272                 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);
9273                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9274         }
9275
9276         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9277         brighten = r_bloom_brighten.value;
9278         if (r_hdr.integer)
9279                 brighten *= r_hdr_range.value;
9280         brighten = sqrt(brighten);
9281         if(range >= 1)
9282                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9283         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9284
9285         for (dir = 0;dir < 2;dir++)
9286         {
9287                 // blend on at multiple vertical offsets to achieve a vertical blur
9288                 // TODO: do offset blends using GLSL
9289                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9290                 GL_BlendFunc(GL_ONE, GL_ZERO);
9291                 for (x = -range;x <= range;x++)
9292                 {
9293                         if (!dir){xoffset = 0;yoffset = x;}
9294                         else {xoffset = x;yoffset = 0;}
9295                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9296                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9297                         // compute a texcoord array with the specified x and y offset
9298                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9299                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9300                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9301                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9302                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9303                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9304                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9305                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9306                         // this r value looks like a 'dot' particle, fading sharply to
9307                         // black at the edges
9308                         // (probably not realistic but looks good enough)
9309                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9310                         //r = brighten/(range*2+1);
9311                         r = brighten / (range * 2 + 1);
9312                         if(range >= 1)
9313                                 r *= (1 - x*x/(float)(range*range));
9314                         GL_Color(r, r, r, 1);
9315                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9316                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9317                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9318                         GL_BlendFunc(GL_ONE, GL_ONE);
9319                 }
9320
9321                 // copy the vertically blurred bloom view to a texture
9322                 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);
9323                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9324         }
9325 }
9326
9327 void R_HDR_RenderBloomTexture(void)
9328 {
9329         int oldwidth, oldheight;
9330         float oldcolorscale;
9331         qboolean oldwaterstate;
9332
9333         oldwaterstate = r_waterstate.enabled;
9334         oldcolorscale = r_refdef.view.colorscale;
9335         oldwidth = r_refdef.view.width;
9336         oldheight = r_refdef.view.height;
9337         r_refdef.view.width = r_bloomstate.bloomwidth;
9338         r_refdef.view.height = r_bloomstate.bloomheight;
9339
9340         if(r_hdr.integer < 2)
9341                 r_waterstate.enabled = false;
9342
9343         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9344         // TODO: add exposure compensation features
9345         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9346
9347         r_refdef.view.showdebug = false;
9348         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9349
9350         R_ResetViewRendering3D();
9351
9352         R_ClearScreen(r_refdef.fogenabled);
9353         if (r_timereport_active)
9354                 R_TimeReport("HDRclear");
9355
9356         R_View_Update();
9357         if (r_timereport_active)
9358                 R_TimeReport("visibility");
9359
9360         // only do secondary renders with HDR if r_hdr is 2 or higher
9361         r_waterstate.numwaterplanes = 0;
9362         if (r_waterstate.enabled)
9363                 R_RenderWaterPlanes();
9364
9365         r_refdef.view.showdebug = true;
9366         R_RenderScene();
9367         r_waterstate.numwaterplanes = 0;
9368
9369         R_ResetViewRendering2D();
9370
9371         R_Bloom_CopyHDRTexture();
9372         R_Bloom_MakeTexture();
9373
9374         // restore the view settings
9375         r_waterstate.enabled = oldwaterstate;
9376         r_refdef.view.width = oldwidth;
9377         r_refdef.view.height = oldheight;
9378         r_refdef.view.colorscale = oldcolorscale;
9379
9380         R_ResetViewRendering3D();
9381
9382         R_ClearScreen(r_refdef.fogenabled);
9383         if (r_timereport_active)
9384                 R_TimeReport("viewclear");
9385 }
9386
9387 static void R_BlendView(void)
9388 {
9389         unsigned int permutation;
9390         float uservecs[4][4];
9391
9392         switch (vid.renderpath)
9393         {
9394         case RENDERPATH_GL20:
9395         case RENDERPATH_CGGL:
9396         case RENDERPATH_D3D9:
9397         case RENDERPATH_D3D10:
9398         case RENDERPATH_D3D11:
9399         case RENDERPATH_SOFT:
9400                 permutation =
9401                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9402                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9403                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9404                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9405                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9406
9407                 if (r_bloomstate.texture_screen)
9408                 {
9409                         // make sure the buffer is available
9410                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9411
9412                         R_ResetViewRendering2D();
9413
9414                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9415                         {
9416                                 // declare variables
9417                                 float speed;
9418                                 static float avgspeed;
9419
9420                                 speed = VectorLength(cl.movement_velocity);
9421
9422                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9423                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9424
9425                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9426                                 speed = bound(0, speed, 1);
9427                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9428
9429                                 // calculate values into a standard alpha
9430                                 cl.motionbluralpha = 1 - exp(-
9431                                                 (
9432                                                  (r_motionblur.value * speed / 80)
9433                                                  +
9434                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9435                                                 )
9436                                                 /
9437                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9438                                            );
9439
9440                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9441                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9442                                 // apply the blur
9443                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9444                                 {
9445                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9446                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9447                                         switch(vid.renderpath)
9448                                         {
9449                                         case RENDERPATH_GL11:
9450                                         case RENDERPATH_GL13:
9451                                         case RENDERPATH_GL20:
9452                                         case RENDERPATH_CGGL:
9453                                         case RENDERPATH_SOFT:
9454                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9455                                                 break;
9456                                         case RENDERPATH_D3D9:
9457                                         case RENDERPATH_D3D10:
9458                                         case RENDERPATH_D3D11:
9459                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9460                                                 break;
9461                                         }
9462                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9463                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9464                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9465                                 }
9466                         }
9467
9468                         // copy view into the screen texture
9469                         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);
9470                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9471                 }
9472                 else if (!r_bloomstate.texture_bloom)
9473                 {
9474                         // we may still have to do view tint...
9475                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9476                         {
9477                                 // apply a color tint to the whole view
9478                                 R_ResetViewRendering2D();
9479                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9480                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9481                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9482                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9483                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9484                         }
9485                         break; // no screen processing, no bloom, skip it
9486                 }
9487
9488                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9489                 {
9490                         // render simple bloom effect
9491                         // copy the screen and shrink it and darken it for the bloom process
9492                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9493                         // make the bloom texture
9494                         R_Bloom_MakeTexture();
9495                 }
9496
9497 #if _MSC_VER >= 1400
9498 #define sscanf sscanf_s
9499 #endif
9500                 memset(uservecs, 0, sizeof(uservecs));
9501                 if (r_glsl_postprocess_uservec1_enable.integer)
9502                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9503                 if (r_glsl_postprocess_uservec2_enable.integer)
9504                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9505                 if (r_glsl_postprocess_uservec3_enable.integer)
9506                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9507                 if (r_glsl_postprocess_uservec4_enable.integer)
9508                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9509
9510                 R_ResetViewRendering2D();
9511                 GL_Color(1, 1, 1, 1);
9512                 GL_BlendFunc(GL_ONE, GL_ZERO);
9513
9514                 switch(vid.renderpath)
9515                 {
9516                 case RENDERPATH_GL20:
9517                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9518                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9519                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9520                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9521                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9522                         if (r_glsl_permutation->loc_ViewTintColor      >= 0) qglUniform4fARB(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9523                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9524                         if (r_glsl_permutation->loc_UserVec1           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9525                         if (r_glsl_permutation->loc_UserVec2           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9526                         if (r_glsl_permutation->loc_UserVec3           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9527                         if (r_glsl_permutation->loc_UserVec4           >= 0) qglUniform4fARB(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9528                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9529                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9530                         if (r_glsl_permutation->loc_BloomColorSubtract    >= 0) qglUniform4fARB(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9531                         break;
9532                 case RENDERPATH_CGGL:
9533 #ifdef SUPPORTCG
9534                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9535                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9536                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9537                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9538                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9539                         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
9540                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9541                         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
9542                         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
9543                         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
9544                         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
9545                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9546                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9547                         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);
9548 #endif
9549                         break;
9550                 case RENDERPATH_D3D9:
9551 #ifdef SUPPORTD3D
9552                         // 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...
9553                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9554                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9555                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9556                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9557                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9558                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9559                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9560                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9561                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9562                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9563                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9564                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9565                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9566                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9567 #endif
9568                         break;
9569                 case RENDERPATH_D3D10:
9570                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9571                         break;
9572                 case RENDERPATH_D3D11:
9573                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9574                         break;
9575                 case RENDERPATH_SOFT:
9576                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9577                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
9578                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9579                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9580                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9581                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9582                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9583                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9584                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9585                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9586                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9587                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
9588                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9589                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9590                         break;
9591                 default:
9592                         break;
9593                 }
9594                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9595                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9596                 break;
9597         case RENDERPATH_GL13:
9598         case RENDERPATH_GL11:
9599                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9600                 {
9601                         // apply a color tint to the whole view
9602                         R_ResetViewRendering2D();
9603                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9604                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9605                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9606                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9607                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9608                 }
9609                 break;
9610         }
9611 }
9612
9613 matrix4x4_t r_waterscrollmatrix;
9614
9615 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9616 {
9617         if (r_refdef.fog_density)
9618         {
9619                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9620                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9621                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9622
9623                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9624                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9625                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9626                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9627
9628                 {
9629                         vec3_t fogvec;
9630                         VectorCopy(r_refdef.fogcolor, fogvec);
9631                         //   color.rgb *= ContrastBoost * SceneBrightness;
9632                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9633                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9634                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9635                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9636                 }
9637         }
9638 }
9639
9640 void R_UpdateVariables(void)
9641 {
9642         R_Textures_Frame();
9643
9644         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9645
9646         r_refdef.farclip = r_farclip_base.value;
9647         if (r_refdef.scene.worldmodel)
9648                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9649         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9650
9651         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9652                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9653         r_refdef.polygonfactor = 0;
9654         r_refdef.polygonoffset = 0;
9655         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9656         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9657
9658         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9659         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9660         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9661         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9662         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9663         if (FAKELIGHT_ENABLED)
9664         {
9665                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9666         }
9667         if (r_showsurfaces.integer)
9668         {
9669                 r_refdef.scene.rtworld = false;
9670                 r_refdef.scene.rtworldshadows = false;
9671                 r_refdef.scene.rtdlight = false;
9672                 r_refdef.scene.rtdlightshadows = false;
9673                 r_refdef.lightmapintensity = 0;
9674         }
9675
9676         if (gamemode == GAME_NEHAHRA)
9677         {
9678                 if (gl_fogenable.integer)
9679                 {
9680                         r_refdef.oldgl_fogenable = true;
9681                         r_refdef.fog_density = gl_fogdensity.value;
9682                         r_refdef.fog_red = gl_fogred.value;
9683                         r_refdef.fog_green = gl_foggreen.value;
9684                         r_refdef.fog_blue = gl_fogblue.value;
9685                         r_refdef.fog_alpha = 1;
9686                         r_refdef.fog_start = 0;
9687                         r_refdef.fog_end = gl_skyclip.value;
9688                         r_refdef.fog_height = 1<<30;
9689                         r_refdef.fog_fadedepth = 128;
9690                 }
9691                 else if (r_refdef.oldgl_fogenable)
9692                 {
9693                         r_refdef.oldgl_fogenable = false;
9694                         r_refdef.fog_density = 0;
9695                         r_refdef.fog_red = 0;
9696                         r_refdef.fog_green = 0;
9697                         r_refdef.fog_blue = 0;
9698                         r_refdef.fog_alpha = 0;
9699                         r_refdef.fog_start = 0;
9700                         r_refdef.fog_end = 0;
9701                         r_refdef.fog_height = 1<<30;
9702                         r_refdef.fog_fadedepth = 128;
9703                 }
9704         }
9705
9706         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9707         r_refdef.fog_start = max(0, r_refdef.fog_start);
9708         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9709
9710         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9711
9712         if (r_refdef.fog_density && r_drawfog.integer)
9713         {
9714                 r_refdef.fogenabled = true;
9715                 // this is the point where the fog reaches 0.9986 alpha, which we
9716                 // consider a good enough cutoff point for the texture
9717                 // (0.9986 * 256 == 255.6)
9718                 if (r_fog_exp2.integer)
9719                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9720                 else
9721                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9722                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9723                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9724                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9725                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9726                         R_BuildFogHeightTexture();
9727                 // fog color was already set
9728                 // update the fog texture
9729                 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)
9730                         R_BuildFogTexture();
9731                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9732                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9733         }
9734         else
9735                 r_refdef.fogenabled = false;
9736
9737         switch(vid.renderpath)
9738         {
9739         case RENDERPATH_GL20:
9740         case RENDERPATH_CGGL:
9741         case RENDERPATH_D3D9:
9742         case RENDERPATH_D3D10:
9743         case RENDERPATH_D3D11:
9744         case RENDERPATH_SOFT:
9745                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9746                 {
9747                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9748                         {
9749                                 // build GLSL gamma texture
9750 #define RAMPWIDTH 256
9751                                 unsigned short ramp[RAMPWIDTH * 3];
9752                                 unsigned char rampbgr[RAMPWIDTH][4];
9753                                 int i;
9754
9755                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9756
9757                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9758                                 for(i = 0; i < RAMPWIDTH; ++i)
9759                                 {
9760                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9761                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9762                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9763                                         rampbgr[i][3] = 0;
9764                                 }
9765                                 if (r_texture_gammaramps)
9766                                 {
9767                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9768                                 }
9769                                 else
9770                                 {
9771                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9772                                 }
9773                         }
9774                 }
9775                 else
9776                 {
9777                         // remove GLSL gamma texture
9778                 }
9779                 break;
9780         case RENDERPATH_GL13:
9781         case RENDERPATH_GL11:
9782                 break;
9783         }
9784 }
9785
9786 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9787 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9788 /*
9789 ================
9790 R_SelectScene
9791 ================
9792 */
9793 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9794         if( scenetype != r_currentscenetype ) {
9795                 // store the old scenetype
9796                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9797                 r_currentscenetype = scenetype;
9798                 // move in the new scene
9799                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9800         }
9801 }
9802
9803 /*
9804 ================
9805 R_GetScenePointer
9806 ================
9807 */
9808 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9809 {
9810         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9811         if( scenetype == r_currentscenetype ) {
9812                 return &r_refdef.scene;
9813         } else {
9814                 return &r_scenes_store[ scenetype ];
9815         }
9816 }
9817
9818 /*
9819 ================
9820 R_RenderView
9821 ================
9822 */
9823 int dpsoftrast_test;
9824 void R_RenderView(void)
9825 {
9826         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9827
9828         dpsoftrast_test = r_test.integer;
9829
9830         if (r_timereport_active)
9831                 R_TimeReport("start");
9832         r_textureframe++; // used only by R_GetCurrentTexture
9833         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9834
9835         if(R_CompileShader_CheckStaticParms())
9836                 R_GLSL_Restart_f();
9837
9838         if (!r_drawentities.integer)
9839                 r_refdef.scene.numentities = 0;
9840
9841         R_AnimCache_ClearCache();
9842         R_FrameData_NewFrame();
9843
9844         /* adjust for stereo display */
9845         if(R_Stereo_Active())
9846         {
9847                 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);
9848                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9849         }
9850
9851         if (r_refdef.view.isoverlay)
9852         {
9853                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9854                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9855                 R_TimeReport("depthclear");
9856
9857                 r_refdef.view.showdebug = false;
9858
9859                 r_waterstate.enabled = false;
9860                 r_waterstate.numwaterplanes = 0;
9861
9862                 R_RenderScene();
9863
9864                 r_refdef.view.matrix = originalmatrix;
9865
9866                 CHECKGLERROR
9867                 return;
9868         }
9869
9870         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9871         {
9872                 r_refdef.view.matrix = originalmatrix;
9873                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9874         }
9875
9876         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9877
9878         R_RenderView_UpdateViewVectors();
9879
9880         R_Shadow_UpdateWorldLightSelection();
9881
9882         R_Bloom_StartFrame();
9883         R_Water_StartFrame();
9884
9885         CHECKGLERROR
9886         if (r_timereport_active)
9887                 R_TimeReport("viewsetup");
9888
9889         R_ResetViewRendering3D();
9890
9891         if (r_refdef.view.clear || r_refdef.fogenabled)
9892         {
9893                 R_ClearScreen(r_refdef.fogenabled);
9894                 if (r_timereport_active)
9895                         R_TimeReport("viewclear");
9896         }
9897         r_refdef.view.clear = true;
9898
9899         // this produces a bloom texture to be used in R_BlendView() later
9900         if (r_hdr.integer && r_bloomstate.bloomwidth)
9901         {
9902                 R_HDR_RenderBloomTexture();
9903                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9904                 r_textureframe++; // used only by R_GetCurrentTexture
9905         }
9906
9907         r_refdef.view.showdebug = true;
9908
9909         R_View_Update();
9910         if (r_timereport_active)
9911                 R_TimeReport("visibility");
9912
9913         r_waterstate.numwaterplanes = 0;
9914         if (r_waterstate.enabled)
9915                 R_RenderWaterPlanes();
9916
9917         R_RenderScene();
9918         r_waterstate.numwaterplanes = 0;
9919
9920         R_BlendView();
9921         if (r_timereport_active)
9922                 R_TimeReport("blendview");
9923
9924         GL_Scissor(0, 0, vid.width, vid.height);
9925         GL_ScissorTest(false);
9926
9927         r_refdef.view.matrix = originalmatrix;
9928
9929         CHECKGLERROR
9930 }
9931
9932 void R_RenderWaterPlanes(void)
9933 {
9934         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9935         {
9936                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9937                 if (r_timereport_active)
9938                         R_TimeReport("waterworld");
9939         }
9940
9941         // don't let sound skip if going slow
9942         if (r_refdef.scene.extraupdate)
9943                 S_ExtraUpdate ();
9944
9945         R_DrawModelsAddWaterPlanes();
9946         if (r_timereport_active)
9947                 R_TimeReport("watermodels");
9948
9949         if (r_waterstate.numwaterplanes)
9950         {
9951                 R_Water_ProcessPlanes();
9952                 if (r_timereport_active)
9953                         R_TimeReport("waterscenes");
9954         }
9955 }
9956
9957 extern void R_DrawLightningBeams (void);
9958 extern void VM_CL_AddPolygonsToMeshQueue (void);
9959 extern void R_DrawPortals (void);
9960 extern cvar_t cl_locs_show;
9961 static void R_DrawLocs(void);
9962 static void R_DrawEntityBBoxes(void);
9963 static void R_DrawModelDecals(void);
9964 extern void R_DrawModelShadows(void);
9965 extern void R_DrawModelShadowMaps(void);
9966 extern cvar_t cl_decals_newsystem;
9967 extern qboolean r_shadow_usingdeferredprepass;
9968 void R_RenderScene(void)
9969 {
9970         qboolean shadowmapping = false;
9971
9972         if (r_timereport_active)
9973                 R_TimeReport("beginscene");
9974
9975         r_refdef.stats.renders++;
9976
9977         R_UpdateFogColor();
9978
9979         // don't let sound skip if going slow
9980         if (r_refdef.scene.extraupdate)
9981                 S_ExtraUpdate ();
9982
9983         R_MeshQueue_BeginScene();
9984
9985         R_SkyStartFrame();
9986
9987         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);
9988
9989         if (r_timereport_active)
9990                 R_TimeReport("skystartframe");
9991
9992         if (cl.csqc_vidvars.drawworld)
9993         {
9994                 // don't let sound skip if going slow
9995                 if (r_refdef.scene.extraupdate)
9996                         S_ExtraUpdate ();
9997
9998                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9999                 {
10000                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
10001                         if (r_timereport_active)
10002                                 R_TimeReport("worldsky");
10003                 }
10004
10005                 if (R_DrawBrushModelsSky() && r_timereport_active)
10006                         R_TimeReport("bmodelsky");
10007
10008                 if (skyrendermasked && skyrenderlater)
10009                 {
10010                         // we have to force off the water clipping plane while rendering sky
10011                         R_SetupView(false);
10012                         R_Sky();
10013                         R_SetupView(true);
10014                         if (r_timereport_active)
10015                                 R_TimeReport("sky");
10016                 }
10017         }
10018
10019         R_AnimCache_CacheVisibleEntities();
10020         if (r_timereport_active)
10021                 R_TimeReport("animation");
10022
10023         R_Shadow_PrepareLights();
10024         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
10025                 R_Shadow_PrepareModelShadows();
10026         if (r_timereport_active)
10027                 R_TimeReport("preparelights");
10028
10029         if (R_Shadow_ShadowMappingEnabled())
10030                 shadowmapping = true;
10031
10032         if (r_shadow_usingdeferredprepass)
10033                 R_Shadow_DrawPrepass();
10034
10035         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
10036         {
10037                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
10038                 if (r_timereport_active)
10039                         R_TimeReport("worlddepth");
10040         }
10041         if (r_depthfirst.integer >= 2)
10042         {
10043                 R_DrawModelsDepth();
10044                 if (r_timereport_active)
10045                         R_TimeReport("modeldepth");
10046         }
10047
10048         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
10049         {
10050                 R_DrawModelShadowMaps();
10051                 R_ResetViewRendering3D();
10052                 // don't let sound skip if going slow
10053                 if (r_refdef.scene.extraupdate)
10054                         S_ExtraUpdate ();
10055         }
10056
10057         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
10058         {
10059                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
10060                 if (r_timereport_active)
10061                         R_TimeReport("world");
10062         }
10063
10064         // don't let sound skip if going slow
10065         if (r_refdef.scene.extraupdate)
10066                 S_ExtraUpdate ();
10067
10068         R_DrawModels();
10069         if (r_timereport_active)
10070                 R_TimeReport("models");
10071
10072         // don't let sound skip if going slow
10073         if (r_refdef.scene.extraupdate)
10074                 S_ExtraUpdate ();
10075
10076         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10077         {
10078                 R_DrawModelShadows();
10079                 R_ResetViewRendering3D();
10080                 // don't let sound skip if going slow
10081                 if (r_refdef.scene.extraupdate)
10082                         S_ExtraUpdate ();
10083         }
10084
10085         if (!r_shadow_usingdeferredprepass)
10086         {
10087                 R_Shadow_DrawLights();
10088                 if (r_timereport_active)
10089                         R_TimeReport("rtlights");
10090         }
10091
10092         // don't let sound skip if going slow
10093         if (r_refdef.scene.extraupdate)
10094                 S_ExtraUpdate ();
10095
10096         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10097         {
10098                 R_DrawModelShadows();
10099                 R_ResetViewRendering3D();
10100                 // don't let sound skip if going slow
10101                 if (r_refdef.scene.extraupdate)
10102                         S_ExtraUpdate ();
10103         }
10104
10105         if (cl.csqc_vidvars.drawworld)
10106         {
10107                 if (cl_decals_newsystem.integer)
10108                 {
10109                         R_DrawModelDecals();
10110                         if (r_timereport_active)
10111                                 R_TimeReport("modeldecals");
10112                 }
10113                 else
10114                 {
10115                         R_DrawDecals();
10116                         if (r_timereport_active)
10117                                 R_TimeReport("decals");
10118                 }
10119
10120                 R_DrawParticles();
10121                 if (r_timereport_active)
10122                         R_TimeReport("particles");
10123
10124                 R_DrawExplosions();
10125                 if (r_timereport_active)
10126                         R_TimeReport("explosions");
10127
10128                 R_DrawLightningBeams();
10129                 if (r_timereport_active)
10130                         R_TimeReport("lightning");
10131         }
10132
10133         VM_CL_AddPolygonsToMeshQueue();
10134
10135         if (r_refdef.view.showdebug)
10136         {
10137                 if (cl_locs_show.integer)
10138                 {
10139                         R_DrawLocs();
10140                         if (r_timereport_active)
10141                                 R_TimeReport("showlocs");
10142                 }
10143
10144                 if (r_drawportals.integer)
10145                 {
10146                         R_DrawPortals();
10147                         if (r_timereport_active)
10148                                 R_TimeReport("portals");
10149                 }
10150
10151                 if (r_showbboxes.value > 0)
10152                 {
10153                         R_DrawEntityBBoxes();
10154                         if (r_timereport_active)
10155                                 R_TimeReport("bboxes");
10156                 }
10157         }
10158
10159         R_MeshQueue_RenderTransparent();
10160         if (r_timereport_active)
10161                 R_TimeReport("drawtrans");
10162
10163         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))
10164         {
10165                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10166                 if (r_timereport_active)
10167                         R_TimeReport("worlddebug");
10168                 R_DrawModelsDebug();
10169                 if (r_timereport_active)
10170                         R_TimeReport("modeldebug");
10171         }
10172
10173         if (cl.csqc_vidvars.drawworld)
10174         {
10175                 R_Shadow_DrawCoronas();
10176                 if (r_timereport_active)
10177                         R_TimeReport("coronas");
10178         }
10179
10180 #if 0
10181         {
10182                 GL_DepthTest(false);
10183                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10184                 GL_Color(1, 1, 1, 1);
10185                 qglBegin(GL_POLYGON);
10186                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10187                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10188                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10189                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10190                 qglEnd();
10191                 qglBegin(GL_POLYGON);
10192                 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]);
10193                 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]);
10194                 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]);
10195                 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]);
10196                 qglEnd();
10197                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10198         }
10199 #endif
10200
10201         // don't let sound skip if going slow
10202         if (r_refdef.scene.extraupdate)
10203                 S_ExtraUpdate ();
10204
10205         R_ResetViewRendering2D();
10206 }
10207
10208 static const unsigned short bboxelements[36] =
10209 {
10210         5, 1, 3, 5, 3, 7,
10211         6, 2, 0, 6, 0, 4,
10212         7, 3, 2, 7, 2, 6,
10213         4, 0, 1, 4, 1, 5,
10214         4, 5, 7, 4, 7, 6,
10215         1, 0, 2, 1, 2, 3,
10216 };
10217
10218 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10219 {
10220         int i;
10221         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10222
10223         RSurf_ActiveWorldEntity();
10224
10225         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10226         GL_DepthMask(false);
10227         GL_DepthRange(0, 1);
10228         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10229 //      R_Mesh_ResetTextureState();
10230
10231         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10232         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10233         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10234         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10235         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10236         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10237         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10238         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10239         R_FillColors(color4f, 8, cr, cg, cb, ca);
10240         if (r_refdef.fogenabled)
10241         {
10242                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10243                 {
10244                         f1 = RSurf_FogVertex(v);
10245                         f2 = 1 - f1;
10246                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10247                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10248                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10249                 }
10250         }
10251         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10252         R_Mesh_ResetTextureState();
10253         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10254         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10255 }
10256
10257 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10258 {
10259         int i;
10260         float color[4];
10261         prvm_edict_t *edict;
10262         prvm_prog_t *prog_save = prog;
10263
10264         // this function draws bounding boxes of server entities
10265         if (!sv.active)
10266                 return;
10267
10268         GL_CullFace(GL_NONE);
10269         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10270
10271         prog = 0;
10272         SV_VM_Begin();
10273         for (i = 0;i < numsurfaces;i++)
10274         {
10275                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10276                 switch ((int)edict->fields.server->solid)
10277                 {
10278                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10279                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10280                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10281                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10282                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10283                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10284                 }
10285                 color[3] *= r_showbboxes.value;
10286                 color[3] = bound(0, color[3], 1);
10287                 GL_DepthTest(!r_showdisabledepthtest.integer);
10288                 GL_CullFace(r_refdef.view.cullface_front);
10289                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10290         }
10291         SV_VM_End();
10292         prog = prog_save;
10293 }
10294
10295 static void R_DrawEntityBBoxes(void)
10296 {
10297         int i;
10298         prvm_edict_t *edict;
10299         vec3_t center;
10300         prvm_prog_t *prog_save = prog;
10301
10302         // this function draws bounding boxes of server entities
10303         if (!sv.active)
10304                 return;
10305
10306         prog = 0;
10307         SV_VM_Begin();
10308         for (i = 0;i < prog->num_edicts;i++)
10309         {
10310                 edict = PRVM_EDICT_NUM(i);
10311                 if (edict->priv.server->free)
10312                         continue;
10313                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10314                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10315                         continue;
10316                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10317                         continue;
10318                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10319                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10320         }
10321         SV_VM_End();
10322         prog = prog_save;
10323 }
10324
10325 static const int nomodelelement3i[24] =
10326 {
10327         5, 2, 0,
10328         5, 1, 2,
10329         5, 0, 3,
10330         5, 3, 1,
10331         0, 2, 4,
10332         2, 1, 4,
10333         3, 0, 4,
10334         1, 3, 4
10335 };
10336
10337 static const unsigned short nomodelelement3s[24] =
10338 {
10339         5, 2, 0,
10340         5, 1, 2,
10341         5, 0, 3,
10342         5, 3, 1,
10343         0, 2, 4,
10344         2, 1, 4,
10345         3, 0, 4,
10346         1, 3, 4
10347 };
10348
10349 static const float nomodelvertex3f[6*3] =
10350 {
10351         -16,   0,   0,
10352          16,   0,   0,
10353           0, -16,   0,
10354           0,  16,   0,
10355           0,   0, -16,
10356           0,   0,  16
10357 };
10358
10359 static const float nomodelcolor4f[6*4] =
10360 {
10361         0.0f, 0.0f, 0.5f, 1.0f,
10362         0.0f, 0.0f, 0.5f, 1.0f,
10363         0.0f, 0.5f, 0.0f, 1.0f,
10364         0.0f, 0.5f, 0.0f, 1.0f,
10365         0.5f, 0.0f, 0.0f, 1.0f,
10366         0.5f, 0.0f, 0.0f, 1.0f
10367 };
10368
10369 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10370 {
10371         int i;
10372         float f1, f2, *c;
10373         float color4f[6*4];
10374
10375         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);
10376
10377         // this is only called once per entity so numsurfaces is always 1, and
10378         // surfacelist is always {0}, so this code does not handle batches
10379
10380         if (rsurface.ent_flags & RENDER_ADDITIVE)
10381         {
10382                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10383                 GL_DepthMask(false);
10384         }
10385         else if (rsurface.colormod[3] < 1)
10386         {
10387                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10388                 GL_DepthMask(false);
10389         }
10390         else
10391         {
10392                 GL_BlendFunc(GL_ONE, GL_ZERO);
10393                 GL_DepthMask(true);
10394         }
10395         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10396         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10397         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10398         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10399         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10400         for (i = 0, c = color4f;i < 6;i++, c += 4)
10401         {
10402                 c[0] *= rsurface.colormod[0];
10403                 c[1] *= rsurface.colormod[1];
10404                 c[2] *= rsurface.colormod[2];
10405                 c[3] *= rsurface.colormod[3];
10406         }
10407         if (r_refdef.fogenabled)
10408         {
10409                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10410                 {
10411                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10412                         f2 = 1 - f1;
10413                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10414                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10415                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10416                 }
10417         }
10418 //      R_Mesh_ResetTextureState();
10419         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10420         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10421         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10422 }
10423
10424 void R_DrawNoModel(entity_render_t *ent)
10425 {
10426         vec3_t org;
10427         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10428         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10429                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10430         else
10431                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10432 }
10433
10434 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10435 {
10436         vec3_t right1, right2, diff, normal;
10437
10438         VectorSubtract (org2, org1, normal);
10439
10440         // calculate 'right' vector for start
10441         VectorSubtract (r_refdef.view.origin, org1, diff);
10442         CrossProduct (normal, diff, right1);
10443         VectorNormalize (right1);
10444
10445         // calculate 'right' vector for end
10446         VectorSubtract (r_refdef.view.origin, org2, diff);
10447         CrossProduct (normal, diff, right2);
10448         VectorNormalize (right2);
10449
10450         vert[ 0] = org1[0] + width * right1[0];
10451         vert[ 1] = org1[1] + width * right1[1];
10452         vert[ 2] = org1[2] + width * right1[2];
10453         vert[ 3] = org1[0] - width * right1[0];
10454         vert[ 4] = org1[1] - width * right1[1];
10455         vert[ 5] = org1[2] - width * right1[2];
10456         vert[ 6] = org2[0] - width * right2[0];
10457         vert[ 7] = org2[1] - width * right2[1];
10458         vert[ 8] = org2[2] - width * right2[2];
10459         vert[ 9] = org2[0] + width * right2[0];
10460         vert[10] = org2[1] + width * right2[1];
10461         vert[11] = org2[2] + width * right2[2];
10462 }
10463
10464 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)
10465 {
10466         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10467         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10468         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10469         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10470         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10471         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10472         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10473         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10474         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10475         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10476         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10477         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10478 }
10479
10480 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10481 {
10482         int i;
10483         float *vertex3f;
10484         float v[3];
10485         VectorSet(v, x, y, z);
10486         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10487                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10488                         break;
10489         if (i == mesh->numvertices)
10490         {
10491                 if (mesh->numvertices < mesh->maxvertices)
10492                 {
10493                         VectorCopy(v, vertex3f);
10494                         mesh->numvertices++;
10495                 }
10496                 return mesh->numvertices;
10497         }
10498         else
10499                 return i;
10500 }
10501
10502 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10503 {
10504         int i;
10505         int *e, element[3];
10506         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10507         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10508         e = mesh->element3i + mesh->numtriangles * 3;
10509         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10510         {
10511                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10512                 if (mesh->numtriangles < mesh->maxtriangles)
10513                 {
10514                         *e++ = element[0];
10515                         *e++ = element[1];
10516                         *e++ = element[2];
10517                         mesh->numtriangles++;
10518                 }
10519                 element[1] = element[2];
10520         }
10521 }
10522
10523 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10524 {
10525         int i;
10526         int *e, element[3];
10527         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10528         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10529         e = mesh->element3i + mesh->numtriangles * 3;
10530         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10531         {
10532                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10533                 if (mesh->numtriangles < mesh->maxtriangles)
10534                 {
10535                         *e++ = element[0];
10536                         *e++ = element[1];
10537                         *e++ = element[2];
10538                         mesh->numtriangles++;
10539                 }
10540                 element[1] = element[2];
10541         }
10542 }
10543
10544 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10545 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10546 {
10547         int planenum, planenum2;
10548         int w;
10549         int tempnumpoints;
10550         mplane_t *plane, *plane2;
10551         double maxdist;
10552         double temppoints[2][256*3];
10553         // figure out how large a bounding box we need to properly compute this brush
10554         maxdist = 0;
10555         for (w = 0;w < numplanes;w++)
10556                 maxdist = max(maxdist, fabs(planes[w].dist));
10557         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10558         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10559         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10560         {
10561                 w = 0;
10562                 tempnumpoints = 4;
10563                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10564                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10565                 {
10566                         if (planenum2 == planenum)
10567                                 continue;
10568                         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);
10569                         w = !w;
10570                 }
10571                 if (tempnumpoints < 3)
10572                         continue;
10573                 // generate elements forming a triangle fan for this polygon
10574                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10575         }
10576 }
10577
10578 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)
10579 {
10580         texturelayer_t *layer;
10581         layer = t->currentlayers + t->currentnumlayers++;
10582         layer->type = type;
10583         layer->depthmask = depthmask;
10584         layer->blendfunc1 = blendfunc1;
10585         layer->blendfunc2 = blendfunc2;
10586         layer->texture = texture;
10587         layer->texmatrix = *matrix;
10588         layer->color[0] = r;
10589         layer->color[1] = g;
10590         layer->color[2] = b;
10591         layer->color[3] = a;
10592 }
10593
10594 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10595 {
10596         if(parms[0] == 0 && parms[1] == 0)
10597                 return false;
10598         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10599                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10600                         return false;
10601         return true;
10602 }
10603
10604 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10605 {
10606         double index, f;
10607         index = parms[2] + r_refdef.scene.time * parms[3];
10608         index -= floor(index);
10609         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10610         {
10611         default:
10612         case Q3WAVEFUNC_NONE:
10613         case Q3WAVEFUNC_NOISE:
10614         case Q3WAVEFUNC_COUNT:
10615                 f = 0;
10616                 break;
10617         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10618         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10619         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10620         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10621         case Q3WAVEFUNC_TRIANGLE:
10622                 index *= 4;
10623                 f = index - floor(index);
10624                 if (index < 1)
10625                         f = f;
10626                 else if (index < 2)
10627                         f = 1 - f;
10628                 else if (index < 3)
10629                         f = -f;
10630                 else
10631                         f = -(1 - f);
10632                 break;
10633         }
10634         f = parms[0] + parms[1] * f;
10635         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10636                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10637         return (float) f;
10638 }
10639
10640 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10641 {
10642         int w, h, idx;
10643         float f;
10644         float tcmat[12];
10645         matrix4x4_t matrix, temp;
10646         switch(tcmod->tcmod)
10647         {
10648                 case Q3TCMOD_COUNT:
10649                 case Q3TCMOD_NONE:
10650                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10651                                 matrix = r_waterscrollmatrix;
10652                         else
10653                                 matrix = identitymatrix;
10654                         break;
10655                 case Q3TCMOD_ENTITYTRANSLATE:
10656                         // this is used in Q3 to allow the gamecode to control texcoord
10657                         // scrolling on the entity, which is not supported in darkplaces yet.
10658                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10659                         break;
10660                 case Q3TCMOD_ROTATE:
10661                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10662                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10663                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10664                         break;
10665                 case Q3TCMOD_SCALE:
10666                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10667                         break;
10668                 case Q3TCMOD_SCROLL:
10669                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10670                         break;
10671                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10672                         w = (int) tcmod->parms[0];
10673                         h = (int) tcmod->parms[1];
10674                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10675                         f = f - floor(f);
10676                         idx = (int) floor(f * w * h);
10677                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10678                         break;
10679                 case Q3TCMOD_STRETCH:
10680                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10681                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10682                         break;
10683                 case Q3TCMOD_TRANSFORM:
10684                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10685                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10686                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10687                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10688                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10689                         break;
10690                 case Q3TCMOD_TURBULENT:
10691                         // this is handled in the RSurf_PrepareVertices function
10692                         matrix = identitymatrix;
10693                         break;
10694         }
10695         temp = *texmatrix;
10696         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10697 }
10698
10699 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10700 {
10701         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10702         char name[MAX_QPATH];
10703         skinframe_t *skinframe;
10704         unsigned char pixels[296*194];
10705         strlcpy(cache->name, skinname, sizeof(cache->name));
10706         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10707         if (developer_loading.integer)
10708                 Con_Printf("loading %s\n", name);
10709         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10710         if (!skinframe || !skinframe->base)
10711         {
10712                 unsigned char *f;
10713                 fs_offset_t filesize;
10714                 skinframe = NULL;
10715                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10716                 if (f)
10717                 {
10718                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10719                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10720                         Mem_Free(f);
10721                 }
10722         }
10723         cache->skinframe = skinframe;
10724 }
10725
10726 texture_t *R_GetCurrentTexture(texture_t *t)
10727 {
10728         int i;
10729         const entity_render_t *ent = rsurface.entity;
10730         dp_model_t *model = ent->model;
10731         q3shaderinfo_layer_tcmod_t *tcmod;
10732
10733         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10734                 return t->currentframe;
10735         t->update_lastrenderframe = r_textureframe;
10736         t->update_lastrenderentity = (void *)ent;
10737
10738         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10739                 t->camera_entity = ent->entitynumber;
10740         else
10741                 t->camera_entity = 0;
10742
10743         // switch to an alternate material if this is a q1bsp animated material
10744         {
10745                 texture_t *texture = t;
10746                 int s = rsurface.ent_skinnum;
10747                 if ((unsigned int)s >= (unsigned int)model->numskins)
10748                         s = 0;
10749                 if (model->skinscenes)
10750                 {
10751                         if (model->skinscenes[s].framecount > 1)
10752                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10753                         else
10754                                 s = model->skinscenes[s].firstframe;
10755                 }
10756                 if (s > 0)
10757                         t = t + s * model->num_surfaces;
10758                 if (t->animated)
10759                 {
10760                         // use an alternate animation if the entity's frame is not 0,
10761                         // and only if the texture has an alternate animation
10762                         if (rsurface.ent_alttextures && t->anim_total[1])
10763                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10764                         else
10765                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10766                 }
10767                 texture->currentframe = t;
10768         }
10769
10770         // update currentskinframe to be a qw skin or animation frame
10771         if (rsurface.ent_qwskin >= 0)
10772         {
10773                 i = rsurface.ent_qwskin;
10774                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10775                 {
10776                         r_qwskincache_size = cl.maxclients;
10777                         if (r_qwskincache)
10778                                 Mem_Free(r_qwskincache);
10779                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10780                 }
10781                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10782                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10783                 t->currentskinframe = r_qwskincache[i].skinframe;
10784                 if (t->currentskinframe == NULL)
10785                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10786         }
10787         else if (t->numskinframes >= 2)
10788                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10789         if (t->backgroundnumskinframes >= 2)
10790                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10791
10792         t->currentmaterialflags = t->basematerialflags;
10793         t->currentalpha = rsurface.colormod[3];
10794         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10795                 t->currentalpha *= r_wateralpha.value;
10796         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10797                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10798         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10799                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10800         if (!(rsurface.ent_flags & RENDER_LIGHT))
10801                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10802         else if (FAKELIGHT_ENABLED)
10803         {
10804                         // no modellight if using fakelight for the map
10805         }
10806         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10807         {
10808                 // pick a model lighting mode
10809                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10810                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10811                 else
10812                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10813         }
10814         if (rsurface.ent_flags & RENDER_ADDITIVE)
10815                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10816         else if (t->currentalpha < 1)
10817                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10818         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10819                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10820         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10821                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10822         if (t->backgroundnumskinframes)
10823                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10824         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10825         {
10826                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10827                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10828         }
10829         else
10830                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10831         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10832                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10833
10834         // there is no tcmod
10835         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10836         {
10837                 t->currenttexmatrix = r_waterscrollmatrix;
10838                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10839         }
10840         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10841         {
10842                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10843                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10844         }
10845
10846         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10847                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10848         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10849                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10850
10851         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10852         if (t->currentskinframe->qpixels)
10853                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10854         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10855         if (!t->basetexture)
10856                 t->basetexture = r_texture_notexture;
10857         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10858         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10859         t->nmaptexture = t->currentskinframe->nmap;
10860         if (!t->nmaptexture)
10861                 t->nmaptexture = r_texture_blanknormalmap;
10862         t->glosstexture = r_texture_black;
10863         t->glowtexture = t->currentskinframe->glow;
10864         t->fogtexture = t->currentskinframe->fog;
10865         t->reflectmasktexture = t->currentskinframe->reflect;
10866         if (t->backgroundnumskinframes)
10867         {
10868                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10869                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10870                 t->backgroundglosstexture = r_texture_black;
10871                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10872                 if (!t->backgroundnmaptexture)
10873                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10874         }
10875         else
10876         {
10877                 t->backgroundbasetexture = r_texture_white;
10878                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10879                 t->backgroundglosstexture = r_texture_black;
10880                 t->backgroundglowtexture = NULL;
10881         }
10882         t->specularpower = r_shadow_glossexponent.value;
10883         // TODO: store reference values for these in the texture?
10884         t->specularscale = 0;
10885         if (r_shadow_gloss.integer > 0)
10886         {
10887                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10888                 {
10889                         if (r_shadow_glossintensity.value > 0)
10890                         {
10891                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10892                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10893                                 t->specularscale = r_shadow_glossintensity.value;
10894                         }
10895                 }
10896                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10897                 {
10898                         t->glosstexture = r_texture_white;
10899                         t->backgroundglosstexture = r_texture_white;
10900                         t->specularscale = r_shadow_gloss2intensity.value;
10901                         t->specularpower = r_shadow_gloss2exponent.value;
10902                 }
10903         }
10904         t->specularscale *= t->specularscalemod;
10905         t->specularpower *= t->specularpowermod;
10906
10907         // lightmaps mode looks bad with dlights using actual texturing, so turn
10908         // off the colormap and glossmap, but leave the normalmap on as it still
10909         // accurately represents the shading involved
10910         if (gl_lightmaps.integer)
10911         {
10912                 t->basetexture = r_texture_grey128;
10913                 t->pantstexture = r_texture_black;
10914                 t->shirttexture = r_texture_black;
10915                 t->nmaptexture = r_texture_blanknormalmap;
10916                 t->glosstexture = r_texture_black;
10917                 t->glowtexture = NULL;
10918                 t->fogtexture = NULL;
10919                 t->reflectmasktexture = NULL;
10920                 t->backgroundbasetexture = NULL;
10921                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10922                 t->backgroundglosstexture = r_texture_black;
10923                 t->backgroundglowtexture = NULL;
10924                 t->specularscale = 0;
10925                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10926         }
10927
10928         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10929         VectorClear(t->dlightcolor);
10930         t->currentnumlayers = 0;
10931         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10932         {
10933                 int blendfunc1, blendfunc2;
10934                 qboolean depthmask;
10935                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10936                 {
10937                         blendfunc1 = GL_SRC_ALPHA;
10938                         blendfunc2 = GL_ONE;
10939                 }
10940                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10941                 {
10942                         blendfunc1 = GL_SRC_ALPHA;
10943                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10944                 }
10945                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10946                 {
10947                         blendfunc1 = t->customblendfunc[0];
10948                         blendfunc2 = t->customblendfunc[1];
10949                 }
10950                 else
10951                 {
10952                         blendfunc1 = GL_ONE;
10953                         blendfunc2 = GL_ZERO;
10954                 }
10955                 // don't colormod evilblend textures
10956                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10957                         VectorSet(t->lightmapcolor, 1, 1, 1);
10958                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10959                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10960                 {
10961                         // fullbright is not affected by r_refdef.lightmapintensity
10962                         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]);
10963                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10964                                 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]);
10965                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10966                                 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]);
10967                 }
10968                 else
10969                 {
10970                         vec3_t ambientcolor;
10971                         float colorscale;
10972                         // set the color tint used for lights affecting this surface
10973                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10974                         colorscale = 2;
10975                         // q3bsp has no lightmap updates, so the lightstylevalue that
10976                         // would normally be baked into the lightmap must be
10977                         // applied to the color
10978                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10979                         if (model->type == mod_brushq3)
10980                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10981                         colorscale *= r_refdef.lightmapintensity;
10982                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10983                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10984                         // basic lit geometry
10985                         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]);
10986                         // add pants/shirt if needed
10987                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10988                                 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]);
10989                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10990                                 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]);
10991                         // now add ambient passes if needed
10992                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10993                         {
10994                                 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]);
10995                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10996                                         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]);
10997                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10998                                         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]);
10999                         }
11000                 }
11001                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
11002                         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]);
11003                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
11004                 {
11005                         // if this is opaque use alpha blend which will darken the earlier
11006                         // passes cheaply.
11007                         //
11008                         // if this is an alpha blended material, all the earlier passes
11009                         // were darkened by fog already, so we only need to add the fog
11010                         // color ontop through the fog mask texture
11011                         //
11012                         // if this is an additive blended material, all the earlier passes
11013                         // were darkened by fog already, and we should not add fog color
11014                         // (because the background was not darkened, there is no fog color
11015                         // that was lost behind it).
11016                         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]);
11017                 }
11018         }
11019
11020         return t->currentframe;
11021 }
11022
11023 rsurfacestate_t rsurface;
11024
11025 void RSurf_ActiveWorldEntity(void)
11026 {
11027         dp_model_t *model = r_refdef.scene.worldmodel;
11028         //if (rsurface.entity == r_refdef.scene.worldentity)
11029         //      return;
11030         rsurface.entity = r_refdef.scene.worldentity;
11031         rsurface.skeleton = NULL;
11032         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
11033         rsurface.ent_skinnum = 0;
11034         rsurface.ent_qwskin = -1;
11035         rsurface.ent_shadertime = 0;
11036         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
11037         rsurface.matrix = identitymatrix;
11038         rsurface.inversematrix = identitymatrix;
11039         rsurface.matrixscale = 1;
11040         rsurface.inversematrixscale = 1;
11041         R_EntityMatrix(&identitymatrix);
11042         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
11043         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
11044         rsurface.fograngerecip = r_refdef.fograngerecip;
11045         rsurface.fogheightfade = r_refdef.fogheightfade;
11046         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
11047         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11048         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11049         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11050         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11051         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11052         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11053         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
11054         rsurface.colormod[3] = 1;
11055         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);
11056         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11057         rsurface.frameblend[0].lerp = 1;
11058         rsurface.ent_alttextures = false;
11059         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11060         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11061         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11062         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11063         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11064         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11065         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11066         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11067         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11068         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11069         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11070         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11071         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11072         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11073         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11074         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11075         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11076         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11077         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11078         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11079         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11080         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11081         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11082         rsurface.modelelement3i = model->surfmesh.data_element3i;
11083         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11084         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11085         rsurface.modelelement3s = model->surfmesh.data_element3s;
11086         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11087         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11088         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11089         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11090         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11091         rsurface.modelsurfaces = model->data_surfaces;
11092         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11093         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11094         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11095         rsurface.modelgeneratedvertex = false;
11096         rsurface.batchgeneratedvertex = false;
11097         rsurface.batchfirstvertex = 0;
11098         rsurface.batchnumvertices = 0;
11099         rsurface.batchfirsttriangle = 0;
11100         rsurface.batchnumtriangles = 0;
11101         rsurface.batchvertex3f  = NULL;
11102         rsurface.batchvertex3f_vertexbuffer = NULL;
11103         rsurface.batchvertex3f_bufferoffset = 0;
11104         rsurface.batchsvector3f = NULL;
11105         rsurface.batchsvector3f_vertexbuffer = NULL;
11106         rsurface.batchsvector3f_bufferoffset = 0;
11107         rsurface.batchtvector3f = NULL;
11108         rsurface.batchtvector3f_vertexbuffer = NULL;
11109         rsurface.batchtvector3f_bufferoffset = 0;
11110         rsurface.batchnormal3f  = NULL;
11111         rsurface.batchnormal3f_vertexbuffer = NULL;
11112         rsurface.batchnormal3f_bufferoffset = 0;
11113         rsurface.batchlightmapcolor4f = NULL;
11114         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11115         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11116         rsurface.batchtexcoordtexture2f = NULL;
11117         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11118         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11119         rsurface.batchtexcoordlightmap2f = NULL;
11120         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11121         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11122         rsurface.batchvertexmesh = NULL;
11123         rsurface.batchvertexmeshbuffer = NULL;
11124         rsurface.batchvertex3fbuffer = NULL;
11125         rsurface.batchelement3i = NULL;
11126         rsurface.batchelement3i_indexbuffer = NULL;
11127         rsurface.batchelement3i_bufferoffset = 0;
11128         rsurface.batchelement3s = NULL;
11129         rsurface.batchelement3s_indexbuffer = NULL;
11130         rsurface.batchelement3s_bufferoffset = 0;
11131         rsurface.passcolor4f = NULL;
11132         rsurface.passcolor4f_vertexbuffer = NULL;
11133         rsurface.passcolor4f_bufferoffset = 0;
11134 }
11135
11136 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11137 {
11138         dp_model_t *model = ent->model;
11139         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11140         //      return;
11141         rsurface.entity = (entity_render_t *)ent;
11142         rsurface.skeleton = ent->skeleton;
11143         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11144         rsurface.ent_skinnum = ent->skinnum;
11145         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;
11146         rsurface.ent_shadertime = ent->shadertime;
11147         rsurface.ent_flags = ent->flags;
11148         rsurface.matrix = ent->matrix;
11149         rsurface.inversematrix = ent->inversematrix;
11150         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11151         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11152         R_EntityMatrix(&rsurface.matrix);
11153         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11154         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11155         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11156         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11157         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11158         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11159         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11160         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11161         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11162         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11163         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11164         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11165         rsurface.colormod[3] = ent->alpha;
11166         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11167         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11168         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11169         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11170         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11171         if (ent->model->brush.submodel && !prepass)
11172         {
11173                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11174                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11175         }
11176         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11177         {
11178                 if (ent->animcache_vertex3f)
11179                 {
11180                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11181                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11182                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11183                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11184                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11185                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11186                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
11187                 }
11188                 else if (wanttangents)
11189                 {
11190                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11191                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11192                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11193                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11194                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
11195                         rsurface.modelvertexmesh = NULL;
11196                         rsurface.modelvertexmeshbuffer = NULL;
11197                         rsurface.modelvertex3fbuffer = NULL;
11198                 }
11199                 else if (wantnormals)
11200                 {
11201                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11202                         rsurface.modelsvector3f = NULL;
11203                         rsurface.modeltvector3f = NULL;
11204                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11205                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
11206                         rsurface.modelvertexmesh = NULL;
11207                         rsurface.modelvertexmeshbuffer = NULL;
11208                         rsurface.modelvertex3fbuffer = NULL;
11209                 }
11210                 else
11211                 {
11212                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11213                         rsurface.modelsvector3f = NULL;
11214                         rsurface.modeltvector3f = NULL;
11215                         rsurface.modelnormal3f = NULL;
11216                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
11217                         rsurface.modelvertexmesh = NULL;
11218                         rsurface.modelvertexmeshbuffer = NULL;
11219                         rsurface.modelvertex3fbuffer = NULL;
11220                 }
11221                 rsurface.modelvertex3f_vertexbuffer = 0;
11222                 rsurface.modelvertex3f_bufferoffset = 0;
11223                 rsurface.modelsvector3f_vertexbuffer = 0;
11224                 rsurface.modelsvector3f_bufferoffset = 0;
11225                 rsurface.modeltvector3f_vertexbuffer = 0;
11226                 rsurface.modeltvector3f_bufferoffset = 0;
11227                 rsurface.modelnormal3f_vertexbuffer = 0;
11228                 rsurface.modelnormal3f_bufferoffset = 0;
11229                 rsurface.modelgeneratedvertex = true;
11230         }
11231         else
11232         {
11233                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11234                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11235                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11236                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11237                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11238                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11239                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11240                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11241                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11242                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11243                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11244                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11245                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11246                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11247                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11248                 rsurface.modelgeneratedvertex = false;
11249         }
11250         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11251         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11252         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11253         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11254         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11255         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11256         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11257         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11258         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11259         rsurface.modelelement3i = model->surfmesh.data_element3i;
11260         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11261         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11262         rsurface.modelelement3s = model->surfmesh.data_element3s;
11263         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11264         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11265         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11266         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11267         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11268         rsurface.modelsurfaces = model->data_surfaces;
11269         rsurface.batchgeneratedvertex = false;
11270         rsurface.batchfirstvertex = 0;
11271         rsurface.batchnumvertices = 0;
11272         rsurface.batchfirsttriangle = 0;
11273         rsurface.batchnumtriangles = 0;
11274         rsurface.batchvertex3f  = NULL;
11275         rsurface.batchvertex3f_vertexbuffer = NULL;
11276         rsurface.batchvertex3f_bufferoffset = 0;
11277         rsurface.batchsvector3f = NULL;
11278         rsurface.batchsvector3f_vertexbuffer = NULL;
11279         rsurface.batchsvector3f_bufferoffset = 0;
11280         rsurface.batchtvector3f = NULL;
11281         rsurface.batchtvector3f_vertexbuffer = NULL;
11282         rsurface.batchtvector3f_bufferoffset = 0;
11283         rsurface.batchnormal3f  = NULL;
11284         rsurface.batchnormal3f_vertexbuffer = NULL;
11285         rsurface.batchnormal3f_bufferoffset = 0;
11286         rsurface.batchlightmapcolor4f = NULL;
11287         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11288         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11289         rsurface.batchtexcoordtexture2f = NULL;
11290         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11291         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11292         rsurface.batchtexcoordlightmap2f = NULL;
11293         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11294         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11295         rsurface.batchvertexmesh = NULL;
11296         rsurface.batchvertexmeshbuffer = NULL;
11297         rsurface.batchvertex3fbuffer = NULL;
11298         rsurface.batchelement3i = NULL;
11299         rsurface.batchelement3i_indexbuffer = NULL;
11300         rsurface.batchelement3i_bufferoffset = 0;
11301         rsurface.batchelement3s = NULL;
11302         rsurface.batchelement3s_indexbuffer = NULL;
11303         rsurface.batchelement3s_bufferoffset = 0;
11304         rsurface.passcolor4f = NULL;
11305         rsurface.passcolor4f_vertexbuffer = NULL;
11306         rsurface.passcolor4f_bufferoffset = 0;
11307 }
11308
11309 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)
11310 {
11311         rsurface.entity = r_refdef.scene.worldentity;
11312         rsurface.skeleton = NULL;
11313         rsurface.ent_skinnum = 0;
11314         rsurface.ent_qwskin = -1;
11315         rsurface.ent_shadertime = shadertime;
11316         rsurface.ent_flags = entflags;
11317         rsurface.modelnumvertices = numvertices;
11318         rsurface.modelnumtriangles = numtriangles;
11319         rsurface.matrix = *matrix;
11320         rsurface.inversematrix = *inversematrix;
11321         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11322         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11323         R_EntityMatrix(&rsurface.matrix);
11324         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11325         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11326         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11327         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11328         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11329         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11330         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11331         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11332         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11333         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11334         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11335         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11336         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);
11337         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11338         rsurface.frameblend[0].lerp = 1;
11339         rsurface.ent_alttextures = false;
11340         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11341         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11342         if (wanttangents)
11343         {
11344                 rsurface.modelvertex3f = (float *)vertex3f;
11345                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11346                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11347                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11348         }
11349         else if (wantnormals)
11350         {
11351                 rsurface.modelvertex3f = (float *)vertex3f;
11352                 rsurface.modelsvector3f = NULL;
11353                 rsurface.modeltvector3f = NULL;
11354                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11355         }
11356         else
11357         {
11358                 rsurface.modelvertex3f = (float *)vertex3f;
11359                 rsurface.modelsvector3f = NULL;
11360                 rsurface.modeltvector3f = NULL;
11361                 rsurface.modelnormal3f = NULL;
11362         }
11363         rsurface.modelvertexmesh = NULL;
11364         rsurface.modelvertexmeshbuffer = NULL;
11365         rsurface.modelvertex3fbuffer = NULL;
11366         rsurface.modelvertex3f_vertexbuffer = 0;
11367         rsurface.modelvertex3f_bufferoffset = 0;
11368         rsurface.modelsvector3f_vertexbuffer = 0;
11369         rsurface.modelsvector3f_bufferoffset = 0;
11370         rsurface.modeltvector3f_vertexbuffer = 0;
11371         rsurface.modeltvector3f_bufferoffset = 0;
11372         rsurface.modelnormal3f_vertexbuffer = 0;
11373         rsurface.modelnormal3f_bufferoffset = 0;
11374         rsurface.modelgeneratedvertex = true;
11375         rsurface.modellightmapcolor4f  = (float *)color4f;
11376         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11377         rsurface.modellightmapcolor4f_bufferoffset = 0;
11378         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
11379         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11380         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11381         rsurface.modeltexcoordlightmap2f  = NULL;
11382         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11383         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11384         rsurface.modelelement3i = (int *)element3i;
11385         rsurface.modelelement3i_indexbuffer = NULL;
11386         rsurface.modelelement3i_bufferoffset = 0;
11387         rsurface.modelelement3s = (unsigned short *)element3s;
11388         rsurface.modelelement3s_indexbuffer = NULL;
11389         rsurface.modelelement3s_bufferoffset = 0;
11390         rsurface.modellightmapoffsets = NULL;
11391         rsurface.modelsurfaces = NULL;
11392         rsurface.batchgeneratedvertex = false;
11393         rsurface.batchfirstvertex = 0;
11394         rsurface.batchnumvertices = 0;
11395         rsurface.batchfirsttriangle = 0;
11396         rsurface.batchnumtriangles = 0;
11397         rsurface.batchvertex3f  = NULL;
11398         rsurface.batchvertex3f_vertexbuffer = NULL;
11399         rsurface.batchvertex3f_bufferoffset = 0;
11400         rsurface.batchsvector3f = NULL;
11401         rsurface.batchsvector3f_vertexbuffer = NULL;
11402         rsurface.batchsvector3f_bufferoffset = 0;
11403         rsurface.batchtvector3f = NULL;
11404         rsurface.batchtvector3f_vertexbuffer = NULL;
11405         rsurface.batchtvector3f_bufferoffset = 0;
11406         rsurface.batchnormal3f  = NULL;
11407         rsurface.batchnormal3f_vertexbuffer = NULL;
11408         rsurface.batchnormal3f_bufferoffset = 0;
11409         rsurface.batchlightmapcolor4f = NULL;
11410         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11411         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11412         rsurface.batchtexcoordtexture2f = NULL;
11413         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11414         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11415         rsurface.batchtexcoordlightmap2f = NULL;
11416         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11417         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11418         rsurface.batchvertexmesh = NULL;
11419         rsurface.batchvertexmeshbuffer = NULL;
11420         rsurface.batchvertex3fbuffer = NULL;
11421         rsurface.batchelement3i = NULL;
11422         rsurface.batchelement3i_indexbuffer = NULL;
11423         rsurface.batchelement3i_bufferoffset = 0;
11424         rsurface.batchelement3s = NULL;
11425         rsurface.batchelement3s_indexbuffer = NULL;
11426         rsurface.batchelement3s_bufferoffset = 0;
11427         rsurface.passcolor4f = NULL;
11428         rsurface.passcolor4f_vertexbuffer = NULL;
11429         rsurface.passcolor4f_bufferoffset = 0;
11430
11431         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11432         {
11433                 if ((wantnormals || wanttangents) && !normal3f)
11434                 {
11435                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11436                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11437                 }
11438                 if (wanttangents && !svector3f)
11439                 {
11440                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11441                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11442                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11443                 }
11444         }
11445 }
11446
11447 float RSurf_FogPoint(const float *v)
11448 {
11449         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11450         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11451         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11452         float FogHeightFade = r_refdef.fogheightfade;
11453         float fogfrac;
11454         unsigned int fogmasktableindex;
11455         if (r_refdef.fogplaneviewabove)
11456                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11457         else
11458                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11459         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11460         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11461 }
11462
11463 float RSurf_FogVertex(const float *v)
11464 {
11465         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11466         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11467         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11468         float FogHeightFade = rsurface.fogheightfade;
11469         float fogfrac;
11470         unsigned int fogmasktableindex;
11471         if (r_refdef.fogplaneviewabove)
11472                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11473         else
11474                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11475         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11476         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11477 }
11478
11479 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11480 {
11481         int i;
11482         for (i = 0;i < numelements;i++)
11483                 outelement3i[i] = inelement3i[i] + adjust;
11484 }
11485
11486 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11487 extern cvar_t gl_vbo;
11488 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11489 {
11490         int deformindex;
11491         int firsttriangle;
11492         int numtriangles;
11493         int firstvertex;
11494         int endvertex;
11495         int numvertices;
11496         int surfacefirsttriangle;
11497         int surfacenumtriangles;
11498         int surfacefirstvertex;
11499         int surfaceendvertex;
11500         int surfacenumvertices;
11501         int batchnumvertices;
11502         int batchnumtriangles;
11503         int needsupdate;
11504         int i, j;
11505         qboolean gaps;
11506         qboolean dynamicvertex;
11507         float amplitude;
11508         float animpos;
11509         float scale;
11510         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11511         float waveparms[4];
11512         q3shaderinfo_deform_t *deform;
11513         const msurface_t *surface, *firstsurface;
11514         r_vertexmesh_t *vertexmesh;
11515         if (!texturenumsurfaces)
11516                 return;
11517         // find vertex range of this surface batch
11518         gaps = false;
11519         firstsurface = texturesurfacelist[0];
11520         firsttriangle = firstsurface->num_firsttriangle;
11521         batchnumvertices = 0;
11522         batchnumtriangles = 0;
11523         firstvertex = endvertex = firstsurface->num_firstvertex;
11524         for (i = 0;i < texturenumsurfaces;i++)
11525         {
11526                 surface = texturesurfacelist[i];
11527                 if (surface != firstsurface + i)
11528                         gaps = true;
11529                 surfacefirstvertex = surface->num_firstvertex;
11530                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11531                 surfacenumvertices = surface->num_vertices;
11532                 surfacenumtriangles = surface->num_triangles;
11533                 if (firstvertex > surfacefirstvertex)
11534                         firstvertex = surfacefirstvertex;
11535                 if (endvertex < surfaceendvertex)
11536                         endvertex = surfaceendvertex;
11537                 batchnumvertices += surfacenumvertices;
11538                 batchnumtriangles += surfacenumtriangles;
11539         }
11540
11541         // we now know the vertex range used, and if there are any gaps in it
11542         rsurface.batchfirstvertex = firstvertex;
11543         rsurface.batchnumvertices = endvertex - firstvertex;
11544         rsurface.batchfirsttriangle = firsttriangle;
11545         rsurface.batchnumtriangles = batchnumtriangles;
11546
11547         // this variable holds flags for which properties have been updated that
11548         // may require regenerating vertexmesh array...
11549         needsupdate = 0;
11550
11551         // check if any dynamic vertex processing must occur
11552         dynamicvertex = false;
11553
11554         // if there is a chance of animated vertex colors, it's a dynamic batch
11555         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11556         {
11557                 dynamicvertex = true;
11558                 batchneed |= BATCHNEED_NOGAPS;
11559                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
11560         }
11561
11562         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11563         {
11564                 switch (deform->deform)
11565                 {
11566                 default:
11567                 case Q3DEFORM_PROJECTIONSHADOW:
11568                 case Q3DEFORM_TEXT0:
11569                 case Q3DEFORM_TEXT1:
11570                 case Q3DEFORM_TEXT2:
11571                 case Q3DEFORM_TEXT3:
11572                 case Q3DEFORM_TEXT4:
11573                 case Q3DEFORM_TEXT5:
11574                 case Q3DEFORM_TEXT6:
11575                 case Q3DEFORM_TEXT7:
11576                 case Q3DEFORM_NONE:
11577                         break;
11578                 case Q3DEFORM_AUTOSPRITE:
11579                         dynamicvertex = true;
11580                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11581                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11582                         break;
11583                 case Q3DEFORM_AUTOSPRITE2:
11584                         dynamicvertex = true;
11585                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11586                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11587                         break;
11588                 case Q3DEFORM_NORMAL:
11589                         dynamicvertex = true;
11590                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11591                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11592                         break;
11593                 case Q3DEFORM_WAVE:
11594                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11595                                 break; // if wavefunc is a nop, ignore this transform
11596                         dynamicvertex = true;
11597                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11598                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11599                         break;
11600                 case Q3DEFORM_BULGE:
11601                         dynamicvertex = true;
11602                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11603                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11604                         break;
11605                 case Q3DEFORM_MOVE:
11606                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11607                                 break; // if wavefunc is a nop, ignore this transform
11608                         dynamicvertex = true;
11609                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11610                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11611                         break;
11612                 }
11613         }
11614         switch(rsurface.texture->tcgen.tcgen)
11615         {
11616         default:
11617         case Q3TCGEN_TEXTURE:
11618                 break;
11619         case Q3TCGEN_LIGHTMAP:
11620                 dynamicvertex = true;
11621                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11622                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11623                 break;
11624         case Q3TCGEN_VECTOR:
11625                 dynamicvertex = true;
11626                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11627                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11628                 break;
11629         case Q3TCGEN_ENVIRONMENT:
11630                 dynamicvertex = true;
11631                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11632                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11633                 break;
11634         }
11635         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11636         {
11637                 dynamicvertex = true;
11638                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11639                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11640         }
11641
11642         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11643         {
11644                 dynamicvertex = true;
11645                 batchneed |= BATCHNEED_NOGAPS;
11646                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11647         }
11648
11649         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11650         {
11651                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11652                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11653                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11654                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11655                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11656                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11657                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11658         }
11659
11660         // when the model data has no vertex buffer (dynamic mesh), we need to
11661         // eliminate gaps
11662         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11663                 batchneed |= BATCHNEED_NOGAPS;
11664
11665         // if needsupdate, we have to do a dynamic vertex batch for sure
11666         if (needsupdate & batchneed)
11667                 dynamicvertex = true;
11668
11669         // see if we need to build vertexmesh from arrays
11670         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11671                 dynamicvertex = true;
11672
11673         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11674         // also some drivers strongly dislike firstvertex
11675         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11676                 dynamicvertex = true;
11677
11678         rsurface.batchvertex3f = rsurface.modelvertex3f;
11679         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11680         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11681         rsurface.batchsvector3f = rsurface.modelsvector3f;
11682         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11683         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11684         rsurface.batchtvector3f = rsurface.modeltvector3f;
11685         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11686         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11687         rsurface.batchnormal3f = rsurface.modelnormal3f;
11688         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11689         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11690         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11691         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11692         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11693         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11694         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11695         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11696         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11697         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11698         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11699         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11700         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11701         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11702         rsurface.batchelement3i = rsurface.modelelement3i;
11703         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11704         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11705         rsurface.batchelement3s = rsurface.modelelement3s;
11706         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11707         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11708
11709         // if any dynamic vertex processing has to occur in software, we copy the
11710         // entire surface list together before processing to rebase the vertices
11711         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11712         //
11713         // if any gaps exist and we do not have a static vertex buffer, we have to
11714         // copy the surface list together to avoid wasting upload bandwidth on the
11715         // vertices in the gaps.
11716         //
11717         // if gaps exist and we have a static vertex buffer, we still have to
11718         // combine the index buffer ranges into one dynamic index buffer.
11719         //
11720         // in all cases we end up with data that can be drawn in one call.
11721
11722         if (!dynamicvertex)
11723         {
11724                 // static vertex data, just set pointers...
11725                 rsurface.batchgeneratedvertex = false;
11726                 // if there are gaps, we want to build a combined index buffer,
11727                 // otherwise use the original static buffer with an appropriate offset
11728                 if (gaps)
11729                 {
11730                         // build a new triangle elements array for this batch
11731                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11732                         rsurface.batchfirsttriangle = 0;
11733                         numtriangles = 0;
11734                         for (i = 0;i < texturenumsurfaces;i++)
11735                         {
11736                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11737                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11738                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11739                                 numtriangles += surfacenumtriangles;
11740                         }
11741                         rsurface.batchelement3i_indexbuffer = NULL;
11742                         rsurface.batchelement3i_bufferoffset = 0;
11743                         rsurface.batchelement3s = NULL;
11744                         rsurface.batchelement3s_indexbuffer = NULL;
11745                         rsurface.batchelement3s_bufferoffset = 0;
11746                         if (endvertex <= 65536)
11747                         {
11748                                 // make a 16bit (unsigned short) index array if possible
11749                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11750                                 for (i = 0;i < numtriangles*3;i++)
11751                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11752                         }
11753                 }
11754                 return;
11755         }
11756
11757         // something needs software processing, do it for real...
11758         // we only directly handle separate array data in this case and then
11759         // generate interleaved data if needed...
11760         rsurface.batchgeneratedvertex = true;
11761
11762         // now copy the vertex data into a combined array and make an index array
11763         // (this is what Quake3 does all the time)
11764         //if (gaps || rsurface.batchfirstvertex)
11765         {
11766                 rsurface.batchvertex3fbuffer = NULL;
11767                 rsurface.batchvertexmesh = NULL;
11768                 rsurface.batchvertexmeshbuffer = NULL;
11769                 rsurface.batchvertex3f = NULL;
11770                 rsurface.batchvertex3f_vertexbuffer = NULL;
11771                 rsurface.batchvertex3f_bufferoffset = 0;
11772                 rsurface.batchsvector3f = NULL;
11773                 rsurface.batchsvector3f_vertexbuffer = NULL;
11774                 rsurface.batchsvector3f_bufferoffset = 0;
11775                 rsurface.batchtvector3f = NULL;
11776                 rsurface.batchtvector3f_vertexbuffer = NULL;
11777                 rsurface.batchtvector3f_bufferoffset = 0;
11778                 rsurface.batchnormal3f = NULL;
11779                 rsurface.batchnormal3f_vertexbuffer = NULL;
11780                 rsurface.batchnormal3f_bufferoffset = 0;
11781                 rsurface.batchlightmapcolor4f = NULL;
11782                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11783                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11784                 rsurface.batchtexcoordtexture2f = NULL;
11785                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11786                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11787                 rsurface.batchtexcoordlightmap2f = NULL;
11788                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11789                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11790                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11791                 rsurface.batchelement3i_indexbuffer = NULL;
11792                 rsurface.batchelement3i_bufferoffset = 0;
11793                 rsurface.batchelement3s = NULL;
11794                 rsurface.batchelement3s_indexbuffer = NULL;
11795                 rsurface.batchelement3s_bufferoffset = 0;
11796                 // we'll only be setting up certain arrays as needed
11797                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11798                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11799                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11800                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11801                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11802                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11803                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11804                 {
11805                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11806                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11807                 }
11808                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11809                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11810                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11811                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11812                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11813                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11814                 numvertices = 0;
11815                 numtriangles = 0;
11816                 for (i = 0;i < texturenumsurfaces;i++)
11817                 {
11818                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11819                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11820                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11821                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11822                         // copy only the data requested
11823                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11824                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11825                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11826                         {
11827                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11828                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11829                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11830                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11831                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11832                                 {
11833                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11834                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11835                                 }
11836                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11837                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11838                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11839                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11840                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11841                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11842                         }
11843                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11844                         numvertices += surfacenumvertices;
11845                         numtriangles += surfacenumtriangles;
11846                 }
11847
11848                 // generate a 16bit index array as well if possible
11849                 // (in general, dynamic batches fit)
11850                 if (numvertices <= 65536)
11851                 {
11852                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11853                         for (i = 0;i < numtriangles*3;i++)
11854                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11855                 }
11856
11857                 // since we've copied everything, the batch now starts at 0
11858                 rsurface.batchfirstvertex = 0;
11859                 rsurface.batchnumvertices = batchnumvertices;
11860                 rsurface.batchfirsttriangle = 0;
11861                 rsurface.batchnumtriangles = batchnumtriangles;
11862         }
11863
11864         // q1bsp surfaces rendered in vertex color mode have to have colors
11865         // calculated based on lightstyles
11866         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11867         {
11868                 // generate color arrays for the surfaces in this list
11869                 int c[4];
11870                 int scale;
11871                 int size3;
11872                 const int *offsets;
11873                 const unsigned char *lm;
11874                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11875                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11876                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11877                 numvertices = 0;
11878                 for (i = 0;i < texturenumsurfaces;i++)
11879                 {
11880                         surface = texturesurfacelist[i];
11881                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11882                         surfacenumvertices = surface->num_vertices;
11883                         if (surface->lightmapinfo->samples)
11884                         {
11885                                 for (j = 0;j < surfacenumvertices;j++)
11886                                 {
11887                                         lm = surface->lightmapinfo->samples + offsets[j];
11888                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11889                                         VectorScale(lm, scale, c);
11890                                         if (surface->lightmapinfo->styles[1] != 255)
11891                                         {
11892                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11893                                                 lm += size3;
11894                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11895                                                 VectorMA(c, scale, lm, c);
11896                                                 if (surface->lightmapinfo->styles[2] != 255)
11897                                                 {
11898                                                         lm += size3;
11899                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11900                                                         VectorMA(c, scale, lm, c);
11901                                                         if (surface->lightmapinfo->styles[3] != 255)
11902                                                         {
11903                                                                 lm += size3;
11904                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11905                                                                 VectorMA(c, scale, lm, c);
11906                                                         }
11907                                                 }
11908                                         }
11909                                         c[0] >>= 7;
11910                                         c[1] >>= 7;
11911                                         c[2] >>= 7;
11912                                         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);
11913                                         numvertices++;
11914                                 }
11915                         }
11916                         else
11917                         {
11918                                 for (j = 0;j < surfacenumvertices;j++)
11919                                 {
11920                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11921                                         numvertices++;
11922                                 }
11923                         }
11924                 }
11925         }
11926
11927         // if vertices are deformed (sprite flares and things in maps, possibly
11928         // water waves, bulges and other deformations), modify the copied vertices
11929         // in place
11930         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11931         {
11932                 switch (deform->deform)
11933                 {
11934                 default:
11935                 case Q3DEFORM_PROJECTIONSHADOW:
11936                 case Q3DEFORM_TEXT0:
11937                 case Q3DEFORM_TEXT1:
11938                 case Q3DEFORM_TEXT2:
11939                 case Q3DEFORM_TEXT3:
11940                 case Q3DEFORM_TEXT4:
11941                 case Q3DEFORM_TEXT5:
11942                 case Q3DEFORM_TEXT6:
11943                 case Q3DEFORM_TEXT7:
11944                 case Q3DEFORM_NONE:
11945                         break;
11946                 case Q3DEFORM_AUTOSPRITE:
11947                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11948                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11949                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11950                         VectorNormalize(newforward);
11951                         VectorNormalize(newright);
11952                         VectorNormalize(newup);
11953 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11954 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11955 //                      rsurface.batchvertex3f_bufferoffset = 0;
11956 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11957 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
11958 //                      rsurface.batchsvector3f_bufferoffset = 0;
11959 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11960 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
11961 //                      rsurface.batchtvector3f_bufferoffset = 0;
11962 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11963 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11964 //                      rsurface.batchnormal3f_bufferoffset = 0;
11965                         // a single autosprite surface can contain multiple sprites...
11966                         for (j = 0;j < batchnumvertices - 3;j += 4)
11967                         {
11968                                 VectorClear(center);
11969                                 for (i = 0;i < 4;i++)
11970                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11971                                 VectorScale(center, 0.25f, center);
11972                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11973                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11974                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11975                                 for (i = 0;i < 4;i++)
11976                                 {
11977                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11978                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11979                                 }
11980                         }
11981                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11982                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11983                         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);
11984                         break;
11985                 case Q3DEFORM_AUTOSPRITE2:
11986                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11987                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11988                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11989                         VectorNormalize(newforward);
11990                         VectorNormalize(newright);
11991                         VectorNormalize(newup);
11992 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11993 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11994 //                      rsurface.batchvertex3f_bufferoffset = 0;
11995                         {
11996                                 const float *v1, *v2;
11997                                 vec3_t start, end;
11998                                 float f, l;
11999                                 struct
12000                                 {
12001                                         float length2;
12002                                         const float *v1;
12003                                         const float *v2;
12004                                 }
12005                                 shortest[2];
12006                                 memset(shortest, 0, sizeof(shortest));
12007                                 // a single autosprite surface can contain multiple sprites...
12008                                 for (j = 0;j < batchnumvertices - 3;j += 4)
12009                                 {
12010                                         VectorClear(center);
12011                                         for (i = 0;i < 4;i++)
12012                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
12013                                         VectorScale(center, 0.25f, center);
12014                                         // find the two shortest edges, then use them to define the
12015                                         // axis vectors for rotating around the central axis
12016                                         for (i = 0;i < 6;i++)
12017                                         {
12018                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
12019                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
12020                                                 l = VectorDistance2(v1, v2);
12021                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
12022                                                 if (v1[2] != v2[2])
12023                                                         l += (1.0f / 1024.0f);
12024                                                 if (shortest[0].length2 > l || i == 0)
12025                                                 {
12026                                                         shortest[1] = shortest[0];
12027                                                         shortest[0].length2 = l;
12028                                                         shortest[0].v1 = v1;
12029                                                         shortest[0].v2 = v2;
12030                                                 }
12031                                                 else if (shortest[1].length2 > l || i == 1)
12032                                                 {
12033                                                         shortest[1].length2 = l;
12034                                                         shortest[1].v1 = v1;
12035                                                         shortest[1].v2 = v2;
12036                                                 }
12037                                         }
12038                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
12039                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
12040                                         // this calculates the right vector from the shortest edge
12041                                         // and the up vector from the edge midpoints
12042                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
12043                                         VectorNormalize(right);
12044                                         VectorSubtract(end, start, up);
12045                                         VectorNormalize(up);
12046                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
12047                                         VectorSubtract(rsurface.localvieworigin, center, forward);
12048                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
12049                                         VectorNegate(forward, forward);
12050                                         VectorReflect(forward, 0, up, forward);
12051                                         VectorNormalize(forward);
12052                                         CrossProduct(up, forward, newright);
12053                                         VectorNormalize(newright);
12054                                         // rotate the quad around the up axis vector, this is made
12055                                         // especially easy by the fact we know the quad is flat,
12056                                         // so we only have to subtract the center position and
12057                                         // measure distance along the right vector, and then
12058                                         // multiply that by the newright vector and add back the
12059                                         // center position
12060                                         // we also need to subtract the old position to undo the
12061                                         // displacement from the center, which we do with a
12062                                         // DotProduct, the subtraction/addition of center is also
12063                                         // optimized into DotProducts here
12064                                         l = DotProduct(right, center);
12065                                         for (i = 0;i < 4;i++)
12066                                         {
12067                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
12068                                                 f = DotProduct(right, v1) - l;
12069                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
12070                                         }
12071                                 }
12072                         }
12073                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
12074                         {
12075 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12076 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
12077 //                              rsurface.batchnormal3f_bufferoffset = 0;
12078                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12079                         }
12080                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12081                         {
12082 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12083 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12084 //                              rsurface.batchsvector3f_bufferoffset = 0;
12085 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12086 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12087 //                              rsurface.batchtvector3f_bufferoffset = 0;
12088                                 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);
12089                         }
12090                         break;
12091                 case Q3DEFORM_NORMAL:
12092                         // deform the normals to make reflections wavey
12093                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12094                         rsurface.batchnormal3f_vertexbuffer = NULL;
12095                         rsurface.batchnormal3f_bufferoffset = 0;
12096                         for (j = 0;j < batchnumvertices;j++)
12097                         {
12098                                 float vertex[3];
12099                                 float *normal = rsurface.batchnormal3f + 3*j;
12100                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
12101                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
12102                                 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]);
12103                                 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]);
12104                                 VectorNormalize(normal);
12105                         }
12106                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12107                         {
12108 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12109 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12110 //                              rsurface.batchsvector3f_bufferoffset = 0;
12111 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12112 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12113 //                              rsurface.batchtvector3f_bufferoffset = 0;
12114                                 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);
12115                         }
12116                         break;
12117                 case Q3DEFORM_WAVE:
12118                         // deform vertex array to make wavey water and flags and such
12119                         waveparms[0] = deform->waveparms[0];
12120                         waveparms[1] = deform->waveparms[1];
12121                         waveparms[2] = deform->waveparms[2];
12122                         waveparms[3] = deform->waveparms[3];
12123                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12124                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12125                         // this is how a divisor of vertex influence on deformation
12126                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12127                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12128 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12129 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12130 //                      rsurface.batchvertex3f_bufferoffset = 0;
12131 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12132 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12133 //                      rsurface.batchnormal3f_bufferoffset = 0;
12134                         for (j = 0;j < batchnumvertices;j++)
12135                         {
12136                                 // if the wavefunc depends on time, evaluate it per-vertex
12137                                 if (waveparms[3])
12138                                 {
12139                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12140                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12141                                 }
12142                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12143                         }
12144                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12145                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12146                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12147                         {
12148 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12149 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12150 //                              rsurface.batchsvector3f_bufferoffset = 0;
12151 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12152 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12153 //                              rsurface.batchtvector3f_bufferoffset = 0;
12154                                 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);
12155                         }
12156                         break;
12157                 case Q3DEFORM_BULGE:
12158                         // deform vertex array to make the surface have moving bulges
12159 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12160 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12161 //                      rsurface.batchvertex3f_bufferoffset = 0;
12162 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12163 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12164 //                      rsurface.batchnormal3f_bufferoffset = 0;
12165                         for (j = 0;j < batchnumvertices;j++)
12166                         {
12167                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12168                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12169                         }
12170                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12171                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12172                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12173                         {
12174 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12175 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12176 //                              rsurface.batchsvector3f_bufferoffset = 0;
12177 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12178 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12179 //                              rsurface.batchtvector3f_bufferoffset = 0;
12180                                 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);
12181                         }
12182                         break;
12183                 case Q3DEFORM_MOVE:
12184                         // deform vertex array
12185                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12186                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12187                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12188                         VectorScale(deform->parms, scale, waveparms);
12189 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12190 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12191 //                      rsurface.batchvertex3f_bufferoffset = 0;
12192                         for (j = 0;j < batchnumvertices;j++)
12193                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
12194                         break;
12195                 }
12196         }
12197
12198         // generate texcoords based on the chosen texcoord source
12199         switch(rsurface.texture->tcgen.tcgen)
12200         {
12201         default:
12202         case Q3TCGEN_TEXTURE:
12203                 break;
12204         case Q3TCGEN_LIGHTMAP:
12205 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12206 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12207 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12208                 if (rsurface.batchtexcoordlightmap2f)
12209                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
12210                 break;
12211         case Q3TCGEN_VECTOR:
12212 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12213 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12214 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12215                 for (j = 0;j < batchnumvertices;j++)
12216                 {
12217                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12218                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12219                 }
12220                 break;
12221         case Q3TCGEN_ENVIRONMENT:
12222                 // make environment reflections using a spheremap
12223                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12224                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12225                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12226                 for (j = 0;j < batchnumvertices;j++)
12227                 {
12228                         // identical to Q3A's method, but executed in worldspace so
12229                         // carried models can be shiny too
12230
12231                         float viewer[3], d, reflected[3], worldreflected[3];
12232
12233                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12234                         // VectorNormalize(viewer);
12235
12236                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12237
12238                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12239                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12240                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12241                         // note: this is proportinal to viewer, so we can normalize later
12242
12243                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12244                         VectorNormalize(worldreflected);
12245
12246                         // note: this sphere map only uses world x and z!
12247                         // so positive and negative y will LOOK THE SAME.
12248                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12249                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12250                 }
12251                 break;
12252         }
12253         // the only tcmod that needs software vertex processing is turbulent, so
12254         // check for it here and apply the changes if needed
12255         // and we only support that as the first one
12256         // (handling a mixture of turbulent and other tcmods would be problematic
12257         //  without punting it entirely to a software path)
12258         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12259         {
12260                 amplitude = rsurface.texture->tcmods[0].parms[1];
12261                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12262 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12263 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12264 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12265                 for (j = 0;j < batchnumvertices;j++)
12266                 {
12267                         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);
12268                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12269                 }
12270         }
12271
12272         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12273         {
12274                 // convert the modified arrays to vertex structs
12275 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
12276 //              rsurface.batchvertexmeshbuffer = NULL;
12277                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12278                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12279                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12280                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12281                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12282                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12283                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12284                 {
12285                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12286                         {
12287                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12288                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12289                         }
12290                 }
12291                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12292                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12293                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12294                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12295                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12296                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12297                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12298                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12299                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12300         }
12301 }
12302
12303 void RSurf_DrawBatch(void)
12304 {
12305         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12306         // through the pipeline, killing it earlier in the pipeline would have
12307         // per-surface overhead rather than per-batch overhead, so it's best to
12308         // reject it here, before it hits glDraw.
12309         if (rsurface.batchnumtriangles == 0)
12310                 return;
12311 #if 0
12312         // batch debugging code
12313         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12314         {
12315                 int i;
12316                 int j;
12317                 int c;
12318                 const int *e;
12319                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12320                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12321                 {
12322                         c = e[i];
12323                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12324                         {
12325                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12326                                 {
12327                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12328                                                 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);
12329                                         break;
12330                                 }
12331                         }
12332                 }
12333         }
12334 #endif
12335         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);
12336 }
12337
12338 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12339 {
12340         // pick the closest matching water plane
12341         int planeindex, vertexindex, bestplaneindex = -1;
12342         float d, bestd;
12343         vec3_t vert;
12344         const float *v;
12345         r_waterstate_waterplane_t *p;
12346         qboolean prepared = false;
12347         bestd = 0;
12348         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12349         {
12350                 if(p->camera_entity != rsurface.texture->camera_entity)
12351                         continue;
12352                 d = 0;
12353                 if(!prepared)
12354                 {
12355                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12356                         prepared = true;
12357                         if(rsurface.batchnumvertices == 0)
12358                                 break;
12359                 }
12360                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12361                 {
12362                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12363                         d += fabs(PlaneDiff(vert, &p->plane));
12364                 }
12365                 if (bestd > d || bestplaneindex < 0)
12366                 {
12367                         bestd = d;
12368                         bestplaneindex = planeindex;
12369                 }
12370         }
12371         return bestplaneindex;
12372         // NOTE: this MAY return a totally unrelated water plane; we can ignore
12373         // this situation though, as it might be better to render single larger
12374         // batches with useless stuff (backface culled for example) than to
12375         // render multiple smaller batches
12376 }
12377
12378 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12379 {
12380         int i;
12381         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12382         rsurface.passcolor4f_vertexbuffer = 0;
12383         rsurface.passcolor4f_bufferoffset = 0;
12384         for (i = 0;i < rsurface.batchnumvertices;i++)
12385                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12386 }
12387
12388 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12389 {
12390         int i;
12391         float f;
12392         const float *v;
12393         const float *c;
12394         float *c2;
12395         if (rsurface.passcolor4f)
12396         {
12397                 // generate color arrays
12398                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12399                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12400                 rsurface.passcolor4f_vertexbuffer = 0;
12401                 rsurface.passcolor4f_bufferoffset = 0;
12402                 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)
12403                 {
12404                         f = RSurf_FogVertex(v);
12405                         c2[0] = c[0] * f;
12406                         c2[1] = c[1] * f;
12407                         c2[2] = c[2] * f;
12408                         c2[3] = c[3];
12409                 }
12410         }
12411         else
12412         {
12413                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12414                 rsurface.passcolor4f_vertexbuffer = 0;
12415                 rsurface.passcolor4f_bufferoffset = 0;
12416                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12417                 {
12418                         f = RSurf_FogVertex(v);
12419                         c2[0] = f;
12420                         c2[1] = f;
12421                         c2[2] = f;
12422                         c2[3] = 1;
12423                 }
12424         }
12425 }
12426
12427 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12428 {
12429         int i;
12430         float f;
12431         const float *v;
12432         const float *c;
12433         float *c2;
12434         if (!rsurface.passcolor4f)
12435                 return;
12436         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12437         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12438         rsurface.passcolor4f_vertexbuffer = 0;
12439         rsurface.passcolor4f_bufferoffset = 0;
12440         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)
12441         {
12442                 f = RSurf_FogVertex(v);
12443                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12444                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12445                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12446                 c2[3] = c[3];
12447         }
12448 }
12449
12450 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12451 {
12452         int i;
12453         const float *c;
12454         float *c2;
12455         if (!rsurface.passcolor4f)
12456                 return;
12457         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12458         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12459         rsurface.passcolor4f_vertexbuffer = 0;
12460         rsurface.passcolor4f_bufferoffset = 0;
12461         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12462         {
12463                 c2[0] = c[0] * r;
12464                 c2[1] = c[1] * g;
12465                 c2[2] = c[2] * b;
12466                 c2[3] = c[3] * a;
12467         }
12468 }
12469
12470 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12471 {
12472         int i;
12473         const float *c;
12474         float *c2;
12475         if (!rsurface.passcolor4f)
12476                 return;
12477         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
12478         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12479         rsurface.passcolor4f_vertexbuffer = 0;
12480         rsurface.passcolor4f_bufferoffset = 0;
12481         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12482         {
12483                 c2[0] = c[0] + r_refdef.scene.ambient;
12484                 c2[1] = c[1] + r_refdef.scene.ambient;
12485                 c2[2] = c[2] + r_refdef.scene.ambient;
12486                 c2[3] = c[3];
12487         }
12488 }
12489
12490 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12491 {
12492         // TODO: optimize
12493         rsurface.passcolor4f = NULL;
12494         rsurface.passcolor4f_vertexbuffer = 0;
12495         rsurface.passcolor4f_bufferoffset = 0;
12496         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12497         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12498         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12499         GL_Color(r, g, b, a);
12500         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12501         RSurf_DrawBatch();
12502 }
12503
12504 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12505 {
12506         // TODO: optimize applyfog && applycolor case
12507         // just apply fog if necessary, and tint the fog color array if necessary
12508         rsurface.passcolor4f = NULL;
12509         rsurface.passcolor4f_vertexbuffer = 0;
12510         rsurface.passcolor4f_bufferoffset = 0;
12511         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12512         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12513         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12514         GL_Color(r, g, b, a);
12515         RSurf_DrawBatch();
12516 }
12517
12518 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12519 {
12520         // TODO: optimize
12521         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12522         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12523         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12524         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12525         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12526         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12527         GL_Color(r, g, b, a);
12528         RSurf_DrawBatch();
12529 }
12530
12531 static void RSurf_DrawBatch_GL11_ClampColor(void)
12532 {
12533         int i;
12534         const float *c1;
12535         float *c2;
12536         if (!rsurface.passcolor4f)
12537                 return;
12538         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12539         {
12540                 c2[0] = bound(0.0f, c1[0], 1.0f);
12541                 c2[1] = bound(0.0f, c1[1], 1.0f);
12542                 c2[2] = bound(0.0f, c1[2], 1.0f);
12543                 c2[3] = bound(0.0f, c1[3], 1.0f);
12544         }
12545 }
12546
12547 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12548 {
12549         int i;
12550         float f;
12551         const float *v;
12552         const float *n;
12553         float *c;
12554         //vec3_t eyedir;
12555
12556         // fake shading
12557         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12558         rsurface.passcolor4f_vertexbuffer = 0;
12559         rsurface.passcolor4f_bufferoffset = 0;
12560         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)
12561         {
12562                 f = -DotProduct(r_refdef.view.forward, n);
12563                 f = max(0, f);
12564                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12565                 f *= r_refdef.lightmapintensity;
12566                 Vector4Set(c, f, f, f, 1);
12567         }
12568 }
12569
12570 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12571 {
12572         RSurf_DrawBatch_GL11_ApplyFakeLight();
12573         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12574         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12575         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12576         GL_Color(r, g, b, a);
12577         RSurf_DrawBatch();
12578 }
12579
12580 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12581 {
12582         int i;
12583         float f;
12584         float alpha;
12585         const float *v;
12586         const float *n;
12587         float *c;
12588         vec3_t ambientcolor;
12589         vec3_t diffusecolor;
12590         vec3_t lightdir;
12591         // TODO: optimize
12592         // model lighting
12593         VectorCopy(rsurface.modellight_lightdir, lightdir);
12594         f = 0.5f * r_refdef.lightmapintensity;
12595         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12596         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12597         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12598         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12599         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12600         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12601         alpha = *a;
12602         if (VectorLength2(diffusecolor) > 0)
12603         {
12604                 // q3-style directional shading
12605                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12606                 rsurface.passcolor4f_vertexbuffer = 0;
12607                 rsurface.passcolor4f_bufferoffset = 0;
12608                 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)
12609                 {
12610                         if ((f = DotProduct(n, lightdir)) > 0)
12611                                 VectorMA(ambientcolor, f, diffusecolor, c);
12612                         else
12613                                 VectorCopy(ambientcolor, c);
12614                         c[3] = alpha;
12615                 }
12616                 *r = 1;
12617                 *g = 1;
12618                 *b = 1;
12619                 *a = 1;
12620                 *applycolor = false;
12621         }
12622         else
12623         {
12624                 *r = ambientcolor[0];
12625                 *g = ambientcolor[1];
12626                 *b = ambientcolor[2];
12627                 rsurface.passcolor4f = NULL;
12628                 rsurface.passcolor4f_vertexbuffer = 0;
12629                 rsurface.passcolor4f_bufferoffset = 0;
12630         }
12631 }
12632
12633 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12634 {
12635         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12636         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12637         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12638         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12639         GL_Color(r, g, b, a);
12640         RSurf_DrawBatch();
12641 }
12642
12643 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12644 {
12645         int i;
12646         float f;
12647         const float *v;
12648         float *c;
12649         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12650         {
12651                 f = 1 - RSurf_FogVertex(v);
12652                 c[0] = r;
12653                 c[1] = g;
12654                 c[2] = b;
12655                 c[3] = f * a;
12656         }
12657 }
12658
12659 void RSurf_SetupDepthAndCulling(void)
12660 {
12661         // submodels are biased to avoid z-fighting with world surfaces that they
12662         // may be exactly overlapping (avoids z-fighting artifacts on certain
12663         // doors and things in Quake maps)
12664         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12665         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12666         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12667         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12668 }
12669
12670 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12671 {
12672         // transparent sky would be ridiculous
12673         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12674                 return;
12675         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12676         skyrenderlater = true;
12677         RSurf_SetupDepthAndCulling();
12678         GL_DepthMask(true);
12679         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12680         // skymasking on them, and Quake3 never did sky masking (unlike
12681         // software Quake and software Quake2), so disable the sky masking
12682         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12683         // and skymasking also looks very bad when noclipping outside the
12684         // level, so don't use it then either.
12685         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12686         {
12687                 R_Mesh_ResetTextureState();
12688                 if (skyrendermasked)
12689                 {
12690                         R_SetupShader_DepthOrShadow();
12691                         // depth-only (masking)
12692                         GL_ColorMask(0,0,0,0);
12693                         // just to make sure that braindead drivers don't draw
12694                         // anything despite that colormask...
12695                         GL_BlendFunc(GL_ZERO, GL_ONE);
12696                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12697                         if (rsurface.batchvertex3fbuffer)
12698                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12699                         else
12700                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12701                 }
12702                 else
12703                 {
12704                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12705                         // fog sky
12706                         GL_BlendFunc(GL_ONE, GL_ZERO);
12707                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12708                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12709                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12710                 }
12711                 RSurf_DrawBatch();
12712                 if (skyrendermasked)
12713                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12714         }
12715         R_Mesh_ResetTextureState();
12716         GL_Color(1, 1, 1, 1);
12717 }
12718
12719 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12720 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12721 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12722 {
12723         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12724                 return;
12725         if (prepass)
12726         {
12727                 // render screenspace normalmap to texture
12728                 GL_DepthMask(true);
12729                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12730                 RSurf_DrawBatch();
12731                 return;
12732         }
12733
12734         // bind lightmap texture
12735
12736         // water/refraction/reflection/camera surfaces have to be handled specially
12737         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12738         {
12739                 int start, end, startplaneindex;
12740                 for (start = 0;start < texturenumsurfaces;start = end)
12741                 {
12742                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12743                         if(startplaneindex < 0)
12744                         {
12745                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12746                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12747                                 end = start + 1;
12748                                 continue;
12749                         }
12750                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12751                                 ;
12752                         // now that we have a batch using the same planeindex, render it
12753                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12754                         {
12755                                 // render water or distortion background
12756                                 GL_DepthMask(true);
12757                                 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));
12758                                 RSurf_DrawBatch();
12759                                 // blend surface on top
12760                                 GL_DepthMask(false);
12761                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12762                                 RSurf_DrawBatch();
12763                         }
12764                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12765                         {
12766                                 // render surface with reflection texture as input
12767                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12768                                 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));
12769                                 RSurf_DrawBatch();
12770                         }
12771                 }
12772                 return;
12773         }
12774
12775         // render surface batch normally
12776         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12777         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12778         RSurf_DrawBatch();
12779 }
12780
12781 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12782 {
12783         // OpenGL 1.3 path - anything not completely ancient
12784         qboolean applycolor;
12785         qboolean applyfog;
12786         int layerindex;
12787         const texturelayer_t *layer;
12788         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);
12789         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12790
12791         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12792         {
12793                 vec4_t layercolor;
12794                 int layertexrgbscale;
12795                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12796                 {
12797                         if (layerindex == 0)
12798                                 GL_AlphaTest(true);
12799                         else
12800                         {
12801                                 GL_AlphaTest(false);
12802                                 GL_DepthFunc(GL_EQUAL);
12803                         }
12804                 }
12805                 GL_DepthMask(layer->depthmask && writedepth);
12806                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12807                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12808                 {
12809                         layertexrgbscale = 4;
12810                         VectorScale(layer->color, 0.25f, layercolor);
12811                 }
12812                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12813                 {
12814                         layertexrgbscale = 2;
12815                         VectorScale(layer->color, 0.5f, layercolor);
12816                 }
12817                 else
12818                 {
12819                         layertexrgbscale = 1;
12820                         VectorScale(layer->color, 1.0f, layercolor);
12821                 }
12822                 layercolor[3] = layer->color[3];
12823                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12824                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12825                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12826                 switch (layer->type)
12827                 {
12828                 case TEXTURELAYERTYPE_LITTEXTURE:
12829                         // single-pass lightmapped texture with 2x rgbscale
12830                         R_Mesh_TexBind(0, r_texture_white);
12831                         R_Mesh_TexMatrix(0, NULL);
12832                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12833                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12834                         R_Mesh_TexBind(1, layer->texture);
12835                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12836                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12837                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12838                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12839                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12840                         else if (FAKELIGHT_ENABLED)
12841                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12842                         else if (rsurface.uselightmaptexture)
12843                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12844                         else
12845                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12846                         break;
12847                 case TEXTURELAYERTYPE_TEXTURE:
12848                         // singletexture unlit texture with transparency support
12849                         R_Mesh_TexBind(0, layer->texture);
12850                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12851                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12852                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12853                         R_Mesh_TexBind(1, 0);
12854                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12855                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12856                         break;
12857                 case TEXTURELAYERTYPE_FOG:
12858                         // singletexture fogging
12859                         if (layer->texture)
12860                         {
12861                                 R_Mesh_TexBind(0, layer->texture);
12862                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12863                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12864                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12865                         }
12866                         else
12867                         {
12868                                 R_Mesh_TexBind(0, 0);
12869                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12870                         }
12871                         R_Mesh_TexBind(1, 0);
12872                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12873                         // generate a color array for the fog pass
12874                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12875                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12876                         RSurf_DrawBatch();
12877                         break;
12878                 default:
12879                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12880                 }
12881         }
12882         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12883         {
12884                 GL_DepthFunc(GL_LEQUAL);
12885                 GL_AlphaTest(false);
12886         }
12887 }
12888
12889 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12890 {
12891         // OpenGL 1.1 - crusty old voodoo path
12892         qboolean applyfog;
12893         int layerindex;
12894         const texturelayer_t *layer;
12895         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);
12896         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12897
12898         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12899         {
12900                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12901                 {
12902                         if (layerindex == 0)
12903                                 GL_AlphaTest(true);
12904                         else
12905                         {
12906                                 GL_AlphaTest(false);
12907                                 GL_DepthFunc(GL_EQUAL);
12908                         }
12909                 }
12910                 GL_DepthMask(layer->depthmask && writedepth);
12911                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12912                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12913                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12914                 switch (layer->type)
12915                 {
12916                 case TEXTURELAYERTYPE_LITTEXTURE:
12917                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12918                         {
12919                                 // two-pass lit texture with 2x rgbscale
12920                                 // first the lightmap pass
12921                                 R_Mesh_TexBind(0, r_texture_white);
12922                                 R_Mesh_TexMatrix(0, NULL);
12923                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12924                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12925                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12926                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12927                                 else if (FAKELIGHT_ENABLED)
12928                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12929                                 else if (rsurface.uselightmaptexture)
12930                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12931                                 else
12932                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12933                                 // then apply the texture to it
12934                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12935                                 R_Mesh_TexBind(0, layer->texture);
12936                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12937                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12938                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12939                                 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);
12940                         }
12941                         else
12942                         {
12943                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12944                                 R_Mesh_TexBind(0, layer->texture);
12945                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12946                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12947                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12948                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12949                                         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);
12950                                 else
12951                                         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);
12952                         }
12953                         break;
12954                 case TEXTURELAYERTYPE_TEXTURE:
12955                         // singletexture unlit texture with transparency support
12956                         R_Mesh_TexBind(0, layer->texture);
12957                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12958                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12959                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12960                         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);
12961                         break;
12962                 case TEXTURELAYERTYPE_FOG:
12963                         // singletexture fogging
12964                         if (layer->texture)
12965                         {
12966                                 R_Mesh_TexBind(0, layer->texture);
12967                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12968                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12969                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12970                         }
12971                         else
12972                         {
12973                                 R_Mesh_TexBind(0, 0);
12974                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12975                         }
12976                         // generate a color array for the fog pass
12977                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12978                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12979                         RSurf_DrawBatch();
12980                         break;
12981                 default:
12982                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12983                 }
12984         }
12985         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12986         {
12987                 GL_DepthFunc(GL_LEQUAL);
12988                 GL_AlphaTest(false);
12989         }
12990 }
12991
12992 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12993 {
12994         int vi;
12995         int j;
12996         r_vertexgeneric_t *batchvertex;
12997         float c[4];
12998
12999         GL_AlphaTest(false);
13000 //      R_Mesh_ResetTextureState();
13001         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13002
13003         if(rsurface.texture && rsurface.texture->currentskinframe)
13004         {
13005                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
13006                 c[3] *= rsurface.texture->currentalpha;
13007         }
13008         else
13009         {
13010                 c[0] = 1;
13011                 c[1] = 0;
13012                 c[2] = 1;
13013                 c[3] = 1;
13014         }
13015
13016         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
13017         {
13018                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
13019                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
13020                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
13021         }
13022
13023         // brighten it up (as texture value 127 means "unlit")
13024         c[0] *= 2 * r_refdef.view.colorscale;
13025         c[1] *= 2 * r_refdef.view.colorscale;
13026         c[2] *= 2 * r_refdef.view.colorscale;
13027
13028         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
13029                 c[3] *= r_wateralpha.value;
13030
13031         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
13032         {
13033                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13034                 GL_DepthMask(false);
13035         }
13036         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
13037         {
13038                 GL_BlendFunc(GL_ONE, GL_ONE);
13039                 GL_DepthMask(false);
13040         }
13041         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13042         {
13043                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
13044                 GL_DepthMask(false);
13045         }
13046         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
13047         {
13048                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
13049                 GL_DepthMask(false);
13050         }
13051         else
13052         {
13053                 GL_BlendFunc(GL_ONE, GL_ZERO);
13054                 GL_DepthMask(writedepth);
13055         }
13056
13057         if (r_showsurfaces.integer == 3)
13058         {
13059                 rsurface.passcolor4f = NULL;
13060
13061                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
13062                 {
13063                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13064
13065                         rsurface.passcolor4f = NULL;
13066                         rsurface.passcolor4f_vertexbuffer = 0;
13067                         rsurface.passcolor4f_bufferoffset = 0;
13068                 }
13069                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13070                 {
13071                         qboolean applycolor = true;
13072                         float one = 1.0;
13073
13074                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13075
13076                         r_refdef.lightmapintensity = 1;
13077                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
13078                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13079                 }
13080                 else if (FAKELIGHT_ENABLED)
13081                 {
13082                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13083
13084                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
13085                         RSurf_DrawBatch_GL11_ApplyFakeLight();
13086                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13087                 }
13088                 else
13089                 {
13090                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13091
13092                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13093                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13094                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13095                 }
13096
13097                 if(!rsurface.passcolor4f)
13098                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13099
13100                 RSurf_DrawBatch_GL11_ApplyAmbient();
13101                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13102                 if(r_refdef.fogenabled)
13103                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13104                 RSurf_DrawBatch_GL11_ClampColor();
13105
13106                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13107                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13108                 RSurf_DrawBatch();
13109         }
13110         else if (!r_refdef.view.showdebug)
13111         {
13112                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13113                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13114                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13115                 {
13116                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13117                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13118                 }
13119                 R_Mesh_PrepareVertices_Generic_Unlock();
13120                 RSurf_DrawBatch();
13121         }
13122         else if (r_showsurfaces.integer == 4)
13123         {
13124                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13125                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13126                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13127                 {
13128                         unsigned char c = vi << 3;
13129                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13130                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13131                 }
13132                 R_Mesh_PrepareVertices_Generic_Unlock();
13133                 RSurf_DrawBatch();
13134         }
13135         else if (r_showsurfaces.integer == 2)
13136         {
13137                 const int *e;
13138                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13139                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13140                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13141                 {
13142                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13143                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13144                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13145                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13146                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13147                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13148                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13149                 }
13150                 R_Mesh_PrepareVertices_Generic_Unlock();
13151                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13152         }
13153         else
13154         {
13155                 int texturesurfaceindex;
13156                 int k;
13157                 const msurface_t *surface;
13158                 unsigned char surfacecolor4ub[4];
13159                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13160                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13161                 vi = 0;
13162                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13163                 {
13164                         surface = texturesurfacelist[texturesurfaceindex];
13165                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13166                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13167                         for (j = 0;j < surface->num_vertices;j++)
13168                         {
13169                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13170                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13171                                 vi++;
13172                         }
13173                 }
13174                 R_Mesh_PrepareVertices_Generic_Unlock();
13175                 RSurf_DrawBatch();
13176         }
13177 }
13178
13179 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13180 {
13181         CHECKGLERROR
13182         RSurf_SetupDepthAndCulling();
13183         if (r_showsurfaces.integer)
13184         {
13185                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13186                 return;
13187         }
13188         switch (vid.renderpath)
13189         {
13190         case RENDERPATH_GL20:
13191         case RENDERPATH_CGGL:
13192         case RENDERPATH_D3D9:
13193         case RENDERPATH_D3D10:
13194         case RENDERPATH_D3D11:
13195         case RENDERPATH_SOFT:
13196                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13197                 break;
13198         case RENDERPATH_GL13:
13199                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13200                 break;
13201         case RENDERPATH_GL11:
13202                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13203                 break;
13204         }
13205         CHECKGLERROR
13206 }
13207
13208 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13209 {
13210         CHECKGLERROR
13211         RSurf_SetupDepthAndCulling();
13212         if (r_showsurfaces.integer)
13213         {
13214                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13215                 return;
13216         }
13217         switch (vid.renderpath)
13218         {
13219         case RENDERPATH_GL20:
13220         case RENDERPATH_CGGL:
13221         case RENDERPATH_D3D9:
13222         case RENDERPATH_D3D10:
13223         case RENDERPATH_D3D11:
13224         case RENDERPATH_SOFT:
13225                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13226                 break;
13227         case RENDERPATH_GL13:
13228                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13229                 break;
13230         case RENDERPATH_GL11:
13231                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13232                 break;
13233         }
13234         CHECKGLERROR
13235 }
13236
13237 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13238 {
13239         int i, j;
13240         int texturenumsurfaces, endsurface;
13241         texture_t *texture;
13242         const msurface_t *surface;
13243 #define MAXBATCH_TRANSPARENTSURFACES 256
13244         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13245
13246         // if the model is static it doesn't matter what value we give for
13247         // wantnormals and wanttangents, so this logic uses only rules applicable
13248         // to a model, knowing that they are meaningless otherwise
13249         if (ent == r_refdef.scene.worldentity)
13250                 RSurf_ActiveWorldEntity();
13251         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13252                 RSurf_ActiveModelEntity(ent, false, false, false);
13253         else
13254         {
13255                 switch (vid.renderpath)
13256                 {
13257                 case RENDERPATH_GL20:
13258                 case RENDERPATH_CGGL:
13259                 case RENDERPATH_D3D9:
13260                 case RENDERPATH_D3D10:
13261                 case RENDERPATH_D3D11:
13262                 case RENDERPATH_SOFT:
13263                         RSurf_ActiveModelEntity(ent, true, true, false);
13264                         break;
13265                 case RENDERPATH_GL13:
13266                 case RENDERPATH_GL11:
13267                         RSurf_ActiveModelEntity(ent, true, false, false);
13268                         break;
13269                 }
13270         }
13271
13272         if (r_transparentdepthmasking.integer)
13273         {
13274                 qboolean setup = false;
13275                 for (i = 0;i < numsurfaces;i = j)
13276                 {
13277                         j = i + 1;
13278                         surface = rsurface.modelsurfaces + surfacelist[i];
13279                         texture = surface->texture;
13280                         rsurface.texture = R_GetCurrentTexture(texture);
13281                         rsurface.lightmaptexture = NULL;
13282                         rsurface.deluxemaptexture = NULL;
13283                         rsurface.uselightmaptexture = false;
13284                         // scan ahead until we find a different texture
13285                         endsurface = min(i + 1024, numsurfaces);
13286                         texturenumsurfaces = 0;
13287                         texturesurfacelist[texturenumsurfaces++] = surface;
13288                         for (;j < endsurface;j++)
13289                         {
13290                                 surface = rsurface.modelsurfaces + surfacelist[j];
13291                                 if (texture != surface->texture)
13292                                         break;
13293                                 texturesurfacelist[texturenumsurfaces++] = surface;
13294                         }
13295                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13296                                 continue;
13297                         // render the range of surfaces as depth
13298                         if (!setup)
13299                         {
13300                                 setup = true;
13301                                 GL_ColorMask(0,0,0,0);
13302                                 GL_Color(1,1,1,1);
13303                                 GL_DepthTest(true);
13304                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13305                                 GL_DepthMask(true);
13306                                 GL_AlphaTest(false);
13307 //                              R_Mesh_ResetTextureState();
13308                                 R_SetupShader_DepthOrShadow();
13309                         }
13310                         RSurf_SetupDepthAndCulling();
13311                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13312                         if (rsurface.batchvertex3fbuffer)
13313                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13314                         else
13315                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13316                         RSurf_DrawBatch();
13317                 }
13318                 if (setup)
13319                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13320         }
13321
13322         for (i = 0;i < numsurfaces;i = j)
13323         {
13324                 j = i + 1;
13325                 surface = rsurface.modelsurfaces + surfacelist[i];
13326                 texture = surface->texture;
13327                 rsurface.texture = R_GetCurrentTexture(texture);
13328                 // scan ahead until we find a different texture
13329                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13330                 texturenumsurfaces = 0;
13331                 texturesurfacelist[texturenumsurfaces++] = surface;
13332                 if(FAKELIGHT_ENABLED)
13333                 {
13334                         rsurface.lightmaptexture = NULL;
13335                         rsurface.deluxemaptexture = NULL;
13336                         rsurface.uselightmaptexture = false;
13337                         for (;j < endsurface;j++)
13338                         {
13339                                 surface = rsurface.modelsurfaces + surfacelist[j];
13340                                 if (texture != surface->texture)
13341                                         break;
13342                                 texturesurfacelist[texturenumsurfaces++] = surface;
13343                         }
13344                 }
13345                 else
13346                 {
13347                         rsurface.lightmaptexture = surface->lightmaptexture;
13348                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13349                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13350                         for (;j < endsurface;j++)
13351                         {
13352                                 surface = rsurface.modelsurfaces + surfacelist[j];
13353                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13354                                         break;
13355                                 texturesurfacelist[texturenumsurfaces++] = surface;
13356                         }
13357                 }
13358                 // render the range of surfaces
13359                 if (ent == r_refdef.scene.worldentity)
13360                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13361                 else
13362                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13363         }
13364         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13365         GL_AlphaTest(false);
13366 }
13367
13368 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13369 {
13370         // transparent surfaces get pushed off into the transparent queue
13371         int surfacelistindex;
13372         const msurface_t *surface;
13373         vec3_t tempcenter, center;
13374         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13375         {
13376                 surface = texturesurfacelist[surfacelistindex];
13377                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13378                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13379                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13380                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13381                 if (queueentity->transparent_offset) // transparent offset
13382                 {
13383                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13384                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13385                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13386                 }
13387                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13388         }
13389 }
13390
13391 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13392 {
13393         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13394                 return;
13395         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13396                 return;
13397         RSurf_SetupDepthAndCulling();
13398         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13399         if (rsurface.batchvertex3fbuffer)
13400                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13401         else
13402                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13403         RSurf_DrawBatch();
13404 }
13405
13406 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13407 {
13408         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13409         CHECKGLERROR
13410         if (depthonly)
13411                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13412         else if (prepass)
13413         {
13414                 if (!rsurface.texture->currentnumlayers)
13415                         return;
13416                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13417                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13418                 else
13419                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13420         }
13421         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13422                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13423         else if (!rsurface.texture->currentnumlayers)
13424                 return;
13425         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13426         {
13427                 // in the deferred case, transparent surfaces were queued during prepass
13428                 if (!r_shadow_usingdeferredprepass)
13429                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13430         }
13431         else
13432         {
13433                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13434                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13435         }
13436         CHECKGLERROR
13437 }
13438
13439 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13440 {
13441         int i, j;
13442         texture_t *texture;
13443         R_FrameData_SetMark();
13444         // break the surface list down into batches by texture and use of lightmapping
13445         for (i = 0;i < numsurfaces;i = j)
13446         {
13447                 j = i + 1;
13448                 // texture is the base texture pointer, rsurface.texture is the
13449                 // current frame/skin the texture is directing us to use (for example
13450                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13451                 // use skin 1 instead)
13452                 texture = surfacelist[i]->texture;
13453                 rsurface.texture = R_GetCurrentTexture(texture);
13454                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13455                 {
13456                         // if this texture is not the kind we want, skip ahead to the next one
13457                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13458                                 ;
13459                         continue;
13460                 }
13461                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13462                 {
13463                         rsurface.lightmaptexture = NULL;
13464                         rsurface.deluxemaptexture = NULL;
13465                         rsurface.uselightmaptexture = false;
13466                         // simply scan ahead until we find a different texture or lightmap state
13467                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13468                                 ;
13469                 }
13470                 else
13471                 {
13472                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13473                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13474                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13475                         // simply scan ahead until we find a different texture or lightmap state
13476                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13477                                 ;
13478                 }
13479                 // render the range of surfaces
13480                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13481         }
13482         R_FrameData_ReturnToMark();
13483 }
13484
13485 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13486 {
13487         CHECKGLERROR
13488         if (depthonly)
13489                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13490         else if (prepass)
13491         {
13492                 if (!rsurface.texture->currentnumlayers)
13493                         return;
13494                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13495                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13496                 else
13497                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13498         }
13499         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13500                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13501         else if (!rsurface.texture->currentnumlayers)
13502                 return;
13503         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13504         {
13505                 // in the deferred case, transparent surfaces were queued during prepass
13506                 if (!r_shadow_usingdeferredprepass)
13507                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13508         }
13509         else
13510         {
13511                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13512                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13513         }
13514         CHECKGLERROR
13515 }
13516
13517 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13518 {
13519         int i, j;
13520         texture_t *texture;
13521         R_FrameData_SetMark();
13522         // break the surface list down into batches by texture and use of lightmapping
13523         for (i = 0;i < numsurfaces;i = j)
13524         {
13525                 j = i + 1;
13526                 // texture is the base texture pointer, rsurface.texture is the
13527                 // current frame/skin the texture is directing us to use (for example
13528                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13529                 // use skin 1 instead)
13530                 texture = surfacelist[i]->texture;
13531                 rsurface.texture = R_GetCurrentTexture(texture);
13532                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13533                 {
13534                         // if this texture is not the kind we want, skip ahead to the next one
13535                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13536                                 ;
13537                         continue;
13538                 }
13539                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13540                 {
13541                         rsurface.lightmaptexture = NULL;
13542                         rsurface.deluxemaptexture = NULL;
13543                         rsurface.uselightmaptexture = false;
13544                         // simply scan ahead until we find a different texture or lightmap state
13545                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13546                                 ;
13547                 }
13548                 else
13549                 {
13550                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13551                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13552                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13553                         // simply scan ahead until we find a different texture or lightmap state
13554                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13555                                 ;
13556                 }
13557                 // render the range of surfaces
13558                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13559         }
13560         R_FrameData_ReturnToMark();
13561 }
13562
13563 float locboxvertex3f[6*4*3] =
13564 {
13565         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13566         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13567         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13568         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13569         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13570         1,0,0, 0,0,0, 0,1,0, 1,1,0
13571 };
13572
13573 unsigned short locboxelements[6*2*3] =
13574 {
13575          0, 1, 2, 0, 2, 3,
13576          4, 5, 6, 4, 6, 7,
13577          8, 9,10, 8,10,11,
13578         12,13,14, 12,14,15,
13579         16,17,18, 16,18,19,
13580         20,21,22, 20,22,23
13581 };
13582
13583 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13584 {
13585         int i, j;
13586         cl_locnode_t *loc = (cl_locnode_t *)ent;
13587         vec3_t mins, size;
13588         float vertex3f[6*4*3];
13589         CHECKGLERROR
13590         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13591         GL_DepthMask(false);
13592         GL_DepthRange(0, 1);
13593         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13594         GL_DepthTest(true);
13595         GL_CullFace(GL_NONE);
13596         R_EntityMatrix(&identitymatrix);
13597
13598 //      R_Mesh_ResetTextureState();
13599
13600         i = surfacelist[0];
13601         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13602                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13603                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13604                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13605
13606         if (VectorCompare(loc->mins, loc->maxs))
13607         {
13608                 VectorSet(size, 2, 2, 2);
13609                 VectorMA(loc->mins, -0.5f, size, mins);
13610         }
13611         else
13612         {
13613                 VectorCopy(loc->mins, mins);
13614                 VectorSubtract(loc->maxs, loc->mins, size);
13615         }
13616
13617         for (i = 0;i < 6*4*3;)
13618                 for (j = 0;j < 3;j++, i++)
13619                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13620
13621         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13622         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13623         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13624 }
13625
13626 void R_DrawLocs(void)
13627 {
13628         int index;
13629         cl_locnode_t *loc, *nearestloc;
13630         vec3_t center;
13631         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13632         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13633         {
13634                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13635                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13636         }
13637 }
13638
13639 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13640 {
13641         if (decalsystem->decals)
13642                 Mem_Free(decalsystem->decals);
13643         memset(decalsystem, 0, sizeof(*decalsystem));
13644 }
13645
13646 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)
13647 {
13648         tridecal_t *decal;
13649         tridecal_t *decals;
13650         int i;
13651
13652         // expand or initialize the system
13653         if (decalsystem->maxdecals <= decalsystem->numdecals)
13654         {
13655                 decalsystem_t old = *decalsystem;
13656                 qboolean useshortelements;
13657                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13658                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13659                 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)));
13660                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13661                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13662                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13663                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13664                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13665                 if (decalsystem->numdecals)
13666                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13667                 if (old.decals)
13668                         Mem_Free(old.decals);
13669                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13670                         decalsystem->element3i[i] = i;
13671                 if (useshortelements)
13672                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13673                                 decalsystem->element3s[i] = i;
13674         }
13675
13676         // grab a decal and search for another free slot for the next one
13677         decals = decalsystem->decals;
13678         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13679         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13680                 ;
13681         decalsystem->freedecal = i;
13682         if (decalsystem->numdecals <= i)
13683                 decalsystem->numdecals = i + 1;
13684
13685         // initialize the decal
13686         decal->lived = 0;
13687         decal->triangleindex = triangleindex;
13688         decal->surfaceindex = surfaceindex;
13689         decal->decalsequence = decalsequence;
13690         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13691         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13692         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13693         decal->color4ub[0][3] = 255;
13694         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13695         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13696         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13697         decal->color4ub[1][3] = 255;
13698         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13699         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13700         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13701         decal->color4ub[2][3] = 255;
13702         decal->vertex3f[0][0] = v0[0];
13703         decal->vertex3f[0][1] = v0[1];
13704         decal->vertex3f[0][2] = v0[2];
13705         decal->vertex3f[1][0] = v1[0];
13706         decal->vertex3f[1][1] = v1[1];
13707         decal->vertex3f[1][2] = v1[2];
13708         decal->vertex3f[2][0] = v2[0];
13709         decal->vertex3f[2][1] = v2[1];
13710         decal->vertex3f[2][2] = v2[2];
13711         decal->texcoord2f[0][0] = t0[0];
13712         decal->texcoord2f[0][1] = t0[1];
13713         decal->texcoord2f[1][0] = t1[0];
13714         decal->texcoord2f[1][1] = t1[1];
13715         decal->texcoord2f[2][0] = t2[0];
13716         decal->texcoord2f[2][1] = t2[1];
13717 }
13718
13719 extern cvar_t cl_decals_bias;
13720 extern cvar_t cl_decals_models;
13721 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13722 // baseparms, parms, temps
13723 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)
13724 {
13725         int cornerindex;
13726         int index;
13727         float v[9][3];
13728         const float *vertex3f;
13729         int numpoints;
13730         float points[2][9][3];
13731         float temp[3];
13732         float tc[9][2];
13733         float f;
13734         float c[9][4];
13735         const int *e;
13736
13737         e = rsurface.modelelement3i + 3*triangleindex;
13738
13739         vertex3f = rsurface.modelvertex3f;
13740
13741         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13742         {
13743                 index = 3*e[cornerindex];
13744                 VectorCopy(vertex3f + index, v[cornerindex]);
13745         }
13746         // cull backfaces
13747         //TriangleNormal(v[0], v[1], v[2], normal);
13748         //if (DotProduct(normal, localnormal) < 0.0f)
13749         //      continue;
13750         // clip by each of the box planes formed from the projection matrix
13751         // if anything survives, we emit the decal
13752         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]);
13753         if (numpoints < 3)
13754                 return;
13755         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]);
13756         if (numpoints < 3)
13757                 return;
13758         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]);
13759         if (numpoints < 3)
13760                 return;
13761         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]);
13762         if (numpoints < 3)
13763                 return;
13764         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]);
13765         if (numpoints < 3)
13766                 return;
13767         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]);
13768         if (numpoints < 3)
13769                 return;
13770         // some part of the triangle survived, so we have to accept it...
13771         if (dynamic)
13772         {
13773                 // dynamic always uses the original triangle
13774                 numpoints = 3;
13775                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13776                 {
13777                         index = 3*e[cornerindex];
13778                         VectorCopy(vertex3f + index, v[cornerindex]);
13779                 }
13780         }
13781         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13782         {
13783                 // convert vertex positions to texcoords
13784                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13785                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13786                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13787                 // calculate distance fade from the projection origin
13788                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13789                 f = bound(0.0f, f, 1.0f);
13790                 c[cornerindex][0] = r * f;
13791                 c[cornerindex][1] = g * f;
13792                 c[cornerindex][2] = b * f;
13793                 c[cornerindex][3] = 1.0f;
13794                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13795         }
13796         if (dynamic)
13797                 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);
13798         else
13799                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13800                         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);
13801 }
13802 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)
13803 {
13804         matrix4x4_t projection;
13805         decalsystem_t *decalsystem;
13806         qboolean dynamic;
13807         dp_model_t *model;
13808         const msurface_t *surface;
13809         const msurface_t *surfaces;
13810         const int *surfacelist;
13811         const texture_t *texture;
13812         int numtriangles;
13813         int numsurfacelist;
13814         int surfacelistindex;
13815         int surfaceindex;
13816         int triangleindex;
13817         float localorigin[3];
13818         float localnormal[3];
13819         float localmins[3];
13820         float localmaxs[3];
13821         float localsize;
13822         //float normal[3];
13823         float planes[6][4];
13824         float angles[3];
13825         bih_t *bih;
13826         int bih_triangles_count;
13827         int bih_triangles[256];
13828         int bih_surfaces[256];
13829
13830         decalsystem = &ent->decalsystem;
13831         model = ent->model;
13832         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13833         {
13834                 R_DecalSystem_Reset(&ent->decalsystem);
13835                 return;
13836         }
13837
13838         if (!model->brush.data_leafs && !cl_decals_models.integer)
13839         {
13840                 if (decalsystem->model)
13841                         R_DecalSystem_Reset(decalsystem);
13842                 return;
13843         }
13844
13845         if (decalsystem->model != model)
13846                 R_DecalSystem_Reset(decalsystem);
13847         decalsystem->model = model;
13848
13849         RSurf_ActiveModelEntity(ent, false, false, false);
13850
13851         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13852         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13853         VectorNormalize(localnormal);
13854         localsize = worldsize*rsurface.inversematrixscale;
13855         localmins[0] = localorigin[0] - localsize;
13856         localmins[1] = localorigin[1] - localsize;
13857         localmins[2] = localorigin[2] - localsize;
13858         localmaxs[0] = localorigin[0] + localsize;
13859         localmaxs[1] = localorigin[1] + localsize;
13860         localmaxs[2] = localorigin[2] + localsize;
13861
13862         //VectorCopy(localnormal, planes[4]);
13863         //VectorVectors(planes[4], planes[2], planes[0]);
13864         AnglesFromVectors(angles, localnormal, NULL, false);
13865         AngleVectors(angles, planes[0], planes[2], planes[4]);
13866         VectorNegate(planes[0], planes[1]);
13867         VectorNegate(planes[2], planes[3]);
13868         VectorNegate(planes[4], planes[5]);
13869         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13870         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13871         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13872         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13873         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13874         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13875
13876 #if 1
13877 // works
13878 {
13879         matrix4x4_t forwardprojection;
13880         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13881         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13882 }
13883 #else
13884 // broken
13885 {
13886         float projectionvector[4][3];
13887         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13888         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13889         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13890         projectionvector[0][0] = planes[0][0] * ilocalsize;
13891         projectionvector[0][1] = planes[1][0] * ilocalsize;
13892         projectionvector[0][2] = planes[2][0] * ilocalsize;
13893         projectionvector[1][0] = planes[0][1] * ilocalsize;
13894         projectionvector[1][1] = planes[1][1] * ilocalsize;
13895         projectionvector[1][2] = planes[2][1] * ilocalsize;
13896         projectionvector[2][0] = planes[0][2] * ilocalsize;
13897         projectionvector[2][1] = planes[1][2] * ilocalsize;
13898         projectionvector[2][2] = planes[2][2] * ilocalsize;
13899         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13900         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13901         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13902         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13903 }
13904 #endif
13905
13906         dynamic = model->surfmesh.isanimated;
13907         numsurfacelist = model->nummodelsurfaces;
13908         surfacelist = model->sortedmodelsurfaces;
13909         surfaces = model->data_surfaces;
13910
13911         bih = NULL;
13912         bih_triangles_count = -1;
13913         if(!dynamic)
13914         {
13915                 if(model->render_bih.numleafs)
13916                         bih = &model->render_bih;
13917                 else if(model->collision_bih.numleafs)
13918                         bih = &model->collision_bih;
13919         }
13920         if(bih)
13921                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13922         if(bih_triangles_count == 0)
13923                 return;
13924         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13925                 return;
13926         if(bih_triangles_count > 0)
13927         {
13928                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13929                 {
13930                         surfaceindex = bih_surfaces[triangleindex];
13931                         surface = surfaces + surfaceindex;
13932                         texture = surface->texture;
13933                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13934                                 continue;
13935                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13936                                 continue;
13937                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13938                 }
13939         }
13940         else
13941         {
13942                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13943                 {
13944                         surfaceindex = surfacelist[surfacelistindex];
13945                         surface = surfaces + surfaceindex;
13946                         // check cull box first because it rejects more than any other check
13947                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13948                                 continue;
13949                         // skip transparent surfaces
13950                         texture = surface->texture;
13951                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13952                                 continue;
13953                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13954                                 continue;
13955                         numtriangles = surface->num_triangles;
13956                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13957                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13958                 }
13959         }
13960 }
13961
13962 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13963 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)
13964 {
13965         int renderentityindex;
13966         float worldmins[3];
13967         float worldmaxs[3];
13968         entity_render_t *ent;
13969
13970         if (!cl_decals_newsystem.integer)
13971                 return;
13972
13973         worldmins[0] = worldorigin[0] - worldsize;
13974         worldmins[1] = worldorigin[1] - worldsize;
13975         worldmins[2] = worldorigin[2] - worldsize;
13976         worldmaxs[0] = worldorigin[0] + worldsize;
13977         worldmaxs[1] = worldorigin[1] + worldsize;
13978         worldmaxs[2] = worldorigin[2] + worldsize;
13979
13980         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13981
13982         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13983         {
13984                 ent = r_refdef.scene.entities[renderentityindex];
13985                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13986                         continue;
13987
13988                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13989         }
13990 }
13991
13992 typedef struct r_decalsystem_splatqueue_s
13993 {
13994         vec3_t worldorigin;
13995         vec3_t worldnormal;
13996         float color[4];
13997         float tcrange[4];
13998         float worldsize;
13999         int decalsequence;
14000 }
14001 r_decalsystem_splatqueue_t;
14002
14003 int r_decalsystem_numqueued = 0;
14004 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
14005
14006 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)
14007 {
14008         r_decalsystem_splatqueue_t *queue;
14009
14010         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
14011                 return;
14012
14013         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
14014         VectorCopy(worldorigin, queue->worldorigin);
14015         VectorCopy(worldnormal, queue->worldnormal);
14016         Vector4Set(queue->color, r, g, b, a);
14017         Vector4Set(queue->tcrange, s1, t1, s2, t2);
14018         queue->worldsize = worldsize;
14019         queue->decalsequence = cl.decalsequence++;
14020 }
14021
14022 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
14023 {
14024         int i;
14025         r_decalsystem_splatqueue_t *queue;
14026
14027         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
14028                 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);
14029         r_decalsystem_numqueued = 0;
14030 }
14031
14032 extern cvar_t cl_decals_max;
14033 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
14034 {
14035         int i;
14036         decalsystem_t *decalsystem = &ent->decalsystem;
14037         int numdecals;
14038         int killsequence;
14039         tridecal_t *decal;
14040         float frametime;
14041         float lifetime;
14042
14043         if (!decalsystem->numdecals)
14044                 return;
14045
14046         if (r_showsurfaces.integer)
14047                 return;
14048
14049         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14050         {
14051                 R_DecalSystem_Reset(decalsystem);
14052                 return;
14053         }
14054
14055         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
14056         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
14057
14058         if (decalsystem->lastupdatetime)
14059                 frametime = (cl.time - decalsystem->lastupdatetime);
14060         else
14061                 frametime = 0;
14062         decalsystem->lastupdatetime = cl.time;
14063         decal = decalsystem->decals;
14064         numdecals = decalsystem->numdecals;
14065
14066         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14067         {
14068                 if (decal->color4ub[0][3])
14069                 {
14070                         decal->lived += frametime;
14071                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
14072                         {
14073                                 memset(decal, 0, sizeof(*decal));
14074                                 if (decalsystem->freedecal > i)
14075                                         decalsystem->freedecal = i;
14076                         }
14077                 }
14078         }
14079         decal = decalsystem->decals;
14080         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
14081                 numdecals--;
14082
14083         // collapse the array by shuffling the tail decals into the gaps
14084         for (;;)
14085         {
14086                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
14087                         decalsystem->freedecal++;
14088                 if (decalsystem->freedecal == numdecals)
14089                         break;
14090                 decal[decalsystem->freedecal] = decal[--numdecals];
14091         }
14092
14093         decalsystem->numdecals = numdecals;
14094
14095         if (numdecals <= 0)
14096         {
14097                 // if there are no decals left, reset decalsystem
14098                 R_DecalSystem_Reset(decalsystem);
14099         }
14100 }
14101
14102 extern skinframe_t *decalskinframe;
14103 static void R_DrawModelDecals_Entity(entity_render_t *ent)
14104 {
14105         int i;
14106         decalsystem_t *decalsystem = &ent->decalsystem;
14107         int numdecals;
14108         tridecal_t *decal;
14109         float faderate;
14110         float alpha;
14111         float *v3f;
14112         float *c4f;
14113         float *t2f;
14114         const int *e;
14115         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14116         int numtris = 0;
14117
14118         numdecals = decalsystem->numdecals;
14119         if (!numdecals)
14120                 return;
14121
14122         if (r_showsurfaces.integer)
14123                 return;
14124
14125         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14126         {
14127                 R_DecalSystem_Reset(decalsystem);
14128                 return;
14129         }
14130
14131         // if the model is static it doesn't matter what value we give for
14132         // wantnormals and wanttangents, so this logic uses only rules applicable
14133         // to a model, knowing that they are meaningless otherwise
14134         if (ent == r_refdef.scene.worldentity)
14135                 RSurf_ActiveWorldEntity();
14136         else
14137                 RSurf_ActiveModelEntity(ent, false, false, false);
14138
14139         decalsystem->lastupdatetime = cl.time;
14140         decal = decalsystem->decals;
14141
14142         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14143
14144         // update vertex positions for animated models
14145         v3f = decalsystem->vertex3f;
14146         c4f = decalsystem->color4f;
14147         t2f = decalsystem->texcoord2f;
14148         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14149         {
14150                 if (!decal->color4ub[0][3])
14151                         continue;
14152
14153                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14154                         continue;
14155
14156                 // update color values for fading decals
14157                 if (decal->lived >= cl_decals_time.value)
14158                 {
14159                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14160                         alpha *= (1.0f/255.0f);
14161                 }
14162                 else
14163                         alpha = 1.0f/255.0f;
14164
14165                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14166                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14167                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14168                 c4f[ 3] = 1;
14169                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14170                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14171                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14172                 c4f[ 7] = 1;
14173                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14174                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14175                 c4f[10] = decal->color4ub[2][2] * alpha;
14176                 c4f[11] = 1;
14177
14178                 t2f[0] = decal->texcoord2f[0][0];
14179                 t2f[1] = decal->texcoord2f[0][1];
14180                 t2f[2] = decal->texcoord2f[1][0];
14181                 t2f[3] = decal->texcoord2f[1][1];
14182                 t2f[4] = decal->texcoord2f[2][0];
14183                 t2f[5] = decal->texcoord2f[2][1];
14184
14185                 // update vertex positions for animated models
14186                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14187                 {
14188                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14189                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14190                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14191                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14192                 }
14193                 else
14194                 {
14195                         VectorCopy(decal->vertex3f[0], v3f);
14196                         VectorCopy(decal->vertex3f[1], v3f + 3);
14197                         VectorCopy(decal->vertex3f[2], v3f + 6);
14198                 }
14199
14200                 if (r_refdef.fogenabled)
14201                 {
14202                         alpha = RSurf_FogVertex(v3f);
14203                         VectorScale(c4f, alpha, c4f);
14204                         alpha = RSurf_FogVertex(v3f + 3);
14205                         VectorScale(c4f + 4, alpha, c4f + 4);
14206                         alpha = RSurf_FogVertex(v3f + 6);
14207                         VectorScale(c4f + 8, alpha, c4f + 8);
14208                 }
14209
14210                 v3f += 9;
14211                 c4f += 12;
14212                 t2f += 6;
14213                 numtris++;
14214         }
14215
14216         if (numtris > 0)
14217         {
14218                 r_refdef.stats.drawndecals += numtris;
14219
14220                 // now render the decals all at once
14221                 // (this assumes they all use one particle font texture!)
14222                 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);
14223 //              R_Mesh_ResetTextureState();
14224                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14225                 GL_DepthMask(false);
14226                 GL_DepthRange(0, 1);
14227                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14228                 GL_DepthTest(true);
14229                 GL_CullFace(GL_NONE);
14230                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14231                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14232                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14233         }
14234 }
14235
14236 static void R_DrawModelDecals(void)
14237 {
14238         int i, numdecals;
14239
14240         // fade faster when there are too many decals
14241         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14242         for (i = 0;i < r_refdef.scene.numentities;i++)
14243                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14244
14245         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14246         for (i = 0;i < r_refdef.scene.numentities;i++)
14247                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14248                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14249
14250         R_DecalSystem_ApplySplatEntitiesQueue();
14251
14252         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14253         for (i = 0;i < r_refdef.scene.numentities;i++)
14254                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14255
14256         r_refdef.stats.totaldecals += numdecals;
14257
14258         if (r_showsurfaces.integer)
14259                 return;
14260
14261         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14262
14263         for (i = 0;i < r_refdef.scene.numentities;i++)
14264         {
14265                 if (!r_refdef.viewcache.entityvisible[i])
14266                         continue;
14267                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14268                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14269         }
14270 }
14271
14272 extern cvar_t mod_collision_bih;
14273 void R_DrawDebugModel(void)
14274 {
14275         entity_render_t *ent = rsurface.entity;
14276         int i, j, k, l, flagsmask;
14277         const msurface_t *surface;
14278         dp_model_t *model = ent->model;
14279         vec3_t v;
14280
14281         switch(vid.renderpath)
14282         {
14283         case RENDERPATH_GL11:
14284         case RENDERPATH_GL13:
14285         case RENDERPATH_GL20:
14286         case RENDERPATH_CGGL:
14287                 break;
14288         case RENDERPATH_D3D9:
14289                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14290                 return;
14291         case RENDERPATH_D3D10:
14292                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14293                 return;
14294         case RENDERPATH_D3D11:
14295                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14296                 return;
14297         case RENDERPATH_SOFT:
14298                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14299                 return;
14300         }
14301
14302         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14303
14304 //      R_Mesh_ResetTextureState();
14305         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14306         GL_DepthRange(0, 1);
14307         GL_DepthTest(!r_showdisabledepthtest.integer);
14308         GL_DepthMask(false);
14309         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14310
14311         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14312         {
14313                 int triangleindex;
14314                 int bihleafindex;
14315                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14316                 const q3mbrush_t *brush;
14317                 const bih_t *bih = &model->collision_bih;
14318                 const bih_leaf_t *bihleaf;
14319                 float vertex3f[3][3];
14320                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14321                 cullbox = false;
14322                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14323                 {
14324                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14325                                 continue;
14326                         switch (bihleaf->type)
14327                         {
14328                         case BIH_BRUSH:
14329                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14330                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14331                                 {
14332                                         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);
14333                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14334                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14335                                 }
14336                                 break;
14337                         case BIH_COLLISIONTRIANGLE:
14338                                 triangleindex = bihleaf->itemindex;
14339                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14340                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14341                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14342                                 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);
14343                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14344                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14345                                 break;
14346                         case BIH_RENDERTRIANGLE:
14347                                 triangleindex = bihleaf->itemindex;
14348                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14349                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14350                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14351                                 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);
14352                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14353                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14354                                 break;
14355                         }
14356                 }
14357         }
14358
14359         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14360
14361         if (r_showtris.integer || (r_shownormals.value != 0))
14362         {
14363                 if (r_showdisabledepthtest.integer)
14364                 {
14365                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14366                         GL_DepthMask(false);
14367                 }
14368                 else
14369                 {
14370                         GL_BlendFunc(GL_ONE, GL_ZERO);
14371                         GL_DepthMask(true);
14372                 }
14373                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14374                 {
14375                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14376                                 continue;
14377                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14378                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14379                         {
14380                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14381                                 if (r_showtris.value > 0)
14382                                 {
14383                                         if (!rsurface.texture->currentlayers->depthmask)
14384                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14385                                         else if (ent == r_refdef.scene.worldentity)
14386                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14387                                         else
14388                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14389                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14390                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14391                                         RSurf_DrawBatch();
14392                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14393                                         CHECKGLERROR
14394                                 }
14395                                 if (r_shownormals.value < 0)
14396                                 {
14397                                         qglBegin(GL_LINES);
14398                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14399                                         {
14400                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14401                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14402                                                 qglVertex3f(v[0], v[1], v[2]);
14403                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14404                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14405                                                 qglVertex3f(v[0], v[1], v[2]);
14406                                         }
14407                                         qglEnd();
14408                                         CHECKGLERROR
14409                                 }
14410                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14411                                 {
14412                                         qglBegin(GL_LINES);
14413                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14414                                         {
14415                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14416                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14417                                                 qglVertex3f(v[0], v[1], v[2]);
14418                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14419                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14420                                                 qglVertex3f(v[0], v[1], v[2]);
14421                                         }
14422                                         qglEnd();
14423                                         CHECKGLERROR
14424                                         qglBegin(GL_LINES);
14425                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14426                                         {
14427                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14428                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14429                                                 qglVertex3f(v[0], v[1], v[2]);
14430                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14431                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14432                                                 qglVertex3f(v[0], v[1], v[2]);
14433                                         }
14434                                         qglEnd();
14435                                         CHECKGLERROR
14436                                         qglBegin(GL_LINES);
14437                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14438                                         {
14439                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14440                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14441                                                 qglVertex3f(v[0], v[1], v[2]);
14442                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14443                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14444                                                 qglVertex3f(v[0], v[1], v[2]);
14445                                         }
14446                                         qglEnd();
14447                                         CHECKGLERROR
14448                                 }
14449                         }
14450                 }
14451                 rsurface.texture = NULL;
14452         }
14453 }
14454
14455 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14456 int r_maxsurfacelist = 0;
14457 const msurface_t **r_surfacelist = NULL;
14458 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14459 {
14460         int i, j, endj, flagsmask;
14461         dp_model_t *model = r_refdef.scene.worldmodel;
14462         msurface_t *surfaces;
14463         unsigned char *update;
14464         int numsurfacelist = 0;
14465         if (model == NULL)
14466                 return;
14467
14468         if (r_maxsurfacelist < model->num_surfaces)
14469         {
14470                 r_maxsurfacelist = model->num_surfaces;
14471                 if (r_surfacelist)
14472                         Mem_Free((msurface_t**)r_surfacelist);
14473                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14474         }
14475
14476         RSurf_ActiveWorldEntity();
14477
14478         surfaces = model->data_surfaces;
14479         update = model->brushq1.lightmapupdateflags;
14480
14481         // update light styles on this submodel
14482         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14483         {
14484                 model_brush_lightstyleinfo_t *style;
14485                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14486                 {
14487                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14488                         {
14489                                 int *list = style->surfacelist;
14490                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14491                                 for (j = 0;j < style->numsurfaces;j++)
14492                                         update[list[j]] = true;
14493                         }
14494                 }
14495         }
14496
14497         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14498
14499         if (debug)
14500         {
14501                 R_DrawDebugModel();
14502                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14503                 return;
14504         }
14505
14506         rsurface.lightmaptexture = NULL;
14507         rsurface.deluxemaptexture = NULL;
14508         rsurface.uselightmaptexture = false;
14509         rsurface.texture = NULL;
14510         rsurface.rtlight = NULL;
14511         numsurfacelist = 0;
14512         // add visible surfaces to draw list
14513         for (i = 0;i < model->nummodelsurfaces;i++)
14514         {
14515                 j = model->sortedmodelsurfaces[i];
14516                 if (r_refdef.viewcache.world_surfacevisible[j])
14517                         r_surfacelist[numsurfacelist++] = surfaces + j;
14518         }
14519         // update lightmaps if needed
14520         if (model->brushq1.firstrender)
14521         {
14522                 model->brushq1.firstrender = false;
14523                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14524                         if (update[j])
14525                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14526         }
14527         else if (update)
14528         {
14529                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14530                         if (r_refdef.viewcache.world_surfacevisible[j])
14531                                 if (update[j])
14532                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14533         }
14534         // don't do anything if there were no surfaces
14535         if (!numsurfacelist)
14536         {
14537                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14538                 return;
14539         }
14540         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14541         GL_AlphaTest(false);
14542
14543         // add to stats if desired
14544         if (r_speeds.integer && !skysurfaces && !depthonly)
14545         {
14546                 r_refdef.stats.world_surfaces += numsurfacelist;
14547                 for (j = 0;j < numsurfacelist;j++)
14548                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14549         }
14550
14551         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14552 }
14553
14554 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14555 {
14556         int i, j, endj, flagsmask;
14557         dp_model_t *model = ent->model;
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         // if the model is static it doesn't matter what value we give for
14573         // wantnormals and wanttangents, so this logic uses only rules applicable
14574         // to a model, knowing that they are meaningless otherwise
14575         if (ent == r_refdef.scene.worldentity)
14576                 RSurf_ActiveWorldEntity();
14577         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14578                 RSurf_ActiveModelEntity(ent, false, false, false);
14579         else if (prepass)
14580                 RSurf_ActiveModelEntity(ent, true, true, true);
14581         else if (depthonly)
14582         {
14583                 switch (vid.renderpath)
14584                 {
14585                 case RENDERPATH_GL20:
14586                 case RENDERPATH_CGGL:
14587                 case RENDERPATH_D3D9:
14588                 case RENDERPATH_D3D10:
14589                 case RENDERPATH_D3D11:
14590                 case RENDERPATH_SOFT:
14591                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14592                         break;
14593                 case RENDERPATH_GL13:
14594                 case RENDERPATH_GL11:
14595                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14596                         break;
14597                 }
14598         }
14599         else
14600         {
14601                 switch (vid.renderpath)
14602                 {
14603                 case RENDERPATH_GL20:
14604                 case RENDERPATH_CGGL:
14605                 case RENDERPATH_D3D9:
14606                 case RENDERPATH_D3D10:
14607                 case RENDERPATH_D3D11:
14608                 case RENDERPATH_SOFT:
14609                         RSurf_ActiveModelEntity(ent, true, true, false);
14610                         break;
14611                 case RENDERPATH_GL13:
14612                 case RENDERPATH_GL11:
14613                         RSurf_ActiveModelEntity(ent, true, false, false);
14614                         break;
14615                 }
14616         }
14617
14618         surfaces = model->data_surfaces;
14619         update = model->brushq1.lightmapupdateflags;
14620
14621         // update light styles
14622         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14623         {
14624                 model_brush_lightstyleinfo_t *style;
14625                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14626                 {
14627                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14628                         {
14629                                 int *list = style->surfacelist;
14630                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14631                                 for (j = 0;j < style->numsurfaces;j++)
14632                                         update[list[j]] = true;
14633                         }
14634                 }
14635         }
14636
14637         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14638
14639         if (debug)
14640         {
14641                 R_DrawDebugModel();
14642                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14643                 return;
14644         }
14645
14646         rsurface.lightmaptexture = NULL;
14647         rsurface.deluxemaptexture = NULL;
14648         rsurface.uselightmaptexture = false;
14649         rsurface.texture = NULL;
14650         rsurface.rtlight = NULL;
14651         numsurfacelist = 0;
14652         // add visible surfaces to draw list
14653         for (i = 0;i < model->nummodelsurfaces;i++)
14654                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14655         // don't do anything if there were no surfaces
14656         if (!numsurfacelist)
14657         {
14658                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14659                 return;
14660         }
14661         // update lightmaps if needed
14662         if (update)
14663         {
14664                 int updated = 0;
14665                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14666                 {
14667                         if (update[j])
14668                         {
14669                                 updated++;
14670                                 R_BuildLightMap(ent, surfaces + j);
14671                         }
14672                 }
14673         }
14674         if (update)
14675                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14676                         if (update[j])
14677                                 R_BuildLightMap(ent, surfaces + j);
14678         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14679         GL_AlphaTest(false);
14680
14681         // add to stats if desired
14682         if (r_speeds.integer && !skysurfaces && !depthonly)
14683         {
14684                 r_refdef.stats.entities_surfaces += numsurfacelist;
14685                 for (j = 0;j < numsurfacelist;j++)
14686                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14687         }
14688
14689         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14690 }
14691
14692 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14693 {
14694         static texture_t texture;
14695         static msurface_t surface;
14696         const msurface_t *surfacelist = &surface;
14697
14698         // fake enough texture and surface state to render this geometry
14699
14700         texture.update_lastrenderframe = -1; // regenerate this texture
14701         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14702         texture.currentskinframe = skinframe;
14703         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14704         texture.offsetmapping = OFFSETMAPPING_OFF;
14705         texture.offsetscale = 1;
14706         texture.specularscalemod = 1;
14707         texture.specularpowermod = 1;
14708
14709         surface.texture = &texture;
14710         surface.num_triangles = numtriangles;
14711         surface.num_firsttriangle = firsttriangle;
14712         surface.num_vertices = numvertices;
14713         surface.num_firstvertex = firstvertex;
14714
14715         // now render it
14716         rsurface.texture = R_GetCurrentTexture(surface.texture);
14717         rsurface.lightmaptexture = NULL;
14718         rsurface.deluxemaptexture = NULL;
14719         rsurface.uselightmaptexture = false;
14720         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14721 }
14722
14723 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)
14724 {
14725         static msurface_t surface;
14726         const msurface_t *surfacelist = &surface;
14727
14728         // fake enough texture and surface state to render this geometry
14729         surface.texture = texture;
14730         surface.num_triangles = numtriangles;
14731         surface.num_firsttriangle = firsttriangle;
14732         surface.num_vertices = numvertices;
14733         surface.num_firstvertex = firstvertex;
14734
14735         // now render it
14736         rsurface.texture = R_GetCurrentTexture(surface.texture);
14737         rsurface.lightmaptexture = NULL;
14738         rsurface.deluxemaptexture = NULL;
14739         rsurface.uselightmaptexture = false;
14740         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14741 }