]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
move double break in pseudoalpha case to the right case...
[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 exagerated 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 (equivilant 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 accodringly, 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_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4941         DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4942         DPSOFTRAST_Uniform1fARB(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_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
6168                 if (mode == SHADERMODE_LIGHTSOURCE)
6169                 {
6170                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
6171                         DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
6172                         DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
6173                         DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
6174                         DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
6175                         DPSOFTRAST_Uniform3fARB(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_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6179                         DPSOFTRAST_Uniform1fARB(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_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
6186                         }
6187                         else if (mode == SHADERMODE_LIGHTDIRECTION)
6188                         {
6189                                 DPSOFTRAST_Uniform3fARB(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_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
6191                                 DPSOFTRAST_Uniform3fARB(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_Uniform3fARB(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_Uniform3fARB(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
6194                                 DPSOFTRAST_Uniform3fARB(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_Uniform3fARB(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
6196                         }
6197                         else
6198                         {
6199                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
6200                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
6201                                 DPSOFTRAST_Uniform3fARB(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_Uniform3fARB(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_Uniform3fARB(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_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
6208                         else
6209                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
6210                         DPSOFTRAST_Uniform4fARB(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_Uniform4fARB(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
6212                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
6213                         DPSOFTRAST_Uniform4fARB(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_Uniform4fARB(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_Uniform1fARB(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
6216                         DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
6217                         DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6218                         DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
6219                 }
6220                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
6221                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
6222                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
6223                 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6224                 DPSOFTRAST_Uniform4fARB(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_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
6227                 DPSOFTRAST_Uniform1fARB(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_Uniform3fARB(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_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
6233                         else
6234                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
6235                 }
6236                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
6237                 {
6238                         if (rsurface.texture->shirttexture)
6239                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
6240                         else
6241                                 DPSOFTRAST_Uniform3fARB(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
6242                 }
6243                 DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
6244                 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
6245                 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
6246                 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
6247                 DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
6248                 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6249                 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6250
6251         //      R_Mesh_TexBind(GL20TU_FIRST             , r_texture_white                                     );
6252         //      R_Mesh_TexBind(GL20TU_SECOND            , r_texture_white                                     );
6253         //      R_Mesh_TexBind(GL20TU_GAMMARAMPS        , r_texture_gammaramps                                );
6254                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
6255                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
6256                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
6257                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
6258                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
6259                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
6260                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
6261                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
6262                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
6263                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
6264                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
6265                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
6266                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
6267                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
6268                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
6269                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
6270                 if (rsurface.rtlight                                      ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
6271                 if (rsurfacepass == RSURFPASS_BACKGROUND)
6272                 {
6273                         if(DPSOFTRAST_UNIFORM_Texture_Refraction >= 0) R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
6274                         else if(DPSOFTRAST_UNIFORM_Texture_First >= 0) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
6275                         if(DPSOFTRAST_UNIFORM_Texture_Reflection >= 0) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6276                 }
6277                 else
6278                 {
6279                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
6280                 }
6281 //              R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
6282 //              R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
6283                 R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
6284                 R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
6285                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
6286                 {
6287                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dtexture                         );
6288                         if (rsurface.rtlight)
6289                         {
6290                                 R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
6291                                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
6292                         }
6293                 }
6294                 break;
6295         }
6296 }
6297
6298 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
6299 {
6300         // select a permutation of the lighting shader appropriate to this
6301         // combination of texture, entity, light source, and fogging, only use the
6302         // minimum features necessary to avoid wasting rendering time in the
6303         // fragment shader on features that are not being used
6304         unsigned int permutation = 0;
6305         unsigned int mode = 0;
6306         const float *lightcolorbase = rtlight->currentcolor;
6307         float ambientscale = rtlight->ambientscale;
6308         float diffusescale = rtlight->diffusescale;
6309         float specularscale = rtlight->specularscale;
6310         // this is the location of the light in view space
6311         vec3_t viewlightorigin;
6312         // this transforms from view space (camera) to light space (cubemap)
6313         matrix4x4_t viewtolight;
6314         matrix4x4_t lighttoview;
6315         float viewtolight16f[16];
6316         float range = 1.0f / r_shadow_deferred_8bitrange.value;
6317         // light source
6318         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
6319         if (rtlight->currentcubemap != r_texture_whitecube)
6320                 permutation |= SHADERPERMUTATION_CUBEFILTER;
6321         if (diffusescale > 0)
6322                 permutation |= SHADERPERMUTATION_DIFFUSE;
6323         if (specularscale > 0)
6324                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
6325         if (r_shadow_usingshadowmap2d)
6326         {
6327                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
6328                 if (r_shadow_shadowmapvsdct)
6329                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
6330
6331                 if (r_shadow_shadowmapsampler)
6332                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
6333                 if (r_shadow_shadowmappcf > 1)
6334                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
6335                 else if (r_shadow_shadowmappcf)
6336                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
6337         }
6338         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
6339         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
6340         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
6341         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
6342         switch(vid.renderpath)
6343         {
6344         case RENDERPATH_D3D9:
6345 #ifdef SUPPORTD3D
6346                 R_SetupShader_SetPermutationHLSL(mode, permutation);
6347                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6348                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
6349                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6350                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6351                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6352                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6353                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6354                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6355                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6356                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6357
6358                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6359                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
6360                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6361                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6362                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
6363                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6364 #endif
6365                 break;
6366         case RENDERPATH_D3D10:
6367                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6368                 break;
6369         case RENDERPATH_D3D11:
6370                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6371                 break;
6372         case RENDERPATH_GL20:
6373                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6374                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3fARB(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6375                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
6376                 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);
6377                 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);
6378                 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);
6379                 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]);
6380                 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]);
6381                 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));
6382                 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]);
6383                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6384
6385                 if (r_glsl_permutation->loc_Texture_Attenuation       >= 0) R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6386                 if (r_glsl_permutation->loc_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6387                 if (r_glsl_permutation->loc_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6388                 if (r_glsl_permutation->loc_Texture_Cube              >= 0) R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6389                 if (r_glsl_permutation->loc_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6390                 if (r_glsl_permutation->loc_Texture_CubeProjection    >= 0) R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6391                 break;
6392         case RENDERPATH_CGGL:
6393 #ifdef SUPPORTCG
6394                 R_SetupShader_SetPermutationCG(mode, permutation);
6395                 if (r_cg_permutation->fp_LightPosition            ) cgGLSetParameter3f(r_cg_permutation->fp_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);CHECKCGERROR
6396                 if (r_cg_permutation->fp_ViewToLight              ) cgGLSetMatrixParameterfc(r_cg_permutation->fp_ViewToLight, viewtolight16f);CHECKCGERROR
6397                 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
6398                 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
6399                 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
6400                 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
6401                 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
6402                 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
6403                 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
6404                 if (r_cg_permutation->fp_PixelToScreenTexCoord    ) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
6405
6406                 if (r_cg_permutation->fp_Texture_Attenuation      ) CG_BindTexture(r_cg_permutation->fp_Texture_Attenuation    , r_shadow_attenuationgradienttexture                 );CHECKCGERROR
6407                 if (r_cg_permutation->fp_Texture_ScreenDepth      ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenDepth    , r_shadow_prepassgeometrydepthtexture                );CHECKCGERROR
6408                 if (r_cg_permutation->fp_Texture_ScreenNormalMap  ) CG_BindTexture(r_cg_permutation->fp_Texture_ScreenNormalMap, r_shadow_prepassgeometrynormalmaptexture            );CHECKCGERROR
6409                 if (r_cg_permutation->fp_Texture_Cube             ) CG_BindTexture(r_cg_permutation->fp_Texture_Cube           , rsurface.rtlight->currentcubemap                    );CHECKCGERROR
6410                 if (r_cg_permutation->fp_Texture_ShadowMap2D      ) CG_BindTexture(r_cg_permutation->fp_Texture_ShadowMap2D    , r_shadow_shadowmap2dtexture                         );CHECKCGERROR
6411                 if (r_cg_permutation->fp_Texture_CubeProjection   ) CG_BindTexture(r_cg_permutation->fp_Texture_CubeProjection , r_shadow_shadowmapvsdcttexture                      );CHECKCGERROR
6412 #endif
6413                 break;
6414         case RENDERPATH_GL13:
6415         case RENDERPATH_GL11:
6416                 break;
6417         case RENDERPATH_SOFT:
6418                 R_SetupShader_SetPermutationGLSL(mode, permutation);
6419                 DPSOFTRAST_Uniform3fARB(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
6420                 DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
6421                 DPSOFTRAST_Uniform3fARB(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
6422                 DPSOFTRAST_Uniform3fARB(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
6423                 DPSOFTRAST_Uniform3fARB(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
6424                 DPSOFTRAST_Uniform2fARB(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
6425                 DPSOFTRAST_Uniform4fARB(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
6426                 DPSOFTRAST_Uniform1fARB(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
6427                 DPSOFTRAST_Uniform2fARB(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
6428                 DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6429
6430                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
6431                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
6432                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
6433                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
6434                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
6435                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
6436                 break;
6437         }
6438 }
6439
6440 #define SKINFRAME_HASH 1024
6441
6442 typedef struct
6443 {
6444         int loadsequence; // incremented each level change
6445         memexpandablearray_t array;
6446         skinframe_t *hash[SKINFRAME_HASH];
6447 }
6448 r_skinframe_t;
6449 r_skinframe_t r_skinframe;
6450
6451 void R_SkinFrame_PrepareForPurge(void)
6452 {
6453         r_skinframe.loadsequence++;
6454         // wrap it without hitting zero
6455         if (r_skinframe.loadsequence >= 200)
6456                 r_skinframe.loadsequence = 1;
6457 }
6458
6459 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
6460 {
6461         if (!skinframe)
6462                 return;
6463         // mark the skinframe as used for the purging code
6464         skinframe->loadsequence = r_skinframe.loadsequence;
6465 }
6466
6467 void R_SkinFrame_Purge(void)
6468 {
6469         int i;
6470         skinframe_t *s;
6471         for (i = 0;i < SKINFRAME_HASH;i++)
6472         {
6473                 for (s = r_skinframe.hash[i];s;s = s->next)
6474                 {
6475                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
6476                         {
6477                                 if (s->merged == s->base)
6478                                         s->merged = NULL;
6479                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
6480                                 R_PurgeTexture(s->stain );s->stain  = NULL;
6481                                 R_PurgeTexture(s->merged);s->merged = NULL;
6482                                 R_PurgeTexture(s->base  );s->base   = NULL;
6483                                 R_PurgeTexture(s->pants );s->pants  = NULL;
6484                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
6485                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
6486                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
6487                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
6488                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
6489                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
6490                                 s->loadsequence = 0;
6491                         }
6492                 }
6493         }
6494 }
6495
6496 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
6497         skinframe_t *item;
6498         char basename[MAX_QPATH];
6499
6500         Image_StripImageExtension(name, basename, sizeof(basename));
6501
6502         if( last == NULL ) {
6503                 int hashindex;
6504                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6505                 item = r_skinframe.hash[hashindex];
6506         } else {
6507                 item = last->next;
6508         }
6509
6510         // linearly search through the hash bucket
6511         for( ; item ; item = item->next ) {
6512                 if( !strcmp( item->basename, basename ) ) {
6513                         return item;
6514                 }
6515         }
6516         return NULL;
6517 }
6518
6519 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
6520 {
6521         skinframe_t *item;
6522         int hashindex;
6523         char basename[MAX_QPATH];
6524
6525         Image_StripImageExtension(name, basename, sizeof(basename));
6526
6527         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
6528         for (item = r_skinframe.hash[hashindex];item;item = item->next)
6529                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
6530                         break;
6531
6532         if (!item) {
6533                 rtexture_t *dyntexture;
6534                 // check whether its a dynamic texture
6535                 dyntexture = CL_GetDynTexture( basename );
6536                 if (!add && !dyntexture)
6537                         return NULL;
6538                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
6539                 memset(item, 0, sizeof(*item));
6540                 strlcpy(item->basename, basename, sizeof(item->basename));
6541                 item->base = dyntexture; // either NULL or dyntexture handle
6542                 item->textureflags = textureflags;
6543                 item->comparewidth = comparewidth;
6544                 item->compareheight = compareheight;
6545                 item->comparecrc = comparecrc;
6546                 item->next = r_skinframe.hash[hashindex];
6547                 r_skinframe.hash[hashindex] = item;
6548         }
6549         else if( item->base == NULL )
6550         {
6551                 rtexture_t *dyntexture;
6552                 // check whether its a dynamic texture
6553                 // 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]
6554                 dyntexture = CL_GetDynTexture( basename );
6555                 item->base = dyntexture; // either NULL or dyntexture handle
6556         }
6557
6558         R_SkinFrame_MarkUsed(item);
6559         return item;
6560 }
6561
6562 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
6563         { \
6564                 unsigned long long avgcolor[5], wsum; \
6565                 int pix, comp, w; \
6566                 avgcolor[0] = 0; \
6567                 avgcolor[1] = 0; \
6568                 avgcolor[2] = 0; \
6569                 avgcolor[3] = 0; \
6570                 avgcolor[4] = 0; \
6571                 wsum = 0; \
6572                 for(pix = 0; pix < cnt; ++pix) \
6573                 { \
6574                         w = 0; \
6575                         for(comp = 0; comp < 3; ++comp) \
6576                                 w += getpixel; \
6577                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
6578                         { \
6579                                 ++wsum; \
6580                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6581                                 w = getpixel; \
6582                                 for(comp = 0; comp < 3; ++comp) \
6583                                         avgcolor[comp] += getpixel * w; \
6584                                 avgcolor[3] += w; \
6585                         } \
6586                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
6587                         avgcolor[4] += getpixel; \
6588                 } \
6589                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
6590                         avgcolor[3] = 1; \
6591                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
6592                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
6593                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
6594                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
6595         }
6596
6597 extern cvar_t gl_picmip;
6598 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6599 {
6600         int j;
6601         unsigned char *pixels;
6602         unsigned char *bumppixels;
6603         unsigned char *basepixels = NULL;
6604         int basepixels_width = 0;
6605         int basepixels_height = 0;
6606         skinframe_t *skinframe;
6607         rtexture_t *ddsbase = NULL;
6608         qboolean ddshasalpha = false;
6609         float ddsavgcolor[4];
6610         char basename[MAX_QPATH];
6611         int miplevel = R_PicmipForFlags(textureflags);
6612         int savemiplevel = miplevel;
6613         int mymiplevel;
6614
6615         if (cls.state == ca_dedicated)
6616                 return NULL;
6617
6618         // return an existing skinframe if already loaded
6619         // if loading of the first image fails, don't make a new skinframe as it
6620         // would cause all future lookups of this to be missing
6621         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6622         if (skinframe && skinframe->base)
6623                 return skinframe;
6624
6625         Image_StripImageExtension(name, basename, sizeof(basename));
6626
6627         // check for DDS texture file first
6628         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6629         {
6630                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6631                 if (basepixels == NULL)
6632                         return NULL;
6633         }
6634
6635         // FIXME handle miplevel
6636
6637         if (developer_loading.integer)
6638                 Con_Printf("loading skin \"%s\"\n", name);
6639
6640         // we've got some pixels to store, so really allocate this new texture now
6641         if (!skinframe)
6642                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6643         skinframe->stain = NULL;
6644         skinframe->merged = NULL;
6645         skinframe->base = NULL;
6646         skinframe->pants = NULL;
6647         skinframe->shirt = NULL;
6648         skinframe->nmap = NULL;
6649         skinframe->gloss = NULL;
6650         skinframe->glow = NULL;
6651         skinframe->fog = NULL;
6652         skinframe->reflect = NULL;
6653         skinframe->hasalpha = false;
6654
6655         if (ddsbase)
6656         {
6657                 skinframe->base = ddsbase;
6658                 skinframe->hasalpha = ddshasalpha;
6659                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6660                 if (r_loadfog && skinframe->hasalpha)
6661                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6662                 //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]);
6663         }
6664         else
6665         {
6666                 basepixels_width = image_width;
6667                 basepixels_height = image_height;
6668                 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);
6669                 if (textureflags & TEXF_ALPHA)
6670                 {
6671                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6672                         {
6673                                 if (basepixels[j] < 255)
6674                                 {
6675                                         skinframe->hasalpha = true;
6676                                         break;
6677                                 }
6678                         }
6679                         if (r_loadfog && skinframe->hasalpha)
6680                         {
6681                                 // has transparent pixels
6682                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6683                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6684                                 {
6685                                         pixels[j+0] = 255;
6686                                         pixels[j+1] = 255;
6687                                         pixels[j+2] = 255;
6688                                         pixels[j+3] = basepixels[j+3];
6689                                 }
6690                                 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);
6691                                 Mem_Free(pixels);
6692                         }
6693                 }
6694                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6695                 //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]);
6696                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6697                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6698                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6699                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6700         }
6701
6702         if (r_loaddds)
6703         {
6704                 mymiplevel = savemiplevel;
6705                 if (r_loadnormalmap)
6706                         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);
6707                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6708                 if (r_loadgloss)
6709                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6710                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6711                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6712                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6713         }
6714
6715         // _norm is the name used by tenebrae and has been adopted as standard
6716         if (r_loadnormalmap && skinframe->nmap == NULL)
6717         {
6718                 mymiplevel = savemiplevel;
6719                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6720                 {
6721                         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);
6722                         Mem_Free(pixels);
6723                         pixels = NULL;
6724                 }
6725                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6726                 {
6727                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6728                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6729                         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);
6730                         Mem_Free(pixels);
6731                         Mem_Free(bumppixels);
6732                 }
6733                 else if (r_shadow_bumpscale_basetexture.value > 0)
6734                 {
6735                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6736                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6737                         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);
6738                         Mem_Free(pixels);
6739                 }
6740                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6741                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6742         }
6743
6744         // _luma is supported only for tenebrae compatibility
6745         // _glow is the preferred name
6746         mymiplevel = savemiplevel;
6747         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))))
6748         {
6749                 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);
6750                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6751                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6752                 Mem_Free(pixels);pixels = NULL;
6753         }
6754
6755         mymiplevel = savemiplevel;
6756         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6757         {
6758                 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);
6759                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6760                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6761                 Mem_Free(pixels);
6762                 pixels = NULL;
6763         }
6764
6765         mymiplevel = savemiplevel;
6766         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6767         {
6768                 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);
6769                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6770                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6771                 Mem_Free(pixels);
6772                 pixels = NULL;
6773         }
6774
6775         mymiplevel = savemiplevel;
6776         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6777         {
6778                 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);
6779                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6780                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6781                 Mem_Free(pixels);
6782                 pixels = NULL;
6783         }
6784
6785         mymiplevel = savemiplevel;
6786         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6787         {
6788                 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);
6789                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6790                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6791                 Mem_Free(pixels);
6792                 pixels = NULL;
6793         }
6794
6795         if (basepixels)
6796                 Mem_Free(basepixels);
6797
6798         return skinframe;
6799 }
6800
6801 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6802 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6803 {
6804         int i;
6805         unsigned char *temp1, *temp2;
6806         skinframe_t *skinframe;
6807
6808         if (cls.state == ca_dedicated)
6809                 return NULL;
6810
6811         // if already loaded just return it, otherwise make a new skinframe
6812         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6813         if (skinframe && skinframe->base)
6814                 return skinframe;
6815
6816         skinframe->stain = NULL;
6817         skinframe->merged = NULL;
6818         skinframe->base = NULL;
6819         skinframe->pants = NULL;
6820         skinframe->shirt = NULL;
6821         skinframe->nmap = NULL;
6822         skinframe->gloss = NULL;
6823         skinframe->glow = NULL;
6824         skinframe->fog = NULL;
6825         skinframe->reflect = NULL;
6826         skinframe->hasalpha = false;
6827
6828         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6829         if (!skindata)
6830                 return NULL;
6831
6832         if (developer_loading.integer)
6833                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6834
6835         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6836         {
6837                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6838                 temp2 = temp1 + width * height * 4;
6839                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6840                 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);
6841                 Mem_Free(temp1);
6842         }
6843         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6844         if (textureflags & TEXF_ALPHA)
6845         {
6846                 for (i = 3;i < width * height * 4;i += 4)
6847                 {
6848                         if (skindata[i] < 255)
6849                         {
6850                                 skinframe->hasalpha = true;
6851                                 break;
6852                         }
6853                 }
6854                 if (r_loadfog && skinframe->hasalpha)
6855                 {
6856                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6857                         memcpy(fogpixels, skindata, width * height * 4);
6858                         for (i = 0;i < width * height * 4;i += 4)
6859                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6860                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6861                         Mem_Free(fogpixels);
6862                 }
6863         }
6864
6865         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6866         //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]);
6867
6868         return skinframe;
6869 }
6870
6871 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6872 {
6873         int i;
6874         int featuresmask;
6875         skinframe_t *skinframe;
6876
6877         if (cls.state == ca_dedicated)
6878                 return NULL;
6879
6880         // if already loaded just return it, otherwise make a new skinframe
6881         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6882         if (skinframe && skinframe->base)
6883                 return skinframe;
6884
6885         skinframe->stain = NULL;
6886         skinframe->merged = NULL;
6887         skinframe->base = NULL;
6888         skinframe->pants = NULL;
6889         skinframe->shirt = NULL;
6890         skinframe->nmap = NULL;
6891         skinframe->gloss = NULL;
6892         skinframe->glow = NULL;
6893         skinframe->fog = NULL;
6894         skinframe->reflect = NULL;
6895         skinframe->hasalpha = false;
6896
6897         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6898         if (!skindata)
6899                 return NULL;
6900
6901         if (developer_loading.integer)
6902                 Con_Printf("loading quake skin \"%s\"\n", name);
6903
6904         // 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)
6905         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6906         memcpy(skinframe->qpixels, skindata, width*height);
6907         skinframe->qwidth = width;
6908         skinframe->qheight = height;
6909
6910         featuresmask = 0;
6911         for (i = 0;i < width * height;i++)
6912                 featuresmask |= palette_featureflags[skindata[i]];
6913
6914         skinframe->hasalpha = false;
6915         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6916         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6917         skinframe->qgeneratemerged = true;
6918         skinframe->qgeneratebase = skinframe->qhascolormapping;
6919         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6920
6921         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6922         //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]);
6923
6924         return skinframe;
6925 }
6926
6927 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6928 {
6929         int width;
6930         int height;
6931         unsigned char *skindata;
6932
6933         if (!skinframe->qpixels)
6934                 return;
6935
6936         if (!skinframe->qhascolormapping)
6937                 colormapped = false;
6938
6939         if (colormapped)
6940         {
6941                 if (!skinframe->qgeneratebase)
6942                         return;
6943         }
6944         else
6945         {
6946                 if (!skinframe->qgeneratemerged)
6947                         return;
6948         }
6949
6950         width = skinframe->qwidth;
6951         height = skinframe->qheight;
6952         skindata = skinframe->qpixels;
6953
6954         if (skinframe->qgeneratenmap)
6955         {
6956                 unsigned char *temp1, *temp2;
6957                 skinframe->qgeneratenmap = false;
6958                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6959                 temp2 = temp1 + width * height * 4;
6960                 // use either a custom palette or the quake palette
6961                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6962                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6963                 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);
6964                 Mem_Free(temp1);
6965         }
6966
6967         if (skinframe->qgenerateglow)
6968         {
6969                 skinframe->qgenerateglow = false;
6970                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6971         }
6972
6973         if (colormapped)
6974         {
6975                 skinframe->qgeneratebase = false;
6976                 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);
6977                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6978                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6979         }
6980         else
6981         {
6982                 skinframe->qgeneratemerged = false;
6983                 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);
6984         }
6985
6986         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6987         {
6988                 Mem_Free(skinframe->qpixels);
6989                 skinframe->qpixels = NULL;
6990         }
6991 }
6992
6993 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)
6994 {
6995         int i;
6996         skinframe_t *skinframe;
6997
6998         if (cls.state == ca_dedicated)
6999                 return NULL;
7000
7001         // if already loaded just return it, otherwise make a new skinframe
7002         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
7003         if (skinframe && skinframe->base)
7004                 return skinframe;
7005
7006         skinframe->stain = NULL;
7007         skinframe->merged = NULL;
7008         skinframe->base = NULL;
7009         skinframe->pants = NULL;
7010         skinframe->shirt = NULL;
7011         skinframe->nmap = NULL;
7012         skinframe->gloss = NULL;
7013         skinframe->glow = NULL;
7014         skinframe->fog = NULL;
7015         skinframe->reflect = NULL;
7016         skinframe->hasalpha = false;
7017
7018         // if no data was provided, then clearly the caller wanted to get a blank skinframe
7019         if (!skindata)
7020                 return NULL;
7021
7022         if (developer_loading.integer)
7023                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
7024
7025         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
7026         if (textureflags & TEXF_ALPHA)
7027         {
7028                 for (i = 0;i < width * height;i++)
7029                 {
7030                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
7031                         {
7032                                 skinframe->hasalpha = true;
7033                                 break;
7034                         }
7035                 }
7036                 if (r_loadfog && skinframe->hasalpha)
7037                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
7038         }
7039
7040         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
7041         //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]);
7042
7043         return skinframe;
7044 }
7045
7046 skinframe_t *R_SkinFrame_LoadMissing(void)
7047 {
7048         skinframe_t *skinframe;
7049
7050         if (cls.state == ca_dedicated)
7051                 return NULL;
7052
7053         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
7054         skinframe->stain = NULL;
7055         skinframe->merged = NULL;
7056         skinframe->base = NULL;
7057         skinframe->pants = NULL;
7058         skinframe->shirt = NULL;
7059         skinframe->nmap = NULL;
7060         skinframe->gloss = NULL;
7061         skinframe->glow = NULL;
7062         skinframe->fog = NULL;
7063         skinframe->reflect = NULL;
7064         skinframe->hasalpha = false;
7065
7066         skinframe->avgcolor[0] = rand() / RAND_MAX;
7067         skinframe->avgcolor[1] = rand() / RAND_MAX;
7068         skinframe->avgcolor[2] = rand() / RAND_MAX;
7069         skinframe->avgcolor[3] = 1;
7070
7071         return skinframe;
7072 }
7073
7074 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
7075 typedef struct suffixinfo_s
7076 {
7077         const char *suffix;
7078         qboolean flipx, flipy, flipdiagonal;
7079 }
7080 suffixinfo_t;
7081 static suffixinfo_t suffix[3][6] =
7082 {
7083         {
7084                 {"px",   false, false, false},
7085                 {"nx",   false, false, false},
7086                 {"py",   false, false, false},
7087                 {"ny",   false, false, false},
7088                 {"pz",   false, false, false},
7089                 {"nz",   false, false, false}
7090         },
7091         {
7092                 {"posx", false, false, false},
7093                 {"negx", false, false, false},
7094                 {"posy", false, false, false},
7095                 {"negy", false, false, false},
7096                 {"posz", false, false, false},
7097                 {"negz", false, false, false}
7098         },
7099         {
7100                 {"rt",    true, false,  true},
7101                 {"lf",   false,  true,  true},
7102                 {"ft",    true,  true, false},
7103                 {"bk",   false, false, false},
7104                 {"up",    true, false,  true},
7105                 {"dn",    true, false,  true}
7106         }
7107 };
7108
7109 static int componentorder[4] = {0, 1, 2, 3};
7110
7111 rtexture_t *R_LoadCubemap(const char *basename)
7112 {
7113         int i, j, cubemapsize;
7114         unsigned char *cubemappixels, *image_buffer;
7115         rtexture_t *cubemaptexture;
7116         char name[256];
7117         // must start 0 so the first loadimagepixels has no requested width/height
7118         cubemapsize = 0;
7119         cubemappixels = NULL;
7120         cubemaptexture = NULL;
7121         // keep trying different suffix groups (posx, px, rt) until one loads
7122         for (j = 0;j < 3 && !cubemappixels;j++)
7123         {
7124                 // load the 6 images in the suffix group
7125                 for (i = 0;i < 6;i++)
7126                 {
7127                         // generate an image name based on the base and and suffix
7128                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
7129                         // load it
7130                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
7131                         {
7132                                 // an image loaded, make sure width and height are equal
7133                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
7134                                 {
7135                                         // if this is the first image to load successfully, allocate the cubemap memory
7136                                         if (!cubemappixels && image_width >= 1)
7137                                         {
7138                                                 cubemapsize = image_width;
7139                                                 // note this clears to black, so unavailable sides are black
7140                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
7141                                         }
7142                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
7143                                         if (cubemappixels)
7144                                                 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);
7145                                 }
7146                                 else
7147                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
7148                                 // free the image
7149                                 Mem_Free(image_buffer);
7150                         }
7151                 }
7152         }
7153         // if a cubemap loaded, upload it
7154         if (cubemappixels)
7155         {
7156                 if (developer_loading.integer)
7157                         Con_Printf("loading cubemap \"%s\"\n", basename);
7158
7159                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
7160                 Mem_Free(cubemappixels);
7161         }
7162         else
7163         {
7164                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
7165                 if (developer_loading.integer)
7166                 {
7167                         Con_Printf("(tried tried images ");
7168                         for (j = 0;j < 3;j++)
7169                                 for (i = 0;i < 6;i++)
7170                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
7171                         Con_Print(" and was unable to find any of them).\n");
7172                 }
7173         }
7174         return cubemaptexture;
7175 }
7176
7177 rtexture_t *R_GetCubemap(const char *basename)
7178 {
7179         int i;
7180         for (i = 0;i < r_texture_numcubemaps;i++)
7181                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
7182                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
7183         if (i >= MAX_CUBEMAPS)
7184                 return r_texture_whitecube;
7185         r_texture_numcubemaps++;
7186         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
7187         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
7188         return r_texture_cubemaps[i].texture;
7189 }
7190
7191 void R_FreeCubemaps(void)
7192 {
7193         int i;
7194         for (i = 0;i < r_texture_numcubemaps;i++)
7195         {
7196                 if (developer_loading.integer)
7197                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
7198                 if (r_texture_cubemaps[i].texture)
7199                         R_FreeTexture(r_texture_cubemaps[i].texture);
7200         }
7201         r_texture_numcubemaps = 0;
7202 }
7203
7204 void R_Main_FreeViewCache(void)
7205 {
7206         if (r_refdef.viewcache.entityvisible)
7207                 Mem_Free(r_refdef.viewcache.entityvisible);
7208         if (r_refdef.viewcache.world_pvsbits)
7209                 Mem_Free(r_refdef.viewcache.world_pvsbits);
7210         if (r_refdef.viewcache.world_leafvisible)
7211                 Mem_Free(r_refdef.viewcache.world_leafvisible);
7212         if (r_refdef.viewcache.world_surfacevisible)
7213                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
7214         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
7215 }
7216
7217 void R_Main_ResizeViewCache(void)
7218 {
7219         int numentities = r_refdef.scene.numentities;
7220         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
7221         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
7222         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
7223         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
7224         if (r_refdef.viewcache.maxentities < numentities)
7225         {
7226                 r_refdef.viewcache.maxentities = numentities;
7227                 if (r_refdef.viewcache.entityvisible)
7228                         Mem_Free(r_refdef.viewcache.entityvisible);
7229                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
7230         }
7231         if (r_refdef.viewcache.world_numclusters != numclusters)
7232         {
7233                 r_refdef.viewcache.world_numclusters = numclusters;
7234                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
7235                 if (r_refdef.viewcache.world_pvsbits)
7236                         Mem_Free(r_refdef.viewcache.world_pvsbits);
7237                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
7238         }
7239         if (r_refdef.viewcache.world_numleafs != numleafs)
7240         {
7241                 r_refdef.viewcache.world_numleafs = numleafs;
7242                 if (r_refdef.viewcache.world_leafvisible)
7243                         Mem_Free(r_refdef.viewcache.world_leafvisible);
7244                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
7245         }
7246         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
7247         {
7248                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
7249                 if (r_refdef.viewcache.world_surfacevisible)
7250                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
7251                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
7252         }
7253 }
7254
7255 extern rtexture_t *loadingscreentexture;
7256 void gl_main_start(void)
7257 {
7258         loadingscreentexture = NULL;
7259         r_texture_blanknormalmap = NULL;
7260         r_texture_white = NULL;
7261         r_texture_grey128 = NULL;
7262         r_texture_black = NULL;
7263         r_texture_whitecube = NULL;
7264         r_texture_normalizationcube = NULL;
7265         r_texture_fogattenuation = NULL;
7266         r_texture_fogheighttexture = NULL;
7267         r_texture_gammaramps = NULL;
7268         r_texture_numcubemaps = 0;
7269
7270         r_loaddds = r_texture_dds_load.integer;
7271         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
7272
7273         switch(vid.renderpath)
7274         {
7275         case RENDERPATH_GL20:
7276         case RENDERPATH_CGGL:
7277         case RENDERPATH_D3D9:
7278         case RENDERPATH_D3D10:
7279         case RENDERPATH_D3D11:
7280         case RENDERPATH_SOFT:
7281                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7282                 Cvar_SetValueQuick(&gl_combine, 1);
7283                 Cvar_SetValueQuick(&r_glsl, 1);
7284                 r_loadnormalmap = true;
7285                 r_loadgloss = true;
7286                 r_loadfog = false;
7287                 break;
7288         case RENDERPATH_GL13:
7289                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7290                 Cvar_SetValueQuick(&gl_combine, 1);
7291                 Cvar_SetValueQuick(&r_glsl, 0);
7292                 r_loadnormalmap = false;
7293                 r_loadgloss = false;
7294                 r_loadfog = true;
7295                 break;
7296         case RENDERPATH_GL11:
7297                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
7298                 Cvar_SetValueQuick(&gl_combine, 0);
7299                 Cvar_SetValueQuick(&r_glsl, 0);
7300                 r_loadnormalmap = false;
7301                 r_loadgloss = false;
7302                 r_loadfog = true;
7303                 break;
7304         }
7305
7306         R_AnimCache_Free();
7307         R_FrameData_Reset();
7308
7309         r_numqueries = 0;
7310         r_maxqueries = 0;
7311         memset(r_queries, 0, sizeof(r_queries));
7312
7313         r_qwskincache = NULL;
7314         r_qwskincache_size = 0;
7315
7316         // set up r_skinframe loading system for textures
7317         memset(&r_skinframe, 0, sizeof(r_skinframe));
7318         r_skinframe.loadsequence = 1;
7319         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
7320
7321         r_main_texturepool = R_AllocTexturePool();
7322         R_BuildBlankTextures();
7323         R_BuildNoTexture();
7324         if (vid.support.arb_texture_cube_map)
7325         {
7326                 R_BuildWhiteCube();
7327                 R_BuildNormalizationCube();
7328         }
7329         r_texture_fogattenuation = NULL;
7330         r_texture_fogheighttexture = NULL;
7331         r_texture_gammaramps = NULL;
7332         //r_texture_fogintensity = NULL;
7333         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7334         memset(&r_waterstate, 0, sizeof(r_waterstate));
7335         r_glsl_permutation = NULL;
7336         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7337         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
7338         glslshaderstring = NULL;
7339 #ifdef SUPPORTCG
7340         r_cg_permutation = NULL;
7341         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7342         Mem_ExpandableArray_NewArray(&r_cg_permutationarray, r_main_mempool, sizeof(r_cg_permutation_t), 256);
7343         cgshaderstring = NULL;
7344 #endif
7345 #ifdef SUPPORTD3D
7346         r_hlsl_permutation = NULL;
7347         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7348         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
7349         hlslshaderstring = NULL;
7350 #endif
7351         memset(&r_svbsp, 0, sizeof (r_svbsp));
7352
7353         r_refdef.fogmasktable_density = 0;
7354 }
7355
7356 void gl_main_shutdown(void)
7357 {
7358         R_AnimCache_Free();
7359         R_FrameData_Reset();
7360
7361         R_Main_FreeViewCache();
7362
7363         switch(vid.renderpath)
7364         {
7365         case RENDERPATH_GL11:
7366         case RENDERPATH_GL13:
7367         case RENDERPATH_GL20:
7368         case RENDERPATH_CGGL:
7369                 if (r_maxqueries)
7370                         qglDeleteQueriesARB(r_maxqueries, r_queries);
7371                 break;
7372         case RENDERPATH_D3D9:
7373                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7374                 break;
7375         case RENDERPATH_D3D10:
7376                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7377                 break;
7378         case RENDERPATH_D3D11:
7379                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
7380                 break;
7381         case RENDERPATH_SOFT:
7382                 break;
7383         }
7384
7385         r_numqueries = 0;
7386         r_maxqueries = 0;
7387         memset(r_queries, 0, sizeof(r_queries));
7388
7389         r_qwskincache = NULL;
7390         r_qwskincache_size = 0;
7391
7392         // clear out the r_skinframe state
7393         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
7394         memset(&r_skinframe, 0, sizeof(r_skinframe));
7395
7396         if (r_svbsp.nodes)
7397                 Mem_Free(r_svbsp.nodes);
7398         memset(&r_svbsp, 0, sizeof (r_svbsp));
7399         R_FreeTexturePool(&r_main_texturepool);
7400         loadingscreentexture = NULL;
7401         r_texture_blanknormalmap = NULL;
7402         r_texture_white = NULL;
7403         r_texture_grey128 = NULL;
7404         r_texture_black = NULL;
7405         r_texture_whitecube = NULL;
7406         r_texture_normalizationcube = NULL;
7407         r_texture_fogattenuation = NULL;
7408         r_texture_fogheighttexture = NULL;
7409         r_texture_gammaramps = NULL;
7410         r_texture_numcubemaps = 0;
7411         //r_texture_fogintensity = NULL;
7412         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
7413         memset(&r_waterstate, 0, sizeof(r_waterstate));
7414         R_GLSL_Restart_f();
7415
7416         r_glsl_permutation = NULL;
7417         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
7418         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
7419         glslshaderstring = NULL;
7420 #ifdef SUPPORTCG
7421         r_cg_permutation = NULL;
7422         memset(r_cg_permutationhash, 0, sizeof(r_cg_permutationhash));
7423         Mem_ExpandableArray_FreeArray(&r_cg_permutationarray);
7424         cgshaderstring = NULL;
7425 #endif
7426 #ifdef SUPPORTD3D
7427         r_hlsl_permutation = NULL;
7428         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
7429         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
7430         hlslshaderstring = NULL;
7431 #endif
7432 }
7433
7434 extern void CL_ParseEntityLump(char *entitystring);
7435 void gl_main_newmap(void)
7436 {
7437         // FIXME: move this code to client
7438         char *entities, entname[MAX_QPATH];
7439         if (r_qwskincache)
7440                 Mem_Free(r_qwskincache);
7441         r_qwskincache = NULL;
7442         r_qwskincache_size = 0;
7443         if (cl.worldmodel)
7444         {
7445                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
7446                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
7447                 {
7448                         CL_ParseEntityLump(entities);
7449                         Mem_Free(entities);
7450                         return;
7451                 }
7452                 if (cl.worldmodel->brush.entities)
7453                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
7454         }
7455         R_Main_FreeViewCache();
7456
7457         R_FrameData_Reset();
7458 }
7459
7460 void GL_Main_Init(void)
7461 {
7462         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
7463
7464         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
7465         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
7466         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
7467         if (gamemode == GAME_NEHAHRA)
7468         {
7469                 Cvar_RegisterVariable (&gl_fogenable);
7470                 Cvar_RegisterVariable (&gl_fogdensity);
7471                 Cvar_RegisterVariable (&gl_fogred);
7472                 Cvar_RegisterVariable (&gl_foggreen);
7473                 Cvar_RegisterVariable (&gl_fogblue);
7474                 Cvar_RegisterVariable (&gl_fogstart);
7475                 Cvar_RegisterVariable (&gl_fogend);
7476                 Cvar_RegisterVariable (&gl_skyclip);
7477         }
7478         Cvar_RegisterVariable(&r_motionblur);
7479         Cvar_RegisterVariable(&r_motionblur_maxblur);
7480         Cvar_RegisterVariable(&r_motionblur_bmin);
7481         Cvar_RegisterVariable(&r_motionblur_vmin);
7482         Cvar_RegisterVariable(&r_motionblur_vmax);
7483         Cvar_RegisterVariable(&r_motionblur_vcoeff);
7484         Cvar_RegisterVariable(&r_motionblur_randomize);
7485         Cvar_RegisterVariable(&r_damageblur);
7486         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
7487         Cvar_RegisterVariable(&r_equalize_entities_minambient);
7488         Cvar_RegisterVariable(&r_equalize_entities_by);
7489         Cvar_RegisterVariable(&r_equalize_entities_to);
7490         Cvar_RegisterVariable(&r_depthfirst);
7491         Cvar_RegisterVariable(&r_useinfinitefarclip);
7492         Cvar_RegisterVariable(&r_farclip_base);
7493         Cvar_RegisterVariable(&r_farclip_world);
7494         Cvar_RegisterVariable(&r_nearclip);
7495         Cvar_RegisterVariable(&r_showbboxes);
7496         Cvar_RegisterVariable(&r_showsurfaces);
7497         Cvar_RegisterVariable(&r_showtris);
7498         Cvar_RegisterVariable(&r_shownormals);
7499         Cvar_RegisterVariable(&r_showlighting);
7500         Cvar_RegisterVariable(&r_showshadowvolumes);
7501         Cvar_RegisterVariable(&r_showcollisionbrushes);
7502         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
7503         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
7504         Cvar_RegisterVariable(&r_showdisabledepthtest);
7505         Cvar_RegisterVariable(&r_drawportals);
7506         Cvar_RegisterVariable(&r_drawentities);
7507         Cvar_RegisterVariable(&r_draw2d);
7508         Cvar_RegisterVariable(&r_drawworld);
7509         Cvar_RegisterVariable(&r_cullentities_trace);
7510         Cvar_RegisterVariable(&r_cullentities_trace_samples);
7511         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
7512         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
7513         Cvar_RegisterVariable(&r_cullentities_trace_delay);
7514         Cvar_RegisterVariable(&r_drawviewmodel);
7515         Cvar_RegisterVariable(&r_drawexteriormodel);
7516         Cvar_RegisterVariable(&r_speeds);
7517         Cvar_RegisterVariable(&r_fullbrights);
7518         Cvar_RegisterVariable(&r_wateralpha);
7519         Cvar_RegisterVariable(&r_dynamic);
7520         Cvar_RegisterVariable(&r_fakelight);
7521         Cvar_RegisterVariable(&r_fakelight_intensity);
7522         Cvar_RegisterVariable(&r_fullbright);
7523         Cvar_RegisterVariable(&r_shadows);
7524         Cvar_RegisterVariable(&r_shadows_darken);
7525         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
7526         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
7527         Cvar_RegisterVariable(&r_shadows_throwdistance);
7528         Cvar_RegisterVariable(&r_shadows_throwdirection);
7529         Cvar_RegisterVariable(&r_shadows_focus);
7530         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
7531         Cvar_RegisterVariable(&r_q1bsp_skymasking);
7532         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
7533         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
7534         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
7535         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
7536         Cvar_RegisterVariable(&r_fog_exp2);
7537         Cvar_RegisterVariable(&r_drawfog);
7538         Cvar_RegisterVariable(&r_transparentdepthmasking);
7539         Cvar_RegisterVariable(&r_texture_dds_load);
7540         Cvar_RegisterVariable(&r_texture_dds_save);
7541         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
7542         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
7543         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
7544         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
7545         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
7546         Cvar_RegisterVariable(&r_textureunits);
7547         Cvar_RegisterVariable(&gl_combine);
7548         Cvar_RegisterVariable(&r_glsl);
7549         Cvar_RegisterVariable(&r_glsl_deluxemapping);
7550         Cvar_RegisterVariable(&r_glsl_offsetmapping);
7551         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
7552         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
7553         Cvar_RegisterVariable(&r_glsl_postprocess);
7554         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
7555         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
7556         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
7557         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
7558         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
7559         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
7560         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
7561         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
7562
7563         Cvar_RegisterVariable(&r_water);
7564         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
7565         Cvar_RegisterVariable(&r_water_clippingplanebias);
7566         Cvar_RegisterVariable(&r_water_refractdistort);
7567         Cvar_RegisterVariable(&r_water_reflectdistort);
7568         Cvar_RegisterVariable(&r_water_scissormode);
7569         Cvar_RegisterVariable(&r_lerpsprites);
7570         Cvar_RegisterVariable(&r_lerpmodels);
7571         Cvar_RegisterVariable(&r_lerplightstyles);
7572         Cvar_RegisterVariable(&r_waterscroll);
7573         Cvar_RegisterVariable(&r_bloom);
7574         Cvar_RegisterVariable(&r_bloom_colorscale);
7575         Cvar_RegisterVariable(&r_bloom_brighten);
7576         Cvar_RegisterVariable(&r_bloom_blur);
7577         Cvar_RegisterVariable(&r_bloom_resolution);
7578         Cvar_RegisterVariable(&r_bloom_colorexponent);
7579         Cvar_RegisterVariable(&r_bloom_colorsubtract);
7580         Cvar_RegisterVariable(&r_hdr);
7581         Cvar_RegisterVariable(&r_hdr_scenebrightness);
7582         Cvar_RegisterVariable(&r_hdr_glowintensity);
7583         Cvar_RegisterVariable(&r_hdr_range);
7584         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
7585         Cvar_RegisterVariable(&developer_texturelogging);
7586         Cvar_RegisterVariable(&gl_lightmaps);
7587         Cvar_RegisterVariable(&r_test);
7588         Cvar_RegisterVariable(&r_glsl_saturation);
7589         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
7590         Cvar_RegisterVariable(&r_framedatasize);
7591         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
7592                 Cvar_SetValue("r_fullbrights", 0);
7593         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
7594
7595         Cvar_RegisterVariable(&r_track_sprites);
7596         Cvar_RegisterVariable(&r_track_sprites_flags);
7597         Cvar_RegisterVariable(&r_track_sprites_scalew);
7598         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7599         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7600         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7601         Cvar_RegisterVariable(&r_overheadsprites_scalex);
7602         Cvar_RegisterVariable(&r_overheadsprites_scaley);
7603 }
7604
7605 extern void R_Textures_Init(void);
7606 extern void GL_Draw_Init(void);
7607 extern void GL_Main_Init(void);
7608 extern void R_Shadow_Init(void);
7609 extern void R_Sky_Init(void);
7610 extern void GL_Surf_Init(void);
7611 extern void R_Particles_Init(void);
7612 extern void R_Explosion_Init(void);
7613 extern void gl_backend_init(void);
7614 extern void Sbar_Init(void);
7615 extern void R_LightningBeams_Init(void);
7616 extern void Mod_RenderInit(void);
7617 extern void Font_Init(void);
7618
7619 void Render_Init(void)
7620 {
7621         gl_backend_init();
7622         R_Textures_Init();
7623         GL_Main_Init();
7624         Font_Init();
7625         GL_Draw_Init();
7626         R_Shadow_Init();
7627         R_Sky_Init();
7628         GL_Surf_Init();
7629         Sbar_Init();
7630         R_Particles_Init();
7631         R_Explosion_Init();
7632         R_LightningBeams_Init();
7633         Mod_RenderInit();
7634 }
7635
7636 /*
7637 ===============
7638 GL_Init
7639 ===============
7640 */
7641 extern char *ENGINE_EXTENSIONS;
7642 void GL_Init (void)
7643 {
7644         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7645         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7646         gl_version = (const char *)qglGetString(GL_VERSION);
7647         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7648
7649         if (!gl_extensions)
7650                 gl_extensions = "";
7651         if (!gl_platformextensions)
7652                 gl_platformextensions = "";
7653
7654         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7655         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7656         Con_Printf("GL_VERSION: %s\n", gl_version);
7657         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7658         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7659
7660         VID_CheckExtensions();
7661
7662         // LordHavoc: report supported extensions
7663         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7664
7665         // clear to black (loading plaque will be seen over this)
7666         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7667 }
7668
7669 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7670 {
7671         int i;
7672         mplane_t *p;
7673         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7674         {
7675                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7676                 if (i == 4)
7677                         continue;
7678                 p = r_refdef.view.frustum + i;
7679                 switch(p->signbits)
7680                 {
7681                 default:
7682                 case 0:
7683                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7684                                 return true;
7685                         break;
7686                 case 1:
7687                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7688                                 return true;
7689                         break;
7690                 case 2:
7691                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7692                                 return true;
7693                         break;
7694                 case 3:
7695                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7696                                 return true;
7697                         break;
7698                 case 4:
7699                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7700                                 return true;
7701                         break;
7702                 case 5:
7703                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7704                                 return true;
7705                         break;
7706                 case 6:
7707                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7708                                 return true;
7709                         break;
7710                 case 7:
7711                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7712                                 return true;
7713                         break;
7714                 }
7715         }
7716         return false;
7717 }
7718
7719 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7720 {
7721         int i;
7722         const mplane_t *p;
7723         for (i = 0;i < numplanes;i++)
7724         {
7725                 p = planes + i;
7726                 switch(p->signbits)
7727                 {
7728                 default:
7729                 case 0:
7730                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7731                                 return true;
7732                         break;
7733                 case 1:
7734                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7735                                 return true;
7736                         break;
7737                 case 2:
7738                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7739                                 return true;
7740                         break;
7741                 case 3:
7742                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7743                                 return true;
7744                         break;
7745                 case 4:
7746                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7747                                 return true;
7748                         break;
7749                 case 5:
7750                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7751                                 return true;
7752                         break;
7753                 case 6:
7754                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7755                                 return true;
7756                         break;
7757                 case 7:
7758                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7759                                 return true;
7760                         break;
7761                 }
7762         }
7763         return false;
7764 }
7765
7766 //==================================================================================
7767
7768 // LordHavoc: this stores temporary data used within the same frame
7769
7770 typedef struct r_framedata_mem_s
7771 {
7772         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7773         size_t size; // how much usable space
7774         size_t current; // how much space in use
7775         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7776         size_t wantedsize; // how much space was allocated
7777         unsigned char *data; // start of real data (16byte aligned)
7778 }
7779 r_framedata_mem_t;
7780
7781 static r_framedata_mem_t *r_framedata_mem;
7782
7783 void R_FrameData_Reset(void)
7784 {
7785         while (r_framedata_mem)
7786         {
7787                 r_framedata_mem_t *next = r_framedata_mem->purge;
7788                 Mem_Free(r_framedata_mem);
7789                 r_framedata_mem = next;
7790         }
7791 }
7792
7793 void R_FrameData_Resize(void)
7794 {
7795         size_t wantedsize;
7796         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7797         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7798         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7799         {
7800                 r_framedata_mem_t *newmem = Mem_Alloc(r_main_mempool, wantedsize);
7801                 newmem->wantedsize = wantedsize;
7802                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7803                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7804                 newmem->current = 0;
7805                 newmem->mark = 0;
7806                 newmem->purge = r_framedata_mem;
7807                 r_framedata_mem = newmem;
7808         }
7809 }
7810
7811 void R_FrameData_NewFrame(void)
7812 {
7813         R_FrameData_Resize();
7814         if (!r_framedata_mem)
7815                 return;
7816         // if we ran out of space on the last frame, free the old memory now
7817         while (r_framedata_mem->purge)
7818         {
7819                 // repeatedly remove the second item in the list, leaving only head
7820                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7821                 Mem_Free(r_framedata_mem->purge);
7822                 r_framedata_mem->purge = next;
7823         }
7824         // reset the current mem pointer
7825         r_framedata_mem->current = 0;
7826         r_framedata_mem->mark = 0;
7827 }
7828
7829 void *R_FrameData_Alloc(size_t size)
7830 {
7831         void *data;
7832
7833         // align to 16 byte boundary - the data pointer is already aligned, so we
7834         // only need to ensure the size of every allocation is also aligned
7835         size = (size + 15) & ~15;
7836
7837         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7838         {
7839                 // emergency - we ran out of space, allocate more memory
7840                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7841                 R_FrameData_Resize();
7842         }
7843
7844         data = r_framedata_mem->data + r_framedata_mem->current;
7845         r_framedata_mem->current += size;
7846
7847         // count the usage for stats
7848         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7849         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7850
7851         return (void *)data;
7852 }
7853
7854 void *R_FrameData_Store(size_t size, void *data)
7855 {
7856         void *d = R_FrameData_Alloc(size);
7857         if (d && data)
7858                 memcpy(d, data, size);
7859         return d;
7860 }
7861
7862 void R_FrameData_SetMark(void)
7863 {
7864         if (!r_framedata_mem)
7865                 return;
7866         r_framedata_mem->mark = r_framedata_mem->current;
7867 }
7868
7869 void R_FrameData_ReturnToMark(void)
7870 {
7871         if (!r_framedata_mem)
7872                 return;
7873         r_framedata_mem->current = r_framedata_mem->mark;
7874 }
7875
7876 //==================================================================================
7877
7878 // LordHavoc: animcache originally written by Echon, rewritten since then
7879
7880 /**
7881  * Animation cache prevents re-generating mesh data for an animated model
7882  * multiple times in one frame for lighting, shadowing, reflections, etc.
7883  */
7884
7885 void R_AnimCache_Free(void)
7886 {
7887 }
7888
7889 void R_AnimCache_ClearCache(void)
7890 {
7891         int i;
7892         entity_render_t *ent;
7893
7894         for (i = 0;i < r_refdef.scene.numentities;i++)
7895         {
7896                 ent = r_refdef.scene.entities[i];
7897                 ent->animcache_vertex3f = NULL;
7898                 ent->animcache_normal3f = NULL;
7899                 ent->animcache_svector3f = NULL;
7900                 ent->animcache_tvector3f = NULL;
7901                 ent->animcache_vertexmesh = NULL;
7902                 ent->animcache_vertex3fbuffer = NULL;
7903                 ent->animcache_vertexmeshbuffer = NULL;
7904         }
7905 }
7906
7907 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7908 {
7909         int i;
7910
7911         // check if we need the meshbuffers
7912         if (!vid.useinterleavedarrays)
7913                 return;
7914
7915         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7916                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7917         // TODO: upload vertex3f buffer?
7918         if (ent->animcache_vertexmesh)
7919         {
7920                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7921                 for (i = 0;i < numvertices;i++)
7922                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7923                 if (ent->animcache_svector3f)
7924                         for (i = 0;i < numvertices;i++)
7925                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7926                 if (ent->animcache_tvector3f)
7927                         for (i = 0;i < numvertices;i++)
7928                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7929                 if (ent->animcache_normal3f)
7930                         for (i = 0;i < numvertices;i++)
7931                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7932                 // TODO: upload vertexmeshbuffer?
7933         }
7934 }
7935
7936 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7937 {
7938         dp_model_t *model = ent->model;
7939         int numvertices;
7940         // see if it's already cached this frame
7941         if (ent->animcache_vertex3f)
7942         {
7943                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7944                 if (wantnormals || wanttangents)
7945                 {
7946                         if (ent->animcache_normal3f)
7947                                 wantnormals = false;
7948                         if (ent->animcache_svector3f)
7949                                 wanttangents = false;
7950                         if (wantnormals || wanttangents)
7951                         {
7952                                 numvertices = model->surfmesh.num_vertices;
7953                                 if (wantnormals)
7954                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7955                                 if (wanttangents)
7956                                 {
7957                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7958                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7959                                 }
7960                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7961                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7962                         }
7963                 }
7964         }
7965         else
7966         {
7967                 // see if this ent is worth caching
7968                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7969                         return false;
7970                 // get some memory for this entity and generate mesh data
7971                 numvertices = model->surfmesh.num_vertices;
7972                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7973                 if (wantnormals)
7974                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7975                 if (wanttangents)
7976                 {
7977                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7978                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7979                 }
7980                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7981                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7982         }
7983         return true;
7984 }
7985
7986 void R_AnimCache_CacheVisibleEntities(void)
7987 {
7988         int i;
7989         qboolean wantnormals = true;
7990         qboolean wanttangents = !r_showsurfaces.integer;
7991
7992         switch(vid.renderpath)
7993         {
7994         case RENDERPATH_GL20:
7995         case RENDERPATH_CGGL:
7996         case RENDERPATH_D3D9:
7997         case RENDERPATH_D3D10:
7998         case RENDERPATH_D3D11:
7999                 break;
8000         case RENDERPATH_GL13:
8001         case RENDERPATH_GL11:
8002                 wanttangents = false;
8003                 break;
8004         case RENDERPATH_SOFT:
8005                 break;
8006         }
8007
8008         if (r_shownormals.integer)
8009                 wanttangents = wantnormals = true;
8010
8011         // TODO: thread this
8012         // NOTE: R_PrepareRTLights() also caches entities
8013
8014         for (i = 0;i < r_refdef.scene.numentities;i++)
8015                 if (r_refdef.viewcache.entityvisible[i])
8016                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
8017 }
8018
8019 //==================================================================================
8020
8021 static void R_View_UpdateEntityLighting (void)
8022 {
8023         int i;
8024         entity_render_t *ent;
8025         vec3_t tempdiffusenormal, avg;
8026         vec_t f, fa, fd, fdd;
8027         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
8028
8029         for (i = 0;i < r_refdef.scene.numentities;i++)
8030         {
8031                 ent = r_refdef.scene.entities[i];
8032
8033                 // skip unseen models
8034                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
8035                         continue;
8036
8037                 // skip bsp models
8038                 if (ent->model && ent->model->brush.num_leafs)
8039                 {
8040                         // TODO: use modellight for r_ambient settings on world?
8041                         VectorSet(ent->modellight_ambient, 0, 0, 0);
8042                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
8043                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
8044                         continue;
8045                 }
8046
8047                 // fetch the lighting from the worldmodel data
8048                 VectorClear(ent->modellight_ambient);
8049                 VectorClear(ent->modellight_diffuse);
8050                 VectorClear(tempdiffusenormal);
8051                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
8052                 {
8053                         vec3_t org;
8054                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
8055
8056                         // complete lightning for lit sprites
8057                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
8058                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
8059                         {
8060                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
8061                                         org[2] = org[2] + r_overheadsprites_pushback.value;
8062                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, ent->modellight_lightdir, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
8063                         }
8064                         else
8065                                 r_refdef.scene.worldmodel->brush.LightPoint(r_refdef.scene.worldmodel, org, ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal);
8066
8067                         if(ent->flags & RENDER_EQUALIZE)
8068                         {
8069                                 // first fix up ambient lighting...
8070                                 if(r_equalize_entities_minambient.value > 0)
8071                                 {
8072                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8073                                         if(fd > 0)
8074                                         {
8075                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
8076                                                 if(fa < r_equalize_entities_minambient.value * fd)
8077                                                 {
8078                                                         // solve:
8079                                                         //   fa'/fd' = minambient
8080                                                         //   fa'+0.25*fd' = fa+0.25*fd
8081                                                         //   ...
8082                                                         //   fa' = fd' * minambient
8083                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
8084                                                         //   ...
8085                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
8086                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
8087                                                         //   ...
8088                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
8089                                                         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
8090                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
8091                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
8092                                                 }
8093                                         }
8094                                 }
8095
8096                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
8097                                 {
8098                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
8099                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
8100                                         f = fa + 0.25 * fd;
8101                                         if(f > 0)
8102                                         {
8103                                                 // adjust brightness and saturation to target
8104                                                 avg[0] = avg[1] = avg[2] = fa / f;
8105                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
8106                                                 avg[0] = avg[1] = avg[2] = fd / f;
8107                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
8108                                         }
8109                                 }
8110                         }
8111                 }
8112                 else // highly rare
8113                         VectorSet(ent->modellight_ambient, 1, 1, 1);
8114
8115                 // move the light direction into modelspace coordinates for lighting code
8116                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
8117                 if(VectorLength2(ent->modellight_lightdir) == 0)
8118                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
8119                 VectorNormalize(ent->modellight_lightdir);
8120         }
8121 }
8122
8123 #define MAX_LINEOFSIGHTTRACES 64
8124
8125 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
8126 {
8127         int i;
8128         vec3_t boxmins, boxmaxs;
8129         vec3_t start;
8130         vec3_t end;
8131         dp_model_t *model = r_refdef.scene.worldmodel;
8132
8133         if (!model || !model->brush.TraceLineOfSight)
8134                 return true;
8135
8136         // expand the box a little
8137         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
8138         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
8139         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
8140         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
8141         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
8142         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
8143
8144         // return true if eye is inside enlarged box
8145         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
8146                 return true;
8147
8148         // try center
8149         VectorCopy(eye, start);
8150         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
8151         if (model->brush.TraceLineOfSight(model, start, end))
8152                 return true;
8153
8154         // try various random positions
8155         for (i = 0;i < numsamples;i++)
8156         {
8157                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
8158                 if (model->brush.TraceLineOfSight(model, start, end))
8159                         return true;
8160         }
8161
8162         return false;
8163 }
8164
8165
8166 static void R_View_UpdateEntityVisible (void)
8167 {
8168         int i;
8169         int renderimask;
8170         int samples;
8171         entity_render_t *ent;
8172
8173         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8174                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
8175                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
8176                 :                                                          RENDER_EXTERIORMODEL;
8177         if (!r_drawviewmodel.integer)
8178                 renderimask |= RENDER_VIEWMODEL;
8179         if (!r_drawexteriormodel.integer)
8180                 renderimask |= RENDER_EXTERIORMODEL;
8181         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
8182         {
8183                 // worldmodel can check visibility
8184                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
8185                 for (i = 0;i < r_refdef.scene.numentities;i++)
8186                 {
8187                         ent = r_refdef.scene.entities[i];
8188                         if (!(ent->flags & renderimask))
8189                         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)))
8190                         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))
8191                                 r_refdef.viewcache.entityvisible[i] = true;
8192                 }
8193                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
8194                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
8195                 {
8196                         for (i = 0;i < r_refdef.scene.numentities;i++)
8197                         {
8198                                 ent = r_refdef.scene.entities[i];
8199                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
8200                                 {
8201                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
8202                                         if (samples < 0)
8203                                                 continue; // temp entities do pvs only
8204                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
8205                                                 ent->last_trace_visibility = realtime;
8206                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
8207                                                 r_refdef.viewcache.entityvisible[i] = 0;
8208                                 }
8209                         }
8210                 }
8211         }
8212         else
8213         {
8214                 // no worldmodel or it can't check visibility
8215                 for (i = 0;i < r_refdef.scene.numentities;i++)
8216                 {
8217                         ent = r_refdef.scene.entities[i];
8218                         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));
8219                 }
8220         }
8221 }
8222
8223 /// only used if skyrendermasked, and normally returns false
8224 int R_DrawBrushModelsSky (void)
8225 {
8226         int i, sky;
8227         entity_render_t *ent;
8228
8229         sky = false;
8230         for (i = 0;i < r_refdef.scene.numentities;i++)
8231         {
8232                 if (!r_refdef.viewcache.entityvisible[i])
8233                         continue;
8234                 ent = r_refdef.scene.entities[i];
8235                 if (!ent->model || !ent->model->DrawSky)
8236                         continue;
8237                 ent->model->DrawSky(ent);
8238                 sky = true;
8239         }
8240         return sky;
8241 }
8242
8243 static void R_DrawNoModel(entity_render_t *ent);
8244 static void R_DrawModels(void)
8245 {
8246         int i;
8247         entity_render_t *ent;
8248
8249         for (i = 0;i < r_refdef.scene.numentities;i++)
8250         {
8251                 if (!r_refdef.viewcache.entityvisible[i])
8252                         continue;
8253                 ent = r_refdef.scene.entities[i];
8254                 r_refdef.stats.entities++;
8255                 if (ent->model && ent->model->Draw != NULL)
8256                         ent->model->Draw(ent);
8257                 else
8258                         R_DrawNoModel(ent);
8259         }
8260 }
8261
8262 static void R_DrawModelsDepth(void)
8263 {
8264         int i;
8265         entity_render_t *ent;
8266
8267         for (i = 0;i < r_refdef.scene.numentities;i++)
8268         {
8269                 if (!r_refdef.viewcache.entityvisible[i])
8270                         continue;
8271                 ent = r_refdef.scene.entities[i];
8272                 if (ent->model && ent->model->DrawDepth != NULL)
8273                         ent->model->DrawDepth(ent);
8274         }
8275 }
8276
8277 static void R_DrawModelsDebug(void)
8278 {
8279         int i;
8280         entity_render_t *ent;
8281
8282         for (i = 0;i < r_refdef.scene.numentities;i++)
8283         {
8284                 if (!r_refdef.viewcache.entityvisible[i])
8285                         continue;
8286                 ent = r_refdef.scene.entities[i];
8287                 if (ent->model && ent->model->DrawDebug != NULL)
8288                         ent->model->DrawDebug(ent);
8289         }
8290 }
8291
8292 static void R_DrawModelsAddWaterPlanes(void)
8293 {
8294         int i;
8295         entity_render_t *ent;
8296
8297         for (i = 0;i < r_refdef.scene.numentities;i++)
8298         {
8299                 if (!r_refdef.viewcache.entityvisible[i])
8300                         continue;
8301                 ent = r_refdef.scene.entities[i];
8302                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
8303                         ent->model->DrawAddWaterPlanes(ent);
8304         }
8305 }
8306
8307 static void R_View_SetFrustum(const int *scissor)
8308 {
8309         int i;
8310         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
8311         vec3_t forward, left, up, origin, v;
8312
8313         if(scissor)
8314         {
8315                 // flipped x coordinates (because x points left here)
8316                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8317                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
8318
8319                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
8320                 switch(vid.renderpath)
8321                 {
8322                         case RENDERPATH_D3D9:
8323                         case RENDERPATH_D3D10:
8324                         case RENDERPATH_D3D11:
8325                         case RENDERPATH_SOFT:
8326                                 // non-flipped y coordinates
8327                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8328                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8329                                 break;
8330                         case RENDERPATH_GL11:
8331                         case RENDERPATH_GL13:
8332                         case RENDERPATH_GL20:
8333                         case RENDERPATH_CGGL:
8334                                 // non-flipped y coordinates
8335                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8336                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
8337                                 break;
8338                 }
8339         }
8340
8341         // we can't trust r_refdef.view.forward and friends in reflected scenes
8342         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
8343
8344 #if 0
8345         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
8346         r_refdef.view.frustum[0].normal[1] = 0 - 0;
8347         r_refdef.view.frustum[0].normal[2] = -1 - 0;
8348         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
8349         r_refdef.view.frustum[1].normal[1] = 0 + 0;
8350         r_refdef.view.frustum[1].normal[2] = -1 + 0;
8351         r_refdef.view.frustum[2].normal[0] = 0 - 0;
8352         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
8353         r_refdef.view.frustum[2].normal[2] = -1 - 0;
8354         r_refdef.view.frustum[3].normal[0] = 0 + 0;
8355         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
8356         r_refdef.view.frustum[3].normal[2] = -1 + 0;
8357 #endif
8358
8359 #if 0
8360         zNear = r_refdef.nearclip;
8361         nudge = 1.0 - 1.0 / (1<<23);
8362         r_refdef.view.frustum[4].normal[0] = 0 - 0;
8363         r_refdef.view.frustum[4].normal[1] = 0 - 0;
8364         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
8365         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
8366         r_refdef.view.frustum[5].normal[0] = 0 + 0;
8367         r_refdef.view.frustum[5].normal[1] = 0 + 0;
8368         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
8369         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
8370 #endif
8371
8372
8373
8374 #if 0
8375         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
8376         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
8377         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
8378         r_refdef.view.frustum[0].dist = m[15] - m[12];
8379
8380         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
8381         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
8382         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
8383         r_refdef.view.frustum[1].dist = m[15] + m[12];
8384
8385         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
8386         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
8387         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
8388         r_refdef.view.frustum[2].dist = m[15] - m[13];
8389
8390         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
8391         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
8392         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
8393         r_refdef.view.frustum[3].dist = m[15] + m[13];
8394
8395         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
8396         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
8397         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
8398         r_refdef.view.frustum[4].dist = m[15] - m[14];
8399
8400         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
8401         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
8402         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
8403         r_refdef.view.frustum[5].dist = m[15] + m[14];
8404 #endif
8405
8406         if (r_refdef.view.useperspective)
8407         {
8408                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
8409                 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]);
8410                 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]);
8411                 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]);
8412                 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]);
8413
8414                 // then the normals from the corners relative to origin
8415                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
8416                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
8417                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
8418                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
8419
8420                 // in a NORMAL view, forward cross left == up
8421                 // in a REFLECTED view, forward cross left == down
8422                 // so our cross products above need to be adjusted for a left handed coordinate system
8423                 CrossProduct(forward, left, v);
8424                 if(DotProduct(v, up) < 0)
8425                 {
8426                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
8427                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
8428                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
8429                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
8430                 }
8431
8432                 // Leaving those out was a mistake, those were in the old code, and they
8433                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
8434                 // I couldn't reproduce it after adding those normalizations. --blub
8435                 VectorNormalize(r_refdef.view.frustum[0].normal);
8436                 VectorNormalize(r_refdef.view.frustum[1].normal);
8437                 VectorNormalize(r_refdef.view.frustum[2].normal);
8438                 VectorNormalize(r_refdef.view.frustum[3].normal);
8439
8440                 // make the corners absolute
8441                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
8442                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
8443                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
8444                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
8445
8446                 // one more normal
8447                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8448
8449                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
8450                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
8451                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
8452                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
8453                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8454         }
8455         else
8456         {
8457                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
8458                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
8459                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
8460                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
8461                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
8462                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
8463                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
8464                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
8465                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
8466                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
8467         }
8468         r_refdef.view.numfrustumplanes = 5;
8469
8470         if (r_refdef.view.useclipplane)
8471         {
8472                 r_refdef.view.numfrustumplanes = 6;
8473                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
8474         }
8475
8476         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
8477                 PlaneClassify(r_refdef.view.frustum + i);
8478
8479         // LordHavoc: note to all quake engine coders, Quake had a special case
8480         // for 90 degrees which assumed a square view (wrong), so I removed it,
8481         // Quake2 has it disabled as well.
8482
8483         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
8484         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
8485         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
8486         //PlaneClassify(&frustum[0]);
8487
8488         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
8489         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
8490         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
8491         //PlaneClassify(&frustum[1]);
8492
8493         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
8494         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
8495         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
8496         //PlaneClassify(&frustum[2]);
8497
8498         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
8499         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
8500         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
8501         //PlaneClassify(&frustum[3]);
8502
8503         // nearclip plane
8504         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
8505         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
8506         //PlaneClassify(&frustum[4]);
8507 }
8508
8509 void R_View_UpdateWithScissor(const int *myscissor)
8510 {
8511         R_Main_ResizeViewCache();
8512         R_View_SetFrustum(myscissor);
8513         R_View_WorldVisibility(r_refdef.view.useclipplane);
8514         R_View_UpdateEntityVisible();
8515         R_View_UpdateEntityLighting();
8516 }
8517
8518 void R_View_Update(void)
8519 {
8520         R_Main_ResizeViewCache();
8521         R_View_SetFrustum(NULL);
8522         R_View_WorldVisibility(r_refdef.view.useclipplane);
8523         R_View_UpdateEntityVisible();
8524         R_View_UpdateEntityLighting();
8525 }
8526
8527 void R_SetupView(qboolean allowwaterclippingplane)
8528 {
8529         const float *customclipplane = NULL;
8530         float plane[4];
8531         if (r_refdef.view.useclipplane && allowwaterclippingplane)
8532         {
8533                 // LordHavoc: couldn't figure out how to make this approach the
8534                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
8535                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
8536                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
8537                         dist = r_refdef.view.clipplane.dist;
8538                 plane[0] = r_refdef.view.clipplane.normal[0];
8539                 plane[1] = r_refdef.view.clipplane.normal[1];
8540                 plane[2] = r_refdef.view.clipplane.normal[2];
8541                 plane[3] = dist;
8542                 customclipplane = plane;
8543         }
8544
8545         if (!r_refdef.view.useperspective)
8546                 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);
8547         else if (vid.stencil && r_useinfinitefarclip.integer)
8548                 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);
8549         else
8550                 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);
8551         R_SetViewport(&r_refdef.view.viewport);
8552 }
8553
8554 void R_EntityMatrix(const matrix4x4_t *matrix)
8555 {
8556         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
8557         {
8558                 gl_modelmatrixchanged = false;
8559                 gl_modelmatrix = *matrix;
8560                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
8561                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
8562                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
8563                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
8564                 CHECKGLERROR
8565                 switch(vid.renderpath)
8566                 {
8567                 case RENDERPATH_D3D9:
8568 #ifdef SUPPORTD3D
8569                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8570                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8571 #endif
8572                         break;
8573                 case RENDERPATH_D3D10:
8574                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8575                         break;
8576                 case RENDERPATH_D3D11:
8577                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8578                         break;
8579                 case RENDERPATH_GL20:
8580                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8581                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fvARB(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8582                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8583                         break;
8584                 case RENDERPATH_CGGL:
8585 #ifdef SUPPORTCG
8586                         CHECKCGERROR
8587                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewProjectionMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewProjectionMatrix, gl_modelviewprojection16f);CHECKCGERROR
8588                         if (r_cg_permutation && r_cg_permutation->vp_ModelViewMatrix) cgGLSetMatrixParameterfc(r_cg_permutation->vp_ModelViewMatrix, gl_modelview16f);CHECKCGERROR
8589                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8590 #endif
8591                         break;
8592                 case RENDERPATH_GL13:
8593                 case RENDERPATH_GL11:
8594                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8595                         break;
8596                 case RENDERPATH_SOFT:
8597                         DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
8598                         DPSOFTRAST_UniformMatrix4fvARB(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
8599                         break;
8600                 }
8601         }
8602 }
8603
8604 void R_ResetViewRendering2D(void)
8605 {
8606         r_viewport_t viewport;
8607         DrawQ_Finish();
8608
8609         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8610         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);
8611         R_SetViewport(&viewport);
8612         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8613         GL_Color(1, 1, 1, 1);
8614         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8615         GL_BlendFunc(GL_ONE, GL_ZERO);
8616         GL_AlphaTest(false);
8617         GL_ScissorTest(false);
8618         GL_DepthMask(false);
8619         GL_DepthRange(0, 1);
8620         GL_DepthTest(false);
8621         GL_DepthFunc(GL_LEQUAL);
8622         R_EntityMatrix(&identitymatrix);
8623         R_Mesh_ResetTextureState();
8624         GL_PolygonOffset(0, 0);
8625         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8626         switch(vid.renderpath)
8627         {
8628         case RENDERPATH_GL11:
8629         case RENDERPATH_GL13:
8630         case RENDERPATH_GL20:
8631         case RENDERPATH_CGGL:
8632                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8633                 break;
8634         case RENDERPATH_D3D9:
8635         case RENDERPATH_D3D10:
8636         case RENDERPATH_D3D11:
8637         case RENDERPATH_SOFT:
8638                 break;
8639         }
8640         GL_CullFace(GL_NONE);
8641 }
8642
8643 void R_ResetViewRendering3D(void)
8644 {
8645         DrawQ_Finish();
8646
8647         R_SetupView(true);
8648         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8649         GL_Color(1, 1, 1, 1);
8650         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8651         GL_BlendFunc(GL_ONE, GL_ZERO);
8652         GL_AlphaTest(false);
8653         GL_ScissorTest(true);
8654         GL_DepthMask(true);
8655         GL_DepthRange(0, 1);
8656         GL_DepthTest(true);
8657         GL_DepthFunc(GL_LEQUAL);
8658         R_EntityMatrix(&identitymatrix);
8659         R_Mesh_ResetTextureState();
8660         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8661         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8662         switch(vid.renderpath)
8663         {
8664         case RENDERPATH_GL11:
8665         case RENDERPATH_GL13:
8666         case RENDERPATH_GL20:
8667         case RENDERPATH_CGGL:
8668                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8669                 break;
8670         case RENDERPATH_D3D9:
8671         case RENDERPATH_D3D10:
8672         case RENDERPATH_D3D11:
8673         case RENDERPATH_SOFT:
8674                 break;
8675         }
8676         GL_CullFace(r_refdef.view.cullface_back);
8677 }
8678
8679 /*
8680 ================
8681 R_RenderView_UpdateViewVectors
8682 ================
8683 */
8684 static void R_RenderView_UpdateViewVectors(void)
8685 {
8686         // break apart the view matrix into vectors for various purposes
8687         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8688         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8689         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8690         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8691         // make an inverted copy of the view matrix for tracking sprites
8692         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8693 }
8694
8695 void R_RenderScene(void);
8696 void R_RenderWaterPlanes(void);
8697
8698 static void R_Water_StartFrame(void)
8699 {
8700         int i;
8701         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8702         r_waterstate_waterplane_t *p;
8703
8704         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8705                 return;
8706
8707         switch(vid.renderpath)
8708         {
8709         case RENDERPATH_GL20:
8710         case RENDERPATH_CGGL:
8711         case RENDERPATH_D3D9:
8712         case RENDERPATH_D3D10:
8713         case RENDERPATH_D3D11:
8714         case RENDERPATH_SOFT:
8715                 break;
8716         case RENDERPATH_GL13:
8717         case RENDERPATH_GL11:
8718                 return;
8719         }
8720
8721         // set waterwidth and waterheight to the water resolution that will be
8722         // used (often less than the screen resolution for faster rendering)
8723         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8724         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8725
8726         // calculate desired texture sizes
8727         // can't use water if the card does not support the texture size
8728         if (!r_water.integer || r_showsurfaces.integer)
8729                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8730         else if (vid.support.arb_texture_non_power_of_two)
8731         {
8732                 texturewidth = waterwidth;
8733                 textureheight = waterheight;
8734                 camerawidth = waterwidth;
8735                 cameraheight = waterheight;
8736         }
8737         else
8738         {
8739                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8740                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8741                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8742                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8743         }
8744
8745         // allocate textures as needed
8746         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8747         {
8748                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8749                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8750                 {
8751                         if (p->texture_refraction)
8752                                 R_FreeTexture(p->texture_refraction);
8753                         p->texture_refraction = NULL;
8754                         if (p->texture_reflection)
8755                                 R_FreeTexture(p->texture_reflection);
8756                         p->texture_reflection = NULL;
8757                         if (p->texture_camera)
8758                                 R_FreeTexture(p->texture_camera);
8759                         p->texture_camera = NULL;
8760                 }
8761                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8762                 r_waterstate.texturewidth = texturewidth;
8763                 r_waterstate.textureheight = textureheight;
8764                 r_waterstate.camerawidth = camerawidth;
8765                 r_waterstate.cameraheight = cameraheight;
8766         }
8767
8768         if (r_waterstate.texturewidth)
8769         {
8770                 r_waterstate.enabled = true;
8771
8772                 // when doing a reduced render (HDR) we want to use a smaller area
8773                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8774                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8775
8776                 // set up variables that will be used in shader setup
8777                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8778                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8779                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8780                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8781         }
8782
8783         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8784         r_waterstate.numwaterplanes = 0;
8785 }
8786
8787 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8788 {
8789         int triangleindex, planeindex;
8790         const int *e;
8791         vec3_t vert[3];
8792         vec3_t normal;
8793         vec3_t center;
8794         mplane_t plane;
8795         r_waterstate_waterplane_t *p;
8796         texture_t *t = R_GetCurrentTexture(surface->texture);
8797
8798         // just use the first triangle with a valid normal for any decisions
8799         VectorClear(normal);
8800         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8801         {
8802                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8803                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8804                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8805                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8806                 if (VectorLength2(normal) >= 0.001)
8807                         break;
8808         }
8809
8810         VectorCopy(normal, plane.normal);
8811         VectorNormalize(plane.normal);
8812         plane.dist = DotProduct(vert[0], plane.normal);
8813         PlaneClassify(&plane);
8814         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8815         {
8816                 // skip backfaces (except if nocullface is set)
8817                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8818                         return;
8819                 VectorNegate(plane.normal, plane.normal);
8820                 plane.dist *= -1;
8821                 PlaneClassify(&plane);
8822         }
8823
8824
8825         // find a matching plane if there is one
8826         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8827                 if(p->camera_entity == t->camera_entity)
8828                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8829                                 break;
8830         if (planeindex >= r_waterstate.maxwaterplanes)
8831                 return; // nothing we can do, out of planes
8832
8833         // if this triangle does not fit any known plane rendered this frame, add one
8834         if (planeindex >= r_waterstate.numwaterplanes)
8835         {
8836                 // store the new plane
8837                 r_waterstate.numwaterplanes++;
8838                 p->plane = plane;
8839                 // clear materialflags and pvs
8840                 p->materialflags = 0;
8841                 p->pvsvalid = false;
8842                 p->camera_entity = t->camera_entity;
8843                 VectorCopy(surface->mins, p->mins);
8844                 VectorCopy(surface->maxs, p->maxs);
8845         }
8846         else
8847         {
8848                 // merge mins/maxs
8849                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8850                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8851                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8852                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8853                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8854                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8855         }
8856         // merge this surface's materialflags into the waterplane
8857         p->materialflags |= t->currentmaterialflags;
8858         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8859         {
8860                 // merge this surface's PVS into the waterplane
8861                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8862                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8863                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8864                 {
8865                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8866                         p->pvsvalid = true;
8867                 }
8868         }
8869 }
8870
8871 static void R_Water_ProcessPlanes(void)
8872 {
8873         int myscissor[4];
8874         r_refdef_view_t originalview;
8875         r_refdef_view_t myview;
8876         int planeindex;
8877         r_waterstate_waterplane_t *p;
8878         vec3_t visorigin;
8879
8880         originalview = r_refdef.view;
8881
8882         // make sure enough textures are allocated
8883         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8884         {
8885                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8886                 {
8887                         if (!p->texture_refraction)
8888                                 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);
8889                         if (!p->texture_refraction)
8890                                 goto error;
8891                 }
8892                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8893                 {
8894                         if (!p->texture_camera)
8895                                 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);
8896                         if (!p->texture_camera)
8897                                 goto error;
8898                 }
8899
8900                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8901                 {
8902                         if (!p->texture_reflection)
8903                                 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);
8904                         if (!p->texture_reflection)
8905                                 goto error;
8906                 }
8907         }
8908
8909         // render views
8910         r_refdef.view = originalview;
8911         r_refdef.view.showdebug = false;
8912         r_refdef.view.width = r_waterstate.waterwidth;
8913         r_refdef.view.height = r_waterstate.waterheight;
8914         r_refdef.view.useclipplane = true;
8915         myview = r_refdef.view;
8916         r_waterstate.renderingscene = true;
8917         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8918         {
8919                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8920                 {
8921                         r_refdef.view = myview;
8922                         if(r_water_scissormode.integer)
8923                         {
8924                                 R_SetupView(true);
8925                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8926                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8927                         }
8928
8929                         // render reflected scene and copy into texture
8930                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8931                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8932                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8933                         r_refdef.view.clipplane = p->plane;
8934
8935                         // reverse the cullface settings for this render
8936                         r_refdef.view.cullface_front = GL_FRONT;
8937                         r_refdef.view.cullface_back = GL_BACK;
8938                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8939                         {
8940                                 r_refdef.view.usecustompvs = true;
8941                                 if (p->pvsvalid)
8942                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8943                                 else
8944                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8945                         }
8946
8947                         R_ResetViewRendering3D();
8948                         R_ClearScreen(r_refdef.fogenabled);
8949                         if(r_water_scissormode.integer & 2)
8950                                 R_View_UpdateWithScissor(myscissor);
8951                         else
8952                                 R_View_Update();
8953                         if(r_water_scissormode.integer & 1)
8954                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8955                         R_RenderScene();
8956
8957                         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);
8958                 }
8959
8960                 // render the normal view scene and copy into texture
8961                 // (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)
8962                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8963                 {
8964                         r_refdef.view = myview;
8965                         if(r_water_scissormode.integer)
8966                         {
8967                                 R_SetupView(true);
8968                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8969                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8970                         }
8971
8972                         r_waterstate.renderingrefraction = true;
8973
8974                         r_refdef.view.clipplane = p->plane;
8975                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8976                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8977
8978                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8979                         {
8980                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8981                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8982                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8983                                 R_RenderView_UpdateViewVectors();
8984                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8985                                 {
8986                                         r_refdef.view.usecustompvs = true;
8987                                         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);
8988                                 }
8989                         }
8990
8991                         PlaneClassify(&r_refdef.view.clipplane);
8992
8993                         R_ResetViewRendering3D();
8994                         R_ClearScreen(r_refdef.fogenabled);
8995                         if(r_water_scissormode.integer & 2)
8996                                 R_View_UpdateWithScissor(myscissor);
8997                         else
8998                                 R_View_Update();
8999                         if(r_water_scissormode.integer & 1)
9000                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
9001                         R_RenderScene();
9002
9003                         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);
9004                         r_waterstate.renderingrefraction = false;
9005                 }
9006                 else if (p->materialflags & MATERIALFLAG_CAMERA)
9007                 {
9008                         r_refdef.view = myview;
9009
9010                         r_refdef.view.clipplane = p->plane;
9011                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
9012                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
9013
9014                         r_refdef.view.width = r_waterstate.camerawidth;
9015                         r_refdef.view.height = r_waterstate.cameraheight;
9016                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
9017                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
9018
9019                         if(p->camera_entity)
9020                         {
9021                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
9022                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
9023                         }
9024
9025                         // note: all of the view is used for displaying... so
9026                         // there is no use in scissoring
9027
9028                         // reverse the cullface settings for this render
9029                         r_refdef.view.cullface_front = GL_FRONT;
9030                         r_refdef.view.cullface_back = GL_BACK;
9031                         // also reverse the view matrix
9032                         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
9033                         R_RenderView_UpdateViewVectors();
9034                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
9035                         {
9036                                 r_refdef.view.usecustompvs = true;
9037                                 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);
9038                         }
9039                         
9040                         // camera needs no clipplane
9041                         r_refdef.view.useclipplane = false;
9042
9043                         PlaneClassify(&r_refdef.view.clipplane);
9044
9045                         R_ResetViewRendering3D();
9046                         R_ClearScreen(r_refdef.fogenabled);
9047                         R_View_Update();
9048                         R_RenderScene();
9049
9050                         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);
9051                         r_waterstate.renderingrefraction = false;
9052                 }
9053
9054         }
9055         r_waterstate.renderingscene = false;
9056         r_refdef.view = originalview;
9057         R_ResetViewRendering3D();
9058         R_ClearScreen(r_refdef.fogenabled);
9059         R_View_Update();
9060         return;
9061 error:
9062         r_refdef.view = originalview;
9063         r_waterstate.renderingscene = false;
9064         Cvar_SetValueQuick(&r_water, 0);
9065         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
9066         return;
9067 }
9068
9069 void R_Bloom_StartFrame(void)
9070 {
9071         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
9072
9073         switch(vid.renderpath)
9074         {
9075         case RENDERPATH_GL20:
9076         case RENDERPATH_CGGL:
9077         case RENDERPATH_D3D9:
9078         case RENDERPATH_D3D10:
9079         case RENDERPATH_D3D11:
9080         case RENDERPATH_SOFT:
9081                 break;
9082         case RENDERPATH_GL13:
9083         case RENDERPATH_GL11:
9084                 return;
9085         }
9086
9087         // set bloomwidth and bloomheight to the bloom resolution that will be
9088         // used (often less than the screen resolution for faster rendering)
9089         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
9090         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
9091         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
9092         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
9093         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
9094
9095         // calculate desired texture sizes
9096         if (vid.support.arb_texture_non_power_of_two)
9097         {
9098                 screentexturewidth = r_refdef.view.width;
9099                 screentextureheight = r_refdef.view.height;
9100                 bloomtexturewidth = r_bloomstate.bloomwidth;
9101                 bloomtextureheight = r_bloomstate.bloomheight;
9102         }
9103         else
9104         {
9105                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
9106                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
9107                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
9108                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
9109         }
9110
9111         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))
9112         {
9113                 Cvar_SetValueQuick(&r_hdr, 0);
9114                 Cvar_SetValueQuick(&r_bloom, 0);
9115                 Cvar_SetValueQuick(&r_motionblur, 0);
9116                 Cvar_SetValueQuick(&r_damageblur, 0);
9117         }
9118
9119         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)))
9120                 screentexturewidth = screentextureheight = 0;
9121         if (!r_hdr.integer && !r_bloom.integer)
9122                 bloomtexturewidth = bloomtextureheight = 0;
9123
9124         // allocate textures as needed
9125         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
9126         {
9127                 if (r_bloomstate.texture_screen)
9128                         R_FreeTexture(r_bloomstate.texture_screen);
9129                 r_bloomstate.texture_screen = NULL;
9130                 r_bloomstate.screentexturewidth = screentexturewidth;
9131                 r_bloomstate.screentextureheight = screentextureheight;
9132                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
9133                         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);
9134         }
9135         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
9136         {
9137                 if (r_bloomstate.texture_bloom)
9138                         R_FreeTexture(r_bloomstate.texture_bloom);
9139                 r_bloomstate.texture_bloom = NULL;
9140                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
9141                 r_bloomstate.bloomtextureheight = bloomtextureheight;
9142                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
9143                         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);
9144         }
9145
9146         // when doing a reduced render (HDR) we want to use a smaller area
9147         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
9148         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
9149         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
9150         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
9151         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
9152
9153         // set up a texcoord array for the full resolution screen image
9154         // (we have to keep this around to copy back during final render)
9155         r_bloomstate.screentexcoord2f[0] = 0;
9156         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9157         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9158         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
9159         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
9160         r_bloomstate.screentexcoord2f[5] = 0;
9161         r_bloomstate.screentexcoord2f[6] = 0;
9162         r_bloomstate.screentexcoord2f[7] = 0;
9163
9164         // set up a texcoord array for the reduced resolution bloom image
9165         // (which will be additive blended over the screen image)
9166         r_bloomstate.bloomtexcoord2f[0] = 0;
9167         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9168         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9169         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9170         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
9171         r_bloomstate.bloomtexcoord2f[5] = 0;
9172         r_bloomstate.bloomtexcoord2f[6] = 0;
9173         r_bloomstate.bloomtexcoord2f[7] = 0;
9174
9175         switch(vid.renderpath)
9176         {
9177         case RENDERPATH_GL11:
9178         case RENDERPATH_GL13:
9179         case RENDERPATH_GL20:
9180         case RENDERPATH_CGGL:
9181         case RENDERPATH_SOFT:
9182                 break;
9183         case RENDERPATH_D3D9:
9184         case RENDERPATH_D3D10:
9185         case RENDERPATH_D3D11:
9186                 {
9187                         int i;
9188                         for (i = 0;i < 4;i++)
9189                         {
9190                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
9191                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
9192                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
9193                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
9194                         }
9195                 }
9196                 break;
9197         }
9198
9199         if (r_hdr.integer || r_bloom.integer)
9200         {
9201                 r_bloomstate.enabled = true;
9202                 r_bloomstate.hdr = r_hdr.integer != 0;
9203         }
9204
9205         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);
9206 }
9207
9208 void R_Bloom_CopyBloomTexture(float colorscale)
9209 {
9210         r_refdef.stats.bloom++;
9211
9212         // scale down screen texture to the bloom texture size
9213         CHECKGLERROR
9214         R_SetViewport(&r_bloomstate.viewport);
9215         GL_BlendFunc(GL_ONE, GL_ZERO);
9216         GL_Color(colorscale, colorscale, colorscale, 1);
9217         // 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...
9218         switch(vid.renderpath)
9219         {
9220         case RENDERPATH_GL11:
9221         case RENDERPATH_GL13:
9222         case RENDERPATH_GL20:
9223         case RENDERPATH_CGGL:
9224         case RENDERPATH_SOFT:
9225                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9226                 break;
9227         case RENDERPATH_D3D9:
9228         case RENDERPATH_D3D10:
9229         case RENDERPATH_D3D11:
9230                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9231                 break;
9232         }
9233         // TODO: do boxfilter scale-down in shader?
9234         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9235         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9236         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9237
9238         // we now have a bloom image in the framebuffer
9239         // copy it into the bloom image texture for later processing
9240         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);
9241         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9242 }
9243
9244 void R_Bloom_CopyHDRTexture(void)
9245 {
9246         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);
9247         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9248 }
9249
9250 void R_Bloom_MakeTexture(void)
9251 {
9252         int x, range, dir;
9253         float xoffset, yoffset, r, brighten;
9254
9255         r_refdef.stats.bloom++;
9256
9257         R_ResetViewRendering2D();
9258
9259         // we have a bloom image in the framebuffer
9260         CHECKGLERROR
9261         R_SetViewport(&r_bloomstate.viewport);
9262
9263         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
9264         {
9265                 x *= 2;
9266                 r = bound(0, r_bloom_colorexponent.value / x, 1);
9267                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9268                 GL_Color(r,r,r,1);
9269                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
9270                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9271                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9272                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9273
9274                 // copy the vertically blurred bloom view to a texture
9275                 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);
9276                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9277         }
9278
9279         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
9280         brighten = r_bloom_brighten.value;
9281         if (r_hdr.integer)
9282                 brighten *= r_hdr_range.value;
9283         brighten = sqrt(brighten);
9284         if(range >= 1)
9285                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
9286         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
9287
9288         for (dir = 0;dir < 2;dir++)
9289         {
9290                 // blend on at multiple vertical offsets to achieve a vertical blur
9291                 // TODO: do offset blends using GLSL
9292                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
9293                 GL_BlendFunc(GL_ONE, GL_ZERO);
9294                 for (x = -range;x <= range;x++)
9295                 {
9296                         if (!dir){xoffset = 0;yoffset = x;}
9297                         else {xoffset = x;yoffset = 0;}
9298                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
9299                         yoffset /= (float)r_bloomstate.bloomtextureheight;
9300                         // compute a texcoord array with the specified x and y offset
9301                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
9302                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9303                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9304                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
9305                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
9306                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
9307                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
9308                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
9309                         // this r value looks like a 'dot' particle, fading sharply to
9310                         // black at the edges
9311                         // (probably not realistic but looks good enough)
9312                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
9313                         //r = brighten/(range*2+1);
9314                         r = brighten / (range * 2 + 1);
9315                         if(range >= 1)
9316                                 r *= (1 - x*x/(float)(range*range));
9317                         GL_Color(r, r, r, 1);
9318                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
9319                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9320                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
9321                         GL_BlendFunc(GL_ONE, GL_ONE);
9322                 }
9323
9324                 // copy the vertically blurred bloom view to a texture
9325                 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);
9326                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
9327         }
9328 }
9329
9330 void R_HDR_RenderBloomTexture(void)
9331 {
9332         int oldwidth, oldheight;
9333         float oldcolorscale;
9334         int oldwaterstate;
9335
9336         oldwaterstate = r_waterstate.enabled;
9337         oldcolorscale = r_refdef.view.colorscale;
9338         oldwidth = r_refdef.view.width;
9339         oldheight = r_refdef.view.height;
9340         r_refdef.view.width = r_bloomstate.bloomwidth;
9341         r_refdef.view.height = r_bloomstate.bloomheight;
9342
9343         if(r_hdr.integer < 2)
9344                 r_waterstate.enabled = false;
9345
9346         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
9347         // TODO: add exposure compensation features
9348         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
9349
9350         r_refdef.view.showdebug = false;
9351         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
9352
9353         R_ResetViewRendering3D();
9354
9355         R_ClearScreen(r_refdef.fogenabled);
9356         if (r_timereport_active)
9357                 R_TimeReport("HDRclear");
9358
9359         R_View_Update();
9360         if (r_timereport_active)
9361                 R_TimeReport("visibility");
9362
9363         // only do secondary renders with HDR if r_hdr is 2 or higher
9364         r_waterstate.numwaterplanes = 0;
9365         if (r_waterstate.enabled)
9366                 R_RenderWaterPlanes();
9367
9368         r_refdef.view.showdebug = true;
9369         R_RenderScene();
9370         r_waterstate.numwaterplanes = 0;
9371
9372         R_ResetViewRendering2D();
9373
9374         R_Bloom_CopyHDRTexture();
9375         R_Bloom_MakeTexture();
9376
9377         // restore the view settings
9378         r_waterstate.enabled = oldwaterstate;
9379         r_refdef.view.width = oldwidth;
9380         r_refdef.view.height = oldheight;
9381         r_refdef.view.colorscale = oldcolorscale;
9382
9383         R_ResetViewRendering3D();
9384
9385         R_ClearScreen(r_refdef.fogenabled);
9386         if (r_timereport_active)
9387                 R_TimeReport("viewclear");
9388 }
9389
9390 static void R_BlendView(void)
9391 {
9392         unsigned int permutation;
9393         float uservecs[4][4];
9394
9395         switch (vid.renderpath)
9396         {
9397         case RENDERPATH_GL20:
9398         case RENDERPATH_CGGL:
9399         case RENDERPATH_D3D9:
9400         case RENDERPATH_D3D10:
9401         case RENDERPATH_D3D11:
9402         case RENDERPATH_SOFT:
9403                 permutation =
9404                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
9405                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
9406                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
9407                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
9408                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
9409
9410                 if (r_bloomstate.texture_screen)
9411                 {
9412                         // make sure the buffer is available
9413                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
9414
9415                         R_ResetViewRendering2D();
9416
9417                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
9418                         {
9419                                 // declare variables
9420                                 float speed;
9421                                 static float avgspeed;
9422
9423                                 speed = VectorLength(cl.movement_velocity);
9424
9425                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
9426                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
9427
9428                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
9429                                 speed = bound(0, speed, 1);
9430                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
9431
9432                                 // calculate values into a standard alpha
9433                                 cl.motionbluralpha = 1 - exp(-
9434                                                 (
9435                                                  (r_motionblur.value * speed / 80)
9436                                                  +
9437                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
9438                                                 )
9439                                                 /
9440                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
9441                                            );
9442
9443                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
9444                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
9445                                 // apply the blur
9446                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
9447                                 {
9448                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9449                                         GL_Color(1, 1, 1, cl.motionbluralpha);
9450                                         switch(vid.renderpath)
9451                                         {
9452                                         case RENDERPATH_GL11:
9453                                         case RENDERPATH_GL13:
9454                                         case RENDERPATH_GL20:
9455                                         case RENDERPATH_CGGL:
9456                                         case RENDERPATH_SOFT:
9457                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9458                                                 break;
9459                                         case RENDERPATH_D3D9:
9460                                         case RENDERPATH_D3D10:
9461                                         case RENDERPATH_D3D11:
9462                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
9463                                                 break;
9464                                         }
9465                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
9466                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9467                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9468                                 }
9469                         }
9470
9471                         // copy view into the screen texture
9472                         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);
9473                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9474                 }
9475                 else if (!r_bloomstate.texture_bloom)
9476                 {
9477                         // we may still have to do view tint...
9478                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9479                         {
9480                                 // apply a color tint to the whole view
9481                                 R_ResetViewRendering2D();
9482                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9483                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9484                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9485                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9486                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9487                         }
9488                         break; // no screen processing, no bloom, skip it
9489                 }
9490
9491                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
9492                 {
9493                         // render simple bloom effect
9494                         // copy the screen and shrink it and darken it for the bloom process
9495                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
9496                         // make the bloom texture
9497                         R_Bloom_MakeTexture();
9498                 }
9499
9500 #if _MSC_VER >= 1400
9501 #define sscanf sscanf_s
9502 #endif
9503                 memset(uservecs, 0, sizeof(uservecs));
9504                 if (r_glsl_postprocess_uservec1_enable.integer)
9505                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
9506                 if (r_glsl_postprocess_uservec2_enable.integer)
9507                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
9508                 if (r_glsl_postprocess_uservec3_enable.integer)
9509                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
9510                 if (r_glsl_postprocess_uservec4_enable.integer)
9511                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
9512
9513                 R_ResetViewRendering2D();
9514                 GL_Color(1, 1, 1, 1);
9515                 GL_BlendFunc(GL_ONE, GL_ZERO);
9516
9517                 switch(vid.renderpath)
9518                 {
9519                 case RENDERPATH_GL20:
9520                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9521                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
9522                         if (r_glsl_permutation->loc_Texture_First      >= 0) R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9523                         if (r_glsl_permutation->loc_Texture_Second     >= 0) R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9524                         if (r_glsl_permutation->loc_Texture_GammaRamps >= 0) R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9525                         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]);
9526                         if (r_glsl_permutation->loc_PixelSize          >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9527                         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]);
9528                         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]);
9529                         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]);
9530                         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]);
9531                         if (r_glsl_permutation->loc_Saturation         >= 0) qglUniform1fARB(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
9532                         if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2fARB(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9533                         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);
9534                         break;
9535                 case RENDERPATH_CGGL:
9536 #ifdef SUPPORTCG
9537                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9538                         R_SetupShader_SetPermutationCG(SHADERMODE_POSTPROCESS, permutation);
9539                         if (r_cg_permutation->fp_Texture_First     ) CG_BindTexture(r_cg_permutation->fp_Texture_First     , r_bloomstate.texture_screen);CHECKCGERROR
9540                         if (r_cg_permutation->fp_Texture_Second    ) CG_BindTexture(r_cg_permutation->fp_Texture_Second    , r_bloomstate.texture_bloom );CHECKCGERROR
9541                         if (r_cg_permutation->fp_Texture_GammaRamps) CG_BindTexture(r_cg_permutation->fp_Texture_GammaRamps, r_texture_gammaramps       );CHECKCGERROR
9542                         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
9543                         if (r_cg_permutation->fp_PixelSize         ) cgGLSetParameter2f(     r_cg_permutation->fp_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);CHECKCGERROR
9544                         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
9545                         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
9546                         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
9547                         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
9548                         if (r_cg_permutation->fp_Saturation        ) cgGLSetParameter1f(     r_cg_permutation->fp_Saturation        , r_glsl_saturation.value);CHECKCGERROR
9549                         if (r_cg_permutation->fp_PixelToScreenTexCoord) cgGLSetParameter2f(r_cg_permutation->fp_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);CHECKCGERROR
9550                         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);
9551 #endif
9552                         break;
9553                 case RENDERPATH_D3D9:
9554 #ifdef SUPPORTD3D
9555                         // 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...
9556                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9557                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
9558                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9559                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9560                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9561                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9562                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9563                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9564                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9565                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9566                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9567                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
9568                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
9569                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9570 #endif
9571                         break;
9572                 case RENDERPATH_D3D10:
9573                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9574                         break;
9575                 case RENDERPATH_D3D11:
9576                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
9577                         break;
9578                 case RENDERPATH_SOFT:
9579                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
9580                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
9581                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
9582                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
9583                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
9584                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9585                         DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
9586                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
9587                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
9588                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
9589                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
9590                         DPSOFTRAST_Uniform1fARB(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
9591                         DPSOFTRAST_Uniform2fARB(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
9592                         DPSOFTRAST_Uniform4fARB(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9593                         break;
9594                 default:
9595                         break;
9596                 }
9597                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9598                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9599                 break;
9600         case RENDERPATH_GL13:
9601         case RENDERPATH_GL11:
9602                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9603                 {
9604                         // apply a color tint to the whole view
9605                         R_ResetViewRendering2D();
9606                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9607                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9608                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9609                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9610                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9611                 }
9612                 break;
9613         }
9614 }
9615
9616 matrix4x4_t r_waterscrollmatrix;
9617
9618 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9619 {
9620         if (r_refdef.fog_density)
9621         {
9622                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9623                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9624                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9625
9626                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9627                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9628                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9629                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9630
9631                 {
9632                         vec3_t fogvec;
9633                         VectorCopy(r_refdef.fogcolor, fogvec);
9634                         //   color.rgb *= ContrastBoost * SceneBrightness;
9635                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9636                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9637                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9638                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9639                 }
9640         }
9641 }
9642
9643 void R_UpdateVariables(void)
9644 {
9645         R_Textures_Frame();
9646
9647         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9648
9649         r_refdef.farclip = r_farclip_base.value;
9650         if (r_refdef.scene.worldmodel)
9651                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9652         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9653
9654         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9655                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9656         r_refdef.polygonfactor = 0;
9657         r_refdef.polygonoffset = 0;
9658         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9659         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9660
9661         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9662         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9663         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9664         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9665         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9666         if (FAKELIGHT_ENABLED)
9667         {
9668                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9669         }
9670         if (r_showsurfaces.integer)
9671         {
9672                 r_refdef.scene.rtworld = false;
9673                 r_refdef.scene.rtworldshadows = false;
9674                 r_refdef.scene.rtdlight = false;
9675                 r_refdef.scene.rtdlightshadows = false;
9676                 r_refdef.lightmapintensity = 0;
9677         }
9678
9679         if (gamemode == GAME_NEHAHRA)
9680         {
9681                 if (gl_fogenable.integer)
9682                 {
9683                         r_refdef.oldgl_fogenable = true;
9684                         r_refdef.fog_density = gl_fogdensity.value;
9685                         r_refdef.fog_red = gl_fogred.value;
9686                         r_refdef.fog_green = gl_foggreen.value;
9687                         r_refdef.fog_blue = gl_fogblue.value;
9688                         r_refdef.fog_alpha = 1;
9689                         r_refdef.fog_start = 0;
9690                         r_refdef.fog_end = gl_skyclip.value;
9691                         r_refdef.fog_height = 1<<30;
9692                         r_refdef.fog_fadedepth = 128;
9693                 }
9694                 else if (r_refdef.oldgl_fogenable)
9695                 {
9696                         r_refdef.oldgl_fogenable = false;
9697                         r_refdef.fog_density = 0;
9698                         r_refdef.fog_red = 0;
9699                         r_refdef.fog_green = 0;
9700                         r_refdef.fog_blue = 0;
9701                         r_refdef.fog_alpha = 0;
9702                         r_refdef.fog_start = 0;
9703                         r_refdef.fog_end = 0;
9704                         r_refdef.fog_height = 1<<30;
9705                         r_refdef.fog_fadedepth = 128;
9706                 }
9707         }
9708
9709         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9710         r_refdef.fog_start = max(0, r_refdef.fog_start);
9711         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9712
9713         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9714
9715         if (r_refdef.fog_density && r_drawfog.integer)
9716         {
9717                 r_refdef.fogenabled = true;
9718                 // this is the point where the fog reaches 0.9986 alpha, which we
9719                 // consider a good enough cutoff point for the texture
9720                 // (0.9986 * 256 == 255.6)
9721                 if (r_fog_exp2.integer)
9722                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9723                 else
9724                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9725                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9726                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9727                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9728                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9729                         R_BuildFogHeightTexture();
9730                 // fog color was already set
9731                 // update the fog texture
9732                 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)
9733                         R_BuildFogTexture();
9734                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9735                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9736         }
9737         else
9738                 r_refdef.fogenabled = false;
9739
9740         switch(vid.renderpath)
9741         {
9742         case RENDERPATH_GL20:
9743         case RENDERPATH_CGGL:
9744         case RENDERPATH_D3D9:
9745         case RENDERPATH_D3D10:
9746         case RENDERPATH_D3D11:
9747         case RENDERPATH_SOFT:
9748                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9749                 {
9750                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9751                         {
9752                                 // build GLSL gamma texture
9753 #define RAMPWIDTH 256
9754                                 unsigned short ramp[RAMPWIDTH * 3];
9755                                 unsigned char rampbgr[RAMPWIDTH][4];
9756                                 int i;
9757
9758                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9759
9760                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9761                                 for(i = 0; i < RAMPWIDTH; ++i)
9762                                 {
9763                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9764                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9765                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9766                                         rampbgr[i][3] = 0;
9767                                 }
9768                                 if (r_texture_gammaramps)
9769                                 {
9770                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9771                                 }
9772                                 else
9773                                 {
9774                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9775                                 }
9776                         }
9777                 }
9778                 else
9779                 {
9780                         // remove GLSL gamma texture
9781                 }
9782                 break;
9783         case RENDERPATH_GL13:
9784         case RENDERPATH_GL11:
9785                 break;
9786         }
9787 }
9788
9789 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9790 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9791 /*
9792 ================
9793 R_SelectScene
9794 ================
9795 */
9796 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9797         if( scenetype != r_currentscenetype ) {
9798                 // store the old scenetype
9799                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9800                 r_currentscenetype = scenetype;
9801                 // move in the new scene
9802                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9803         }
9804 }
9805
9806 /*
9807 ================
9808 R_GetScenePointer
9809 ================
9810 */
9811 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9812 {
9813         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9814         if( scenetype == r_currentscenetype ) {
9815                 return &r_refdef.scene;
9816         } else {
9817                 return &r_scenes_store[ scenetype ];
9818         }
9819 }
9820
9821 /*
9822 ================
9823 R_RenderView
9824 ================
9825 */
9826 void R_RenderView(void)
9827 {
9828         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9829         if (r_timereport_active)
9830                 R_TimeReport("start");
9831         r_textureframe++; // used only by R_GetCurrentTexture
9832         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9833
9834         if(R_CompileShader_CheckStaticParms())
9835                 R_GLSL_Restart_f();
9836
9837         if (!r_drawentities.integer)
9838                 r_refdef.scene.numentities = 0;
9839
9840         R_AnimCache_ClearCache();
9841         R_FrameData_NewFrame();
9842
9843         /* adjust for stereo display */
9844         if(R_Stereo_Active())
9845         {
9846                 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);
9847                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9848         }
9849
9850         if (r_refdef.view.isoverlay)
9851         {
9852                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9853                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9854                 R_TimeReport("depthclear");
9855
9856                 r_refdef.view.showdebug = false;
9857
9858                 r_waterstate.enabled = false;
9859                 r_waterstate.numwaterplanes = 0;
9860
9861                 R_RenderScene();
9862
9863                 r_refdef.view.matrix = originalmatrix;
9864
9865                 CHECKGLERROR
9866                 return;
9867         }
9868
9869         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9870         {
9871                 r_refdef.view.matrix = originalmatrix;
9872                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9873         }
9874
9875         r_refdef.view.colorscale = r_hdr_scenebrightness.value;
9876
9877         R_RenderView_UpdateViewVectors();
9878
9879         R_Shadow_UpdateWorldLightSelection();
9880
9881         R_Bloom_StartFrame();
9882         R_Water_StartFrame();
9883
9884         CHECKGLERROR
9885         if (r_timereport_active)
9886                 R_TimeReport("viewsetup");
9887
9888         R_ResetViewRendering3D();
9889
9890         if (r_refdef.view.clear || r_refdef.fogenabled)
9891         {
9892                 R_ClearScreen(r_refdef.fogenabled);
9893                 if (r_timereport_active)
9894                         R_TimeReport("viewclear");
9895         }
9896         r_refdef.view.clear = true;
9897
9898         // this produces a bloom texture to be used in R_BlendView() later
9899         if (r_hdr.integer && r_bloomstate.bloomwidth)
9900         {
9901                 R_HDR_RenderBloomTexture();
9902                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9903                 r_textureframe++; // used only by R_GetCurrentTexture
9904         }
9905
9906         r_refdef.view.showdebug = true;
9907
9908         R_View_Update();
9909         if (r_timereport_active)
9910                 R_TimeReport("visibility");
9911
9912         r_waterstate.numwaterplanes = 0;
9913         if (r_waterstate.enabled)
9914                 R_RenderWaterPlanes();
9915
9916         R_RenderScene();
9917         r_waterstate.numwaterplanes = 0;
9918
9919         R_BlendView();
9920         if (r_timereport_active)
9921                 R_TimeReport("blendview");
9922
9923         GL_Scissor(0, 0, vid.width, vid.height);
9924         GL_ScissorTest(false);
9925
9926         r_refdef.view.matrix = originalmatrix;
9927
9928         CHECKGLERROR
9929 }
9930
9931 void R_RenderWaterPlanes(void)
9932 {
9933         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9934         {
9935                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9936                 if (r_timereport_active)
9937                         R_TimeReport("waterworld");
9938         }
9939
9940         // don't let sound skip if going slow
9941         if (r_refdef.scene.extraupdate)
9942                 S_ExtraUpdate ();
9943
9944         R_DrawModelsAddWaterPlanes();
9945         if (r_timereport_active)
9946                 R_TimeReport("watermodels");
9947
9948         if (r_waterstate.numwaterplanes)
9949         {
9950                 R_Water_ProcessPlanes();
9951                 if (r_timereport_active)
9952                         R_TimeReport("waterscenes");
9953         }
9954 }
9955
9956 extern void R_DrawLightningBeams (void);
9957 extern void VM_CL_AddPolygonsToMeshQueue (void);
9958 extern void R_DrawPortals (void);
9959 extern cvar_t cl_locs_show;
9960 static void R_DrawLocs(void);
9961 static void R_DrawEntityBBoxes(void);
9962 static void R_DrawModelDecals(void);
9963 extern void R_DrawModelShadows(void);
9964 extern void R_DrawModelShadowMaps(void);
9965 extern cvar_t cl_decals_newsystem;
9966 extern qboolean r_shadow_usingdeferredprepass;
9967 void R_RenderScene(void)
9968 {
9969         qboolean shadowmapping = false;
9970
9971         if (r_timereport_active)
9972                 R_TimeReport("beginscene");
9973
9974         r_refdef.stats.renders++;
9975
9976         R_UpdateFogColor();
9977
9978         // don't let sound skip if going slow
9979         if (r_refdef.scene.extraupdate)
9980                 S_ExtraUpdate ();
9981
9982         R_MeshQueue_BeginScene();
9983
9984         R_SkyStartFrame();
9985
9986         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);
9987
9988         if (r_timereport_active)
9989                 R_TimeReport("skystartframe");
9990
9991         if (cl.csqc_vidvars.drawworld)
9992         {
9993                 // don't let sound skip if going slow
9994                 if (r_refdef.scene.extraupdate)
9995                         S_ExtraUpdate ();
9996
9997                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9998                 {
9999                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
10000                         if (r_timereport_active)
10001                                 R_TimeReport("worldsky");
10002                 }
10003
10004                 if (R_DrawBrushModelsSky() && r_timereport_active)
10005                         R_TimeReport("bmodelsky");
10006
10007                 if (skyrendermasked && skyrenderlater)
10008                 {
10009                         // we have to force off the water clipping plane while rendering sky
10010                         R_SetupView(false);
10011                         R_Sky();
10012                         R_SetupView(true);
10013                         if (r_timereport_active)
10014                                 R_TimeReport("sky");
10015                 }
10016         }
10017
10018         R_AnimCache_CacheVisibleEntities();
10019         if (r_timereport_active)
10020                 R_TimeReport("animation");
10021
10022         R_Shadow_PrepareLights();
10023         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
10024                 R_Shadow_PrepareModelShadows();
10025         if (r_timereport_active)
10026                 R_TimeReport("preparelights");
10027
10028         if (R_Shadow_ShadowMappingEnabled())
10029                 shadowmapping = true;
10030
10031         if (r_shadow_usingdeferredprepass)
10032                 R_Shadow_DrawPrepass();
10033
10034         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
10035         {
10036                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
10037                 if (r_timereport_active)
10038                         R_TimeReport("worlddepth");
10039         }
10040         if (r_depthfirst.integer >= 2)
10041         {
10042                 R_DrawModelsDepth();
10043                 if (r_timereport_active)
10044                         R_TimeReport("modeldepth");
10045         }
10046
10047         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
10048         {
10049                 R_DrawModelShadowMaps();
10050                 R_ResetViewRendering3D();
10051                 // don't let sound skip if going slow
10052                 if (r_refdef.scene.extraupdate)
10053                         S_ExtraUpdate ();
10054         }
10055
10056         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
10057         {
10058                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
10059                 if (r_timereport_active)
10060                         R_TimeReport("world");
10061         }
10062
10063         // don't let sound skip if going slow
10064         if (r_refdef.scene.extraupdate)
10065                 S_ExtraUpdate ();
10066
10067         R_DrawModels();
10068         if (r_timereport_active)
10069                 R_TimeReport("models");
10070
10071         // don't let sound skip if going slow
10072         if (r_refdef.scene.extraupdate)
10073                 S_ExtraUpdate ();
10074
10075         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10076         {
10077                 R_DrawModelShadows();
10078                 R_ResetViewRendering3D();
10079                 // don't let sound skip if going slow
10080                 if (r_refdef.scene.extraupdate)
10081                         S_ExtraUpdate ();
10082         }
10083
10084         if (!r_shadow_usingdeferredprepass)
10085         {
10086                 R_Shadow_DrawLights();
10087                 if (r_timereport_active)
10088                         R_TimeReport("rtlights");
10089         }
10090
10091         // don't let sound skip if going slow
10092         if (r_refdef.scene.extraupdate)
10093                 S_ExtraUpdate ();
10094
10095         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
10096         {
10097                 R_DrawModelShadows();
10098                 R_ResetViewRendering3D();
10099                 // don't let sound skip if going slow
10100                 if (r_refdef.scene.extraupdate)
10101                         S_ExtraUpdate ();
10102         }
10103
10104         if (cl.csqc_vidvars.drawworld)
10105         {
10106                 if (cl_decals_newsystem.integer)
10107                 {
10108                         R_DrawModelDecals();
10109                         if (r_timereport_active)
10110                                 R_TimeReport("modeldecals");
10111                 }
10112                 else
10113                 {
10114                         R_DrawDecals();
10115                         if (r_timereport_active)
10116                                 R_TimeReport("decals");
10117                 }
10118
10119                 R_DrawParticles();
10120                 if (r_timereport_active)
10121                         R_TimeReport("particles");
10122
10123                 R_DrawExplosions();
10124                 if (r_timereport_active)
10125                         R_TimeReport("explosions");
10126
10127                 R_DrawLightningBeams();
10128                 if (r_timereport_active)
10129                         R_TimeReport("lightning");
10130         }
10131
10132         VM_CL_AddPolygonsToMeshQueue();
10133
10134         if (r_refdef.view.showdebug)
10135         {
10136                 if (cl_locs_show.integer)
10137                 {
10138                         R_DrawLocs();
10139                         if (r_timereport_active)
10140                                 R_TimeReport("showlocs");
10141                 }
10142
10143                 if (r_drawportals.integer)
10144                 {
10145                         R_DrawPortals();
10146                         if (r_timereport_active)
10147                                 R_TimeReport("portals");
10148                 }
10149
10150                 if (r_showbboxes.value > 0)
10151                 {
10152                         R_DrawEntityBBoxes();
10153                         if (r_timereport_active)
10154                                 R_TimeReport("bboxes");
10155                 }
10156         }
10157
10158         R_MeshQueue_RenderTransparent();
10159         if (r_timereport_active)
10160                 R_TimeReport("drawtrans");
10161
10162         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))
10163         {
10164                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
10165                 if (r_timereport_active)
10166                         R_TimeReport("worlddebug");
10167                 R_DrawModelsDebug();
10168                 if (r_timereport_active)
10169                         R_TimeReport("modeldebug");
10170         }
10171
10172         if (cl.csqc_vidvars.drawworld)
10173         {
10174                 R_Shadow_DrawCoronas();
10175                 if (r_timereport_active)
10176                         R_TimeReport("coronas");
10177         }
10178
10179 #if 0
10180         {
10181                 GL_DepthTest(false);
10182                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
10183                 GL_Color(1, 1, 1, 1);
10184                 qglBegin(GL_POLYGON);
10185                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
10186                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
10187                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
10188                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
10189                 qglEnd();
10190                 qglBegin(GL_POLYGON);
10191                 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]);
10192                 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]);
10193                 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]);
10194                 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]);
10195                 qglEnd();
10196                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
10197         }
10198 #endif
10199
10200         // don't let sound skip if going slow
10201         if (r_refdef.scene.extraupdate)
10202                 S_ExtraUpdate ();
10203
10204         R_ResetViewRendering2D();
10205 }
10206
10207 static const unsigned short bboxelements[36] =
10208 {
10209         5, 1, 3, 5, 3, 7,
10210         6, 2, 0, 6, 0, 4,
10211         7, 3, 2, 7, 2, 6,
10212         4, 0, 1, 4, 1, 5,
10213         4, 5, 7, 4, 7, 6,
10214         1, 0, 2, 1, 2, 3,
10215 };
10216
10217 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
10218 {
10219         int i;
10220         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
10221
10222         RSurf_ActiveWorldEntity();
10223
10224         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10225         GL_DepthMask(false);
10226         GL_DepthRange(0, 1);
10227         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10228 //      R_Mesh_ResetTextureState();
10229
10230         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
10231         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
10232         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
10233         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
10234         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
10235         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
10236         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
10237         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
10238         R_FillColors(color4f, 8, cr, cg, cb, ca);
10239         if (r_refdef.fogenabled)
10240         {
10241                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
10242                 {
10243                         f1 = RSurf_FogVertex(v);
10244                         f2 = 1 - f1;
10245                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
10246                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
10247                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
10248                 }
10249         }
10250         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
10251         R_Mesh_ResetTextureState();
10252         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10253         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
10254 }
10255
10256 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10257 {
10258         int i;
10259         float color[4];
10260         prvm_edict_t *edict;
10261         prvm_prog_t *prog_save = prog;
10262
10263         // this function draws bounding boxes of server entities
10264         if (!sv.active)
10265                 return;
10266
10267         GL_CullFace(GL_NONE);
10268         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10269
10270         prog = 0;
10271         SV_VM_Begin();
10272         for (i = 0;i < numsurfaces;i++)
10273         {
10274                 edict = PRVM_EDICT_NUM(surfacelist[i]);
10275                 switch ((int)edict->fields.server->solid)
10276                 {
10277                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
10278                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
10279                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
10280                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
10281                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
10282                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
10283                 }
10284                 color[3] *= r_showbboxes.value;
10285                 color[3] = bound(0, color[3], 1);
10286                 GL_DepthTest(!r_showdisabledepthtest.integer);
10287                 GL_CullFace(r_refdef.view.cullface_front);
10288                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
10289         }
10290         SV_VM_End();
10291         prog = prog_save;
10292 }
10293
10294 static void R_DrawEntityBBoxes(void)
10295 {
10296         int i;
10297         prvm_edict_t *edict;
10298         vec3_t center;
10299         prvm_prog_t *prog_save = prog;
10300
10301         // this function draws bounding boxes of server entities
10302         if (!sv.active)
10303                 return;
10304
10305         prog = 0;
10306         SV_VM_Begin();
10307         for (i = 0;i < prog->num_edicts;i++)
10308         {
10309                 edict = PRVM_EDICT_NUM(i);
10310                 if (edict->priv.server->free)
10311                         continue;
10312                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
10313                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
10314                         continue;
10315                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
10316                         continue;
10317                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
10318                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
10319         }
10320         SV_VM_End();
10321         prog = prog_save;
10322 }
10323
10324 static const int nomodelelement3i[24] =
10325 {
10326         5, 2, 0,
10327         5, 1, 2,
10328         5, 0, 3,
10329         5, 3, 1,
10330         0, 2, 4,
10331         2, 1, 4,
10332         3, 0, 4,
10333         1, 3, 4
10334 };
10335
10336 static const unsigned short nomodelelement3s[24] =
10337 {
10338         5, 2, 0,
10339         5, 1, 2,
10340         5, 0, 3,
10341         5, 3, 1,
10342         0, 2, 4,
10343         2, 1, 4,
10344         3, 0, 4,
10345         1, 3, 4
10346 };
10347
10348 static const float nomodelvertex3f[6*3] =
10349 {
10350         -16,   0,   0,
10351          16,   0,   0,
10352           0, -16,   0,
10353           0,  16,   0,
10354           0,   0, -16,
10355           0,   0,  16
10356 };
10357
10358 static const float nomodelcolor4f[6*4] =
10359 {
10360         0.0f, 0.0f, 0.5f, 1.0f,
10361         0.0f, 0.0f, 0.5f, 1.0f,
10362         0.0f, 0.5f, 0.0f, 1.0f,
10363         0.0f, 0.5f, 0.0f, 1.0f,
10364         0.5f, 0.0f, 0.0f, 1.0f,
10365         0.5f, 0.0f, 0.0f, 1.0f
10366 };
10367
10368 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10369 {
10370         int i;
10371         float f1, f2, *c;
10372         float color4f[6*4];
10373
10374         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);
10375
10376         // this is only called once per entity so numsurfaces is always 1, and
10377         // surfacelist is always {0}, so this code does not handle batches
10378
10379         if (rsurface.ent_flags & RENDER_ADDITIVE)
10380         {
10381                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
10382                 GL_DepthMask(false);
10383         }
10384         else if (rsurface.colormod[3] < 1)
10385         {
10386                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10387                 GL_DepthMask(false);
10388         }
10389         else
10390         {
10391                 GL_BlendFunc(GL_ONE, GL_ZERO);
10392                 GL_DepthMask(true);
10393         }
10394         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
10395         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
10396         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
10397         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
10398         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
10399         for (i = 0, c = color4f;i < 6;i++, c += 4)
10400         {
10401                 c[0] *= rsurface.colormod[0];
10402                 c[1] *= rsurface.colormod[1];
10403                 c[2] *= rsurface.colormod[2];
10404                 c[3] *= rsurface.colormod[3];
10405         }
10406         if (r_refdef.fogenabled)
10407         {
10408                 for (i = 0, c = color4f;i < 6;i++, c += 4)
10409                 {
10410                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
10411                         f2 = 1 - f1;
10412                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
10413                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
10414                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
10415                 }
10416         }
10417 //      R_Mesh_ResetTextureState();
10418         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
10419         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
10420         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
10421 }
10422
10423 void R_DrawNoModel(entity_render_t *ent)
10424 {
10425         vec3_t org;
10426         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
10427         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
10428                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
10429         else
10430                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
10431 }
10432
10433 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
10434 {
10435         vec3_t right1, right2, diff, normal;
10436
10437         VectorSubtract (org2, org1, normal);
10438
10439         // calculate 'right' vector for start
10440         VectorSubtract (r_refdef.view.origin, org1, diff);
10441         CrossProduct (normal, diff, right1);
10442         VectorNormalize (right1);
10443
10444         // calculate 'right' vector for end
10445         VectorSubtract (r_refdef.view.origin, org2, diff);
10446         CrossProduct (normal, diff, right2);
10447         VectorNormalize (right2);
10448
10449         vert[ 0] = org1[0] + width * right1[0];
10450         vert[ 1] = org1[1] + width * right1[1];
10451         vert[ 2] = org1[2] + width * right1[2];
10452         vert[ 3] = org1[0] - width * right1[0];
10453         vert[ 4] = org1[1] - width * right1[1];
10454         vert[ 5] = org1[2] - width * right1[2];
10455         vert[ 6] = org2[0] - width * right2[0];
10456         vert[ 7] = org2[1] - width * right2[1];
10457         vert[ 8] = org2[2] - width * right2[2];
10458         vert[ 9] = org2[0] + width * right2[0];
10459         vert[10] = org2[1] + width * right2[1];
10460         vert[11] = org2[2] + width * right2[2];
10461 }
10462
10463 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)
10464 {
10465         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
10466         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
10467         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
10468         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
10469         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
10470         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
10471         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
10472         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
10473         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
10474         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
10475         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
10476         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
10477 }
10478
10479 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
10480 {
10481         int i;
10482         float *vertex3f;
10483         float v[3];
10484         VectorSet(v, x, y, z);
10485         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
10486                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
10487                         break;
10488         if (i == mesh->numvertices)
10489         {
10490                 if (mesh->numvertices < mesh->maxvertices)
10491                 {
10492                         VectorCopy(v, vertex3f);
10493                         mesh->numvertices++;
10494                 }
10495                 return mesh->numvertices;
10496         }
10497         else
10498                 return i;
10499 }
10500
10501 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
10502 {
10503         int i;
10504         int *e, element[3];
10505         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10506         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
10507         e = mesh->element3i + mesh->numtriangles * 3;
10508         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
10509         {
10510                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
10511                 if (mesh->numtriangles < mesh->maxtriangles)
10512                 {
10513                         *e++ = element[0];
10514                         *e++ = element[1];
10515                         *e++ = element[2];
10516                         mesh->numtriangles++;
10517                 }
10518                 element[1] = element[2];
10519         }
10520 }
10521
10522 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
10523 {
10524         int i;
10525         int *e, element[3];
10526         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10527         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
10528         e = mesh->element3i + mesh->numtriangles * 3;
10529         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
10530         {
10531                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
10532                 if (mesh->numtriangles < mesh->maxtriangles)
10533                 {
10534                         *e++ = element[0];
10535                         *e++ = element[1];
10536                         *e++ = element[2];
10537                         mesh->numtriangles++;
10538                 }
10539                 element[1] = element[2];
10540         }
10541 }
10542
10543 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
10544 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
10545 {
10546         int planenum, planenum2;
10547         int w;
10548         int tempnumpoints;
10549         mplane_t *plane, *plane2;
10550         double maxdist;
10551         double temppoints[2][256*3];
10552         // figure out how large a bounding box we need to properly compute this brush
10553         maxdist = 0;
10554         for (w = 0;w < numplanes;w++)
10555                 maxdist = max(maxdist, fabs(planes[w].dist));
10556         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
10557         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
10558         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
10559         {
10560                 w = 0;
10561                 tempnumpoints = 4;
10562                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
10563                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
10564                 {
10565                         if (planenum2 == planenum)
10566                                 continue;
10567                         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);
10568                         w = !w;
10569                 }
10570                 if (tempnumpoints < 3)
10571                         continue;
10572                 // generate elements forming a triangle fan for this polygon
10573                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
10574         }
10575 }
10576
10577 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)
10578 {
10579         texturelayer_t *layer;
10580         layer = t->currentlayers + t->currentnumlayers++;
10581         layer->type = type;
10582         layer->depthmask = depthmask;
10583         layer->blendfunc1 = blendfunc1;
10584         layer->blendfunc2 = blendfunc2;
10585         layer->texture = texture;
10586         layer->texmatrix = *matrix;
10587         layer->color[0] = r;
10588         layer->color[1] = g;
10589         layer->color[2] = b;
10590         layer->color[3] = a;
10591 }
10592
10593 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10594 {
10595         if(parms[0] == 0 && parms[1] == 0)
10596                 return false;
10597         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10598                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10599                         return false;
10600         return true;
10601 }
10602
10603 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10604 {
10605         double index, f;
10606         index = parms[2] + r_refdef.scene.time * parms[3];
10607         index -= floor(index);
10608         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10609         {
10610         default:
10611         case Q3WAVEFUNC_NONE:
10612         case Q3WAVEFUNC_NOISE:
10613         case Q3WAVEFUNC_COUNT:
10614                 f = 0;
10615                 break;
10616         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10617         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10618         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10619         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10620         case Q3WAVEFUNC_TRIANGLE:
10621                 index *= 4;
10622                 f = index - floor(index);
10623                 if (index < 1)
10624                         f = f;
10625                 else if (index < 2)
10626                         f = 1 - f;
10627                 else if (index < 3)
10628                         f = -f;
10629                 else
10630                         f = -(1 - f);
10631                 break;
10632         }
10633         f = parms[0] + parms[1] * f;
10634         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10635                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10636         return (float) f;
10637 }
10638
10639 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10640 {
10641         int w, h, idx;
10642         float f;
10643         float tcmat[12];
10644         matrix4x4_t matrix, temp;
10645         switch(tcmod->tcmod)
10646         {
10647                 case Q3TCMOD_COUNT:
10648                 case Q3TCMOD_NONE:
10649                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10650                                 matrix = r_waterscrollmatrix;
10651                         else
10652                                 matrix = identitymatrix;
10653                         break;
10654                 case Q3TCMOD_ENTITYTRANSLATE:
10655                         // this is used in Q3 to allow the gamecode to control texcoord
10656                         // scrolling on the entity, which is not supported in darkplaces yet.
10657                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10658                         break;
10659                 case Q3TCMOD_ROTATE:
10660                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10661                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10662                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10663                         break;
10664                 case Q3TCMOD_SCALE:
10665                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10666                         break;
10667                 case Q3TCMOD_SCROLL:
10668                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10669                         break;
10670                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10671                         w = (int) tcmod->parms[0];
10672                         h = (int) tcmod->parms[1];
10673                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10674                         f = f - floor(f);
10675                         idx = (int) floor(f * w * h);
10676                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10677                         break;
10678                 case Q3TCMOD_STRETCH:
10679                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10680                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10681                         break;
10682                 case Q3TCMOD_TRANSFORM:
10683                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10684                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10685                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10686                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10687                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10688                         break;
10689                 case Q3TCMOD_TURBULENT:
10690                         // this is handled in the RSurf_PrepareVertices function
10691                         matrix = identitymatrix;
10692                         break;
10693         }
10694         temp = *texmatrix;
10695         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10696 }
10697
10698 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10699 {
10700         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10701         char name[MAX_QPATH];
10702         skinframe_t *skinframe;
10703         unsigned char pixels[296*194];
10704         strlcpy(cache->name, skinname, sizeof(cache->name));
10705         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10706         if (developer_loading.integer)
10707                 Con_Printf("loading %s\n", name);
10708         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10709         if (!skinframe || !skinframe->base)
10710         {
10711                 unsigned char *f;
10712                 fs_offset_t filesize;
10713                 skinframe = NULL;
10714                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10715                 if (f)
10716                 {
10717                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10718                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10719                         Mem_Free(f);
10720                 }
10721         }
10722         cache->skinframe = skinframe;
10723 }
10724
10725 texture_t *R_GetCurrentTexture(texture_t *t)
10726 {
10727         int i;
10728         const entity_render_t *ent = rsurface.entity;
10729         dp_model_t *model = ent->model;
10730         q3shaderinfo_layer_tcmod_t *tcmod;
10731
10732         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10733                 return t->currentframe;
10734         t->update_lastrenderframe = r_textureframe;
10735         t->update_lastrenderentity = (void *)ent;
10736
10737         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10738                 t->camera_entity = ent->entitynumber;
10739         else
10740                 t->camera_entity = 0;
10741
10742         // switch to an alternate material if this is a q1bsp animated material
10743         {
10744                 texture_t *texture = t;
10745                 int s = rsurface.ent_skinnum;
10746                 if ((unsigned int)s >= (unsigned int)model->numskins)
10747                         s = 0;
10748                 if (model->skinscenes)
10749                 {
10750                         if (model->skinscenes[s].framecount > 1)
10751                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10752                         else
10753                                 s = model->skinscenes[s].firstframe;
10754                 }
10755                 if (s > 0)
10756                         t = t + s * model->num_surfaces;
10757                 if (t->animated)
10758                 {
10759                         // use an alternate animation if the entity's frame is not 0,
10760                         // and only if the texture has an alternate animation
10761                         if (rsurface.ent_alttextures && t->anim_total[1])
10762                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10763                         else
10764                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10765                 }
10766                 texture->currentframe = t;
10767         }
10768
10769         // update currentskinframe to be a qw skin or animation frame
10770         if (rsurface.ent_qwskin >= 0)
10771         {
10772                 i = rsurface.ent_qwskin;
10773                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10774                 {
10775                         r_qwskincache_size = cl.maxclients;
10776                         if (r_qwskincache)
10777                                 Mem_Free(r_qwskincache);
10778                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10779                 }
10780                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10781                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10782                 t->currentskinframe = r_qwskincache[i].skinframe;
10783                 if (t->currentskinframe == NULL)
10784                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10785         }
10786         else if (t->numskinframes >= 2)
10787                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10788         if (t->backgroundnumskinframes >= 2)
10789                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10790
10791         t->currentmaterialflags = t->basematerialflags;
10792         t->currentalpha = rsurface.colormod[3];
10793         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10794                 t->currentalpha *= r_wateralpha.value;
10795         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10796                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10797         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10798                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10799         if (!(rsurface.ent_flags & RENDER_LIGHT))
10800                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10801         else if (FAKELIGHT_ENABLED)
10802         {
10803                         // no modellight if using fakelight for the map
10804         }
10805         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10806         {
10807                 // pick a model lighting mode
10808                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10809                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10810                 else
10811                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10812         }
10813         if (rsurface.ent_flags & RENDER_ADDITIVE)
10814                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10815         else if (t->currentalpha < 1)
10816                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10817         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10818                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10819         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10820                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10821         if (t->backgroundnumskinframes)
10822                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10823         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10824         {
10825                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10826                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10827         }
10828         else
10829                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10830         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10831                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10832
10833         // there is no tcmod
10834         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10835         {
10836                 t->currenttexmatrix = r_waterscrollmatrix;
10837                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10838         }
10839         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10840         {
10841                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10842                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10843         }
10844
10845         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10846                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10847         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10848                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10849
10850         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10851         if (t->currentskinframe->qpixels)
10852                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10853         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10854         if (!t->basetexture)
10855                 t->basetexture = r_texture_notexture;
10856         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10857         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10858         t->nmaptexture = t->currentskinframe->nmap;
10859         if (!t->nmaptexture)
10860                 t->nmaptexture = r_texture_blanknormalmap;
10861         t->glosstexture = r_texture_black;
10862         t->glowtexture = t->currentskinframe->glow;
10863         t->fogtexture = t->currentskinframe->fog;
10864         t->reflectmasktexture = t->currentskinframe->reflect;
10865         if (t->backgroundnumskinframes)
10866         {
10867                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10868                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10869                 t->backgroundglosstexture = r_texture_black;
10870                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10871                 if (!t->backgroundnmaptexture)
10872                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10873         }
10874         else
10875         {
10876                 t->backgroundbasetexture = r_texture_white;
10877                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10878                 t->backgroundglosstexture = r_texture_black;
10879                 t->backgroundglowtexture = NULL;
10880         }
10881         t->specularpower = r_shadow_glossexponent.value;
10882         // TODO: store reference values for these in the texture?
10883         t->specularscale = 0;
10884         if (r_shadow_gloss.integer > 0)
10885         {
10886                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10887                 {
10888                         if (r_shadow_glossintensity.value > 0)
10889                         {
10890                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10891                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10892                                 t->specularscale = r_shadow_glossintensity.value;
10893                         }
10894                 }
10895                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10896                 {
10897                         t->glosstexture = r_texture_white;
10898                         t->backgroundglosstexture = r_texture_white;
10899                         t->specularscale = r_shadow_gloss2intensity.value;
10900                         t->specularpower = r_shadow_gloss2exponent.value;
10901                 }
10902         }
10903         t->specularscale *= t->specularscalemod;
10904         t->specularpower *= t->specularpowermod;
10905
10906         // lightmaps mode looks bad with dlights using actual texturing, so turn
10907         // off the colormap and glossmap, but leave the normalmap on as it still
10908         // accurately represents the shading involved
10909         if (gl_lightmaps.integer)
10910         {
10911                 t->basetexture = r_texture_grey128;
10912                 t->pantstexture = r_texture_black;
10913                 t->shirttexture = r_texture_black;
10914                 t->nmaptexture = r_texture_blanknormalmap;
10915                 t->glosstexture = r_texture_black;
10916                 t->glowtexture = NULL;
10917                 t->fogtexture = NULL;
10918                 t->reflectmasktexture = NULL;
10919                 t->backgroundbasetexture = NULL;
10920                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10921                 t->backgroundglosstexture = r_texture_black;
10922                 t->backgroundglowtexture = NULL;
10923                 t->specularscale = 0;
10924                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10925         }
10926
10927         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10928         VectorClear(t->dlightcolor);
10929         t->currentnumlayers = 0;
10930         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10931         {
10932                 int blendfunc1, blendfunc2;
10933                 qboolean depthmask;
10934                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10935                 {
10936                         blendfunc1 = GL_SRC_ALPHA;
10937                         blendfunc2 = GL_ONE;
10938                 }
10939                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10940                 {
10941                         blendfunc1 = GL_SRC_ALPHA;
10942                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10943                 }
10944                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10945                 {
10946                         blendfunc1 = t->customblendfunc[0];
10947                         blendfunc2 = t->customblendfunc[1];
10948                 }
10949                 else
10950                 {
10951                         blendfunc1 = GL_ONE;
10952                         blendfunc2 = GL_ZERO;
10953                 }
10954                 // don't colormod evilblend textures
10955                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10956                         VectorSet(t->lightmapcolor, 1, 1, 1);
10957                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10958                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10959                 {
10960                         // fullbright is not affected by r_refdef.lightmapintensity
10961                         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]);
10962                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10963                                 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]);
10964                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10965                                 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]);
10966                 }
10967                 else
10968                 {
10969                         vec3_t ambientcolor;
10970                         float colorscale;
10971                         // set the color tint used for lights affecting this surface
10972                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10973                         colorscale = 2;
10974                         // q3bsp has no lightmap updates, so the lightstylevalue that
10975                         // would normally be baked into the lightmap must be
10976                         // applied to the color
10977                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10978                         if (model->type == mod_brushq3)
10979                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10980                         colorscale *= r_refdef.lightmapintensity;
10981                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10982                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10983                         // basic lit geometry
10984                         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]);
10985                         // add pants/shirt if needed
10986                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10987                                 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]);
10988                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10989                                 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]);
10990                         // now add ambient passes if needed
10991                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10992                         {
10993                                 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]);
10994                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10995                                         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]);
10996                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10997                                         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]);
10998                         }
10999                 }
11000                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
11001                         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]);
11002                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
11003                 {
11004                         // if this is opaque use alpha blend which will darken the earlier
11005                         // passes cheaply.
11006                         //
11007                         // if this is an alpha blended material, all the earlier passes
11008                         // were darkened by fog already, so we only need to add the fog
11009                         // color ontop through the fog mask texture
11010                         //
11011                         // if this is an additive blended material, all the earlier passes
11012                         // were darkened by fog already, and we should not add fog color
11013                         // (because the background was not darkened, there is no fog color
11014                         // that was lost behind it).
11015                         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]);
11016                 }
11017         }
11018
11019         return t->currentframe;
11020 }
11021
11022 rsurfacestate_t rsurface;
11023
11024 void RSurf_ActiveWorldEntity(void)
11025 {
11026         dp_model_t *model = r_refdef.scene.worldmodel;
11027         //if (rsurface.entity == r_refdef.scene.worldentity)
11028         //      return;
11029         rsurface.entity = r_refdef.scene.worldentity;
11030         rsurface.skeleton = NULL;
11031         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
11032         rsurface.ent_skinnum = 0;
11033         rsurface.ent_qwskin = -1;
11034         rsurface.ent_shadertime = 0;
11035         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
11036         rsurface.matrix = identitymatrix;
11037         rsurface.inversematrix = identitymatrix;
11038         rsurface.matrixscale = 1;
11039         rsurface.inversematrixscale = 1;
11040         R_EntityMatrix(&identitymatrix);
11041         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
11042         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
11043         rsurface.fograngerecip = r_refdef.fograngerecip;
11044         rsurface.fogheightfade = r_refdef.fogheightfade;
11045         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
11046         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11047         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11048         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11049         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11050         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11051         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11052         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
11053         rsurface.colormod[3] = 1;
11054         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);
11055         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11056         rsurface.frameblend[0].lerp = 1;
11057         rsurface.ent_alttextures = false;
11058         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11059         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11060         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11061         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11062         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11063         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11064         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11065         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11066         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11067         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11068         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11069         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11070         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11071         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11072         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11073         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11074         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11075         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11076         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11077         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11078         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11079         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11080         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11081         rsurface.modelelement3i = model->surfmesh.data_element3i;
11082         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11083         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11084         rsurface.modelelement3s = model->surfmesh.data_element3s;
11085         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11086         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11087         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11088         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11089         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11090         rsurface.modelsurfaces = model->data_surfaces;
11091         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11092         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11093         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11094         rsurface.modelgeneratedvertex = false;
11095         rsurface.batchgeneratedvertex = false;
11096         rsurface.batchfirstvertex = 0;
11097         rsurface.batchnumvertices = 0;
11098         rsurface.batchfirsttriangle = 0;
11099         rsurface.batchnumtriangles = 0;
11100         rsurface.batchvertex3f  = NULL;
11101         rsurface.batchvertex3f_vertexbuffer = NULL;
11102         rsurface.batchvertex3f_bufferoffset = 0;
11103         rsurface.batchsvector3f = NULL;
11104         rsurface.batchsvector3f_vertexbuffer = NULL;
11105         rsurface.batchsvector3f_bufferoffset = 0;
11106         rsurface.batchtvector3f = NULL;
11107         rsurface.batchtvector3f_vertexbuffer = NULL;
11108         rsurface.batchtvector3f_bufferoffset = 0;
11109         rsurface.batchnormal3f  = NULL;
11110         rsurface.batchnormal3f_vertexbuffer = NULL;
11111         rsurface.batchnormal3f_bufferoffset = 0;
11112         rsurface.batchlightmapcolor4f = NULL;
11113         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11114         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11115         rsurface.batchtexcoordtexture2f = NULL;
11116         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11117         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11118         rsurface.batchtexcoordlightmap2f = NULL;
11119         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11120         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11121         rsurface.batchvertexmesh = NULL;
11122         rsurface.batchvertexmeshbuffer = NULL;
11123         rsurface.batchvertex3fbuffer = NULL;
11124         rsurface.batchelement3i = NULL;
11125         rsurface.batchelement3i_indexbuffer = NULL;
11126         rsurface.batchelement3i_bufferoffset = 0;
11127         rsurface.batchelement3s = NULL;
11128         rsurface.batchelement3s_indexbuffer = NULL;
11129         rsurface.batchelement3s_bufferoffset = 0;
11130         rsurface.passcolor4f = NULL;
11131         rsurface.passcolor4f_vertexbuffer = NULL;
11132         rsurface.passcolor4f_bufferoffset = 0;
11133 }
11134
11135 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
11136 {
11137         dp_model_t *model = ent->model;
11138         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
11139         //      return;
11140         rsurface.entity = (entity_render_t *)ent;
11141         rsurface.skeleton = ent->skeleton;
11142         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
11143         rsurface.ent_skinnum = ent->skinnum;
11144         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;
11145         rsurface.ent_shadertime = ent->shadertime;
11146         rsurface.ent_flags = ent->flags;
11147         rsurface.matrix = ent->matrix;
11148         rsurface.inversematrix = ent->inversematrix;
11149         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11150         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11151         R_EntityMatrix(&rsurface.matrix);
11152         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11153         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11154         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11155         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11156         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11157         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11158         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
11159         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
11160         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
11161         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
11162         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
11163         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
11164         rsurface.colormod[3] = ent->alpha;
11165         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
11166         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
11167         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
11168         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11169         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11170         if (ent->model->brush.submodel && !prepass)
11171         {
11172                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
11173                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
11174         }
11175         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
11176         {
11177                 if (ent->animcache_vertex3f)
11178                 {
11179                         rsurface.modelvertex3f = ent->animcache_vertex3f;
11180                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
11181                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
11182                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
11183                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
11184                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
11185                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
11186                 }
11187                 else if (wanttangents)
11188                 {
11189                         rsurface.modelvertex3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11190                         rsurface.modelsvector3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11191                         rsurface.modeltvector3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11192                         rsurface.modelnormal3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11193                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
11194                         rsurface.modelvertexmesh = NULL;
11195                         rsurface.modelvertexmeshbuffer = NULL;
11196                         rsurface.modelvertex3fbuffer = NULL;
11197                 }
11198                 else if (wantnormals)
11199                 {
11200                         rsurface.modelvertex3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11201                         rsurface.modelsvector3f = NULL;
11202                         rsurface.modeltvector3f = NULL;
11203                         rsurface.modelnormal3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11204                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
11205                         rsurface.modelvertexmesh = NULL;
11206                         rsurface.modelvertexmeshbuffer = NULL;
11207                         rsurface.modelvertex3fbuffer = NULL;
11208                 }
11209                 else
11210                 {
11211                         rsurface.modelvertex3f = R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
11212                         rsurface.modelsvector3f = NULL;
11213                         rsurface.modeltvector3f = NULL;
11214                         rsurface.modelnormal3f = NULL;
11215                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
11216                         rsurface.modelvertexmesh = NULL;
11217                         rsurface.modelvertexmeshbuffer = NULL;
11218                         rsurface.modelvertex3fbuffer = NULL;
11219                 }
11220                 rsurface.modelvertex3f_vertexbuffer = 0;
11221                 rsurface.modelvertex3f_bufferoffset = 0;
11222                 rsurface.modelsvector3f_vertexbuffer = 0;
11223                 rsurface.modelsvector3f_bufferoffset = 0;
11224                 rsurface.modeltvector3f_vertexbuffer = 0;
11225                 rsurface.modeltvector3f_bufferoffset = 0;
11226                 rsurface.modelnormal3f_vertexbuffer = 0;
11227                 rsurface.modelnormal3f_bufferoffset = 0;
11228                 rsurface.modelgeneratedvertex = true;
11229         }
11230         else
11231         {
11232                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
11233                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11234                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
11235                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
11236                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11237                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
11238                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
11239                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11240                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
11241                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
11242                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11243                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
11244                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
11245                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
11246                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
11247                 rsurface.modelgeneratedvertex = false;
11248         }
11249         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
11250         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11251         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
11252         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
11253         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11254         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
11255         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
11256         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
11257         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
11258         rsurface.modelelement3i = model->surfmesh.data_element3i;
11259         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
11260         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
11261         rsurface.modelelement3s = model->surfmesh.data_element3s;
11262         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
11263         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
11264         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
11265         rsurface.modelnumvertices = model->surfmesh.num_vertices;
11266         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
11267         rsurface.modelsurfaces = model->data_surfaces;
11268         rsurface.batchgeneratedvertex = false;
11269         rsurface.batchfirstvertex = 0;
11270         rsurface.batchnumvertices = 0;
11271         rsurface.batchfirsttriangle = 0;
11272         rsurface.batchnumtriangles = 0;
11273         rsurface.batchvertex3f  = NULL;
11274         rsurface.batchvertex3f_vertexbuffer = NULL;
11275         rsurface.batchvertex3f_bufferoffset = 0;
11276         rsurface.batchsvector3f = NULL;
11277         rsurface.batchsvector3f_vertexbuffer = NULL;
11278         rsurface.batchsvector3f_bufferoffset = 0;
11279         rsurface.batchtvector3f = NULL;
11280         rsurface.batchtvector3f_vertexbuffer = NULL;
11281         rsurface.batchtvector3f_bufferoffset = 0;
11282         rsurface.batchnormal3f  = NULL;
11283         rsurface.batchnormal3f_vertexbuffer = NULL;
11284         rsurface.batchnormal3f_bufferoffset = 0;
11285         rsurface.batchlightmapcolor4f = NULL;
11286         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11287         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11288         rsurface.batchtexcoordtexture2f = NULL;
11289         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11290         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11291         rsurface.batchtexcoordlightmap2f = NULL;
11292         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11293         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11294         rsurface.batchvertexmesh = NULL;
11295         rsurface.batchvertexmeshbuffer = NULL;
11296         rsurface.batchvertex3fbuffer = NULL;
11297         rsurface.batchelement3i = NULL;
11298         rsurface.batchelement3i_indexbuffer = NULL;
11299         rsurface.batchelement3i_bufferoffset = 0;
11300         rsurface.batchelement3s = NULL;
11301         rsurface.batchelement3s_indexbuffer = NULL;
11302         rsurface.batchelement3s_bufferoffset = 0;
11303         rsurface.passcolor4f = NULL;
11304         rsurface.passcolor4f_vertexbuffer = NULL;
11305         rsurface.passcolor4f_bufferoffset = 0;
11306 }
11307
11308 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)
11309 {
11310         rsurface.entity = r_refdef.scene.worldentity;
11311         rsurface.skeleton = NULL;
11312         rsurface.ent_skinnum = 0;
11313         rsurface.ent_qwskin = -1;
11314         rsurface.ent_shadertime = shadertime;
11315         rsurface.ent_flags = entflags;
11316         rsurface.modelnumvertices = numvertices;
11317         rsurface.modelnumtriangles = numtriangles;
11318         rsurface.matrix = *matrix;
11319         rsurface.inversematrix = *inversematrix;
11320         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
11321         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
11322         R_EntityMatrix(&rsurface.matrix);
11323         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
11324         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
11325         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
11326         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
11327         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
11328         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
11329         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
11330         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
11331         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
11332         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
11333         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
11334         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
11335         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);
11336         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
11337         rsurface.frameblend[0].lerp = 1;
11338         rsurface.ent_alttextures = false;
11339         rsurface.basepolygonfactor = r_refdef.polygonfactor;
11340         rsurface.basepolygonoffset = r_refdef.polygonoffset;
11341         if (wanttangents)
11342         {
11343                 rsurface.modelvertex3f = (float *)vertex3f;
11344                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11345                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11346                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11347         }
11348         else if (wantnormals)
11349         {
11350                 rsurface.modelvertex3f = (float *)vertex3f;
11351                 rsurface.modelsvector3f = NULL;
11352                 rsurface.modeltvector3f = NULL;
11353                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11354         }
11355         else
11356         {
11357                 rsurface.modelvertex3f = (float *)vertex3f;
11358                 rsurface.modelsvector3f = NULL;
11359                 rsurface.modeltvector3f = NULL;
11360                 rsurface.modelnormal3f = NULL;
11361         }
11362         rsurface.modelvertexmesh = NULL;
11363         rsurface.modelvertexmeshbuffer = NULL;
11364         rsurface.modelvertex3fbuffer = NULL;
11365         rsurface.modelvertex3f_vertexbuffer = 0;
11366         rsurface.modelvertex3f_bufferoffset = 0;
11367         rsurface.modelsvector3f_vertexbuffer = 0;
11368         rsurface.modelsvector3f_bufferoffset = 0;
11369         rsurface.modeltvector3f_vertexbuffer = 0;
11370         rsurface.modeltvector3f_bufferoffset = 0;
11371         rsurface.modelnormal3f_vertexbuffer = 0;
11372         rsurface.modelnormal3f_bufferoffset = 0;
11373         rsurface.modelgeneratedvertex = true;
11374         rsurface.modellightmapcolor4f  = (float *)color4f;
11375         rsurface.modellightmapcolor4f_vertexbuffer = 0;
11376         rsurface.modellightmapcolor4f_bufferoffset = 0;
11377         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
11378         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
11379         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
11380         rsurface.modeltexcoordlightmap2f  = NULL;
11381         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
11382         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
11383         rsurface.modelelement3i = (int *)element3i;
11384         rsurface.modelelement3i_indexbuffer = NULL;
11385         rsurface.modelelement3i_bufferoffset = 0;
11386         rsurface.modelelement3s = (unsigned short *)element3s;
11387         rsurface.modelelement3s_indexbuffer = NULL;
11388         rsurface.modelelement3s_bufferoffset = 0;
11389         rsurface.modellightmapoffsets = NULL;
11390         rsurface.modelsurfaces = NULL;
11391         rsurface.batchgeneratedvertex = false;
11392         rsurface.batchfirstvertex = 0;
11393         rsurface.batchnumvertices = 0;
11394         rsurface.batchfirsttriangle = 0;
11395         rsurface.batchnumtriangles = 0;
11396         rsurface.batchvertex3f  = NULL;
11397         rsurface.batchvertex3f_vertexbuffer = NULL;
11398         rsurface.batchvertex3f_bufferoffset = 0;
11399         rsurface.batchsvector3f = NULL;
11400         rsurface.batchsvector3f_vertexbuffer = NULL;
11401         rsurface.batchsvector3f_bufferoffset = 0;
11402         rsurface.batchtvector3f = NULL;
11403         rsurface.batchtvector3f_vertexbuffer = NULL;
11404         rsurface.batchtvector3f_bufferoffset = 0;
11405         rsurface.batchnormal3f  = NULL;
11406         rsurface.batchnormal3f_vertexbuffer = NULL;
11407         rsurface.batchnormal3f_bufferoffset = 0;
11408         rsurface.batchlightmapcolor4f = NULL;
11409         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11410         rsurface.batchlightmapcolor4f_bufferoffset = 0;
11411         rsurface.batchtexcoordtexture2f = NULL;
11412         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11413         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11414         rsurface.batchtexcoordlightmap2f = NULL;
11415         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11416         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11417         rsurface.batchvertexmesh = NULL;
11418         rsurface.batchvertexmeshbuffer = NULL;
11419         rsurface.batchvertex3fbuffer = NULL;
11420         rsurface.batchelement3i = NULL;
11421         rsurface.batchelement3i_indexbuffer = NULL;
11422         rsurface.batchelement3i_bufferoffset = 0;
11423         rsurface.batchelement3s = NULL;
11424         rsurface.batchelement3s_indexbuffer = NULL;
11425         rsurface.batchelement3s_bufferoffset = 0;
11426         rsurface.passcolor4f = NULL;
11427         rsurface.passcolor4f_vertexbuffer = NULL;
11428         rsurface.passcolor4f_bufferoffset = 0;
11429
11430         if (rsurface.modelnumvertices && rsurface.modelelement3i)
11431         {
11432                 if ((wantnormals || wanttangents) && !normal3f)
11433                 {
11434                         rsurface.modelnormal3f = R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11435                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
11436                 }
11437                 if (wanttangents && !svector3f)
11438                 {
11439                         rsurface.modelsvector3f = R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11440                         rsurface.modeltvector3f = R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
11441                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
11442                 }
11443         }
11444 }
11445
11446 float RSurf_FogPoint(const float *v)
11447 {
11448         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11449         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
11450         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
11451         float FogHeightFade = r_refdef.fogheightfade;
11452         float fogfrac;
11453         unsigned int fogmasktableindex;
11454         if (r_refdef.fogplaneviewabove)
11455                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11456         else
11457                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11458         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
11459         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11460 }
11461
11462 float RSurf_FogVertex(const float *v)
11463 {
11464         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
11465         float FogPlaneViewDist = rsurface.fogplaneviewdist;
11466         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
11467         float FogHeightFade = rsurface.fogheightfade;
11468         float fogfrac;
11469         unsigned int fogmasktableindex;
11470         if (r_refdef.fogplaneviewabove)
11471                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
11472         else
11473                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
11474         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
11475         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
11476 }
11477
11478 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
11479 {
11480         int i;
11481         for (i = 0;i < numelements;i++)
11482                 outelement3i[i] = inelement3i[i] + adjust;
11483 }
11484
11485 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
11486 extern cvar_t gl_vbo;
11487 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
11488 {
11489         int deformindex;
11490         int firsttriangle;
11491         int numtriangles;
11492         int firstvertex;
11493         int endvertex;
11494         int numvertices;
11495         int surfacefirsttriangle;
11496         int surfacenumtriangles;
11497         int surfacefirstvertex;
11498         int surfaceendvertex;
11499         int surfacenumvertices;
11500         int batchnumvertices;
11501         int batchnumtriangles;
11502         int needsupdate;
11503         int i, j;
11504         qboolean gaps;
11505         qboolean dynamicvertex;
11506         float amplitude;
11507         float animpos;
11508         float scale;
11509         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
11510         float waveparms[4];
11511         q3shaderinfo_deform_t *deform;
11512         const msurface_t *surface, *firstsurface;
11513         r_vertexmesh_t *vertexmesh;
11514         if (!texturenumsurfaces)
11515                 return;
11516         // find vertex range of this surface batch
11517         gaps = false;
11518         firstsurface = texturesurfacelist[0];
11519         firsttriangle = firstsurface->num_firsttriangle;
11520         batchnumvertices = 0;
11521         batchnumtriangles = 0;
11522         firstvertex = endvertex = firstsurface->num_firstvertex;
11523         for (i = 0;i < texturenumsurfaces;i++)
11524         {
11525                 surface = texturesurfacelist[i];
11526                 if (surface != firstsurface + i)
11527                         gaps = true;
11528                 surfacefirstvertex = surface->num_firstvertex;
11529                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
11530                 surfacenumvertices = surface->num_vertices;
11531                 surfacenumtriangles = surface->num_triangles;
11532                 if (firstvertex > surfacefirstvertex)
11533                         firstvertex = surfacefirstvertex;
11534                 if (endvertex < surfaceendvertex)
11535                         endvertex = surfaceendvertex;
11536                 batchnumvertices += surfacenumvertices;
11537                 batchnumtriangles += surfacenumtriangles;
11538         }
11539
11540         // we now know the vertex range used, and if there are any gaps in it
11541         rsurface.batchfirstvertex = firstvertex;
11542         rsurface.batchnumvertices = endvertex - firstvertex;
11543         rsurface.batchfirsttriangle = firsttriangle;
11544         rsurface.batchnumtriangles = batchnumtriangles;
11545
11546         // this variable holds flags for which properties have been updated that
11547         // may require regenerating vertexmesh array...
11548         needsupdate = 0;
11549
11550         // check if any dynamic vertex processing must occur
11551         dynamicvertex = false;
11552
11553         // if there is a chance of animated vertex colors, it's a dynamic batch
11554         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11555         {
11556                 dynamicvertex = true;
11557                 batchneed |= BATCHNEED_NOGAPS;
11558                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
11559         }
11560
11561         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11562         {
11563                 switch (deform->deform)
11564                 {
11565                 default:
11566                 case Q3DEFORM_PROJECTIONSHADOW:
11567                 case Q3DEFORM_TEXT0:
11568                 case Q3DEFORM_TEXT1:
11569                 case Q3DEFORM_TEXT2:
11570                 case Q3DEFORM_TEXT3:
11571                 case Q3DEFORM_TEXT4:
11572                 case Q3DEFORM_TEXT5:
11573                 case Q3DEFORM_TEXT6:
11574                 case Q3DEFORM_TEXT7:
11575                 case Q3DEFORM_NONE:
11576                         break;
11577                 case Q3DEFORM_AUTOSPRITE:
11578                         dynamicvertex = true;
11579                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11580                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11581                         break;
11582                 case Q3DEFORM_AUTOSPRITE2:
11583                         dynamicvertex = true;
11584                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11585                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11586                         break;
11587                 case Q3DEFORM_NORMAL:
11588                         dynamicvertex = true;
11589                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11590                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11591                         break;
11592                 case Q3DEFORM_WAVE:
11593                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11594                                 break; // if wavefunc is a nop, ignore this transform
11595                         dynamicvertex = true;
11596                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11597                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11598                         break;
11599                 case Q3DEFORM_BULGE:
11600                         dynamicvertex = true;
11601                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11602                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11603                         break;
11604                 case Q3DEFORM_MOVE:
11605                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11606                                 break; // if wavefunc is a nop, ignore this transform
11607                         dynamicvertex = true;
11608                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11609                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11610                         break;
11611                 }
11612         }
11613         switch(rsurface.texture->tcgen.tcgen)
11614         {
11615         default:
11616         case Q3TCGEN_TEXTURE:
11617                 break;
11618         case Q3TCGEN_LIGHTMAP:
11619                 dynamicvertex = true;
11620                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11621                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11622                 break;
11623         case Q3TCGEN_VECTOR:
11624                 dynamicvertex = true;
11625                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11626                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11627                 break;
11628         case Q3TCGEN_ENVIRONMENT:
11629                 dynamicvertex = true;
11630                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11631                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11632                 break;
11633         }
11634         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11635         {
11636                 dynamicvertex = true;
11637                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11638                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11639         }
11640
11641         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11642         {
11643                 dynamicvertex = true;
11644                 batchneed |= BATCHNEED_NOGAPS;
11645                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11646         }
11647
11648         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11649         {
11650                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11651                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11652                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11653                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11654                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11655                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11656                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11657         }
11658
11659         // when the model data has no vertex buffer (dynamic mesh), we need to
11660         // eliminate gaps
11661         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11662                 batchneed |= BATCHNEED_NOGAPS;
11663
11664         // if needsupdate, we have to do a dynamic vertex batch for sure
11665         if (needsupdate & batchneed)
11666                 dynamicvertex = true;
11667
11668         // see if we need to build vertexmesh from arrays
11669         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11670                 dynamicvertex = true;
11671
11672         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11673         // also some drivers strongly dislike firstvertex
11674         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11675                 dynamicvertex = true;
11676
11677         rsurface.batchvertex3f = rsurface.modelvertex3f;
11678         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11679         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11680         rsurface.batchsvector3f = rsurface.modelsvector3f;
11681         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11682         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11683         rsurface.batchtvector3f = rsurface.modeltvector3f;
11684         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11685         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11686         rsurface.batchnormal3f = rsurface.modelnormal3f;
11687         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11688         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11689         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11690         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11691         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11692         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11693         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11694         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11695         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11696         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11697         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11698         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11699         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11700         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11701         rsurface.batchelement3i = rsurface.modelelement3i;
11702         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11703         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11704         rsurface.batchelement3s = rsurface.modelelement3s;
11705         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11706         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11707
11708         // if any dynamic vertex processing has to occur in software, we copy the
11709         // entire surface list together before processing to rebase the vertices
11710         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11711         //
11712         // if any gaps exist and we do not have a static vertex buffer, we have to
11713         // copy the surface list together to avoid wasting upload bandwidth on the
11714         // vertices in the gaps.
11715         //
11716         // if gaps exist and we have a static vertex buffer, we still have to
11717         // combine the index buffer ranges into one dynamic index buffer.
11718         //
11719         // in all cases we end up with data that can be drawn in one call.
11720
11721         if (!dynamicvertex)
11722         {
11723                 // static vertex data, just set pointers...
11724                 rsurface.batchgeneratedvertex = false;
11725                 // if there are gaps, we want to build a combined index buffer,
11726                 // otherwise use the original static buffer with an appropriate offset
11727                 if (gaps)
11728                 {
11729                         // build a new triangle elements array for this batch
11730                         rsurface.batchelement3i = R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11731                         rsurface.batchfirsttriangle = 0;
11732                         numtriangles = 0;
11733                         for (i = 0;i < texturenumsurfaces;i++)
11734                         {
11735                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11736                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11737                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11738                                 numtriangles += surfacenumtriangles;
11739                         }
11740                         rsurface.batchelement3i_indexbuffer = NULL;
11741                         rsurface.batchelement3i_bufferoffset = 0;
11742                         rsurface.batchelement3s = NULL;
11743                         rsurface.batchelement3s_indexbuffer = NULL;
11744                         rsurface.batchelement3s_bufferoffset = 0;
11745                         if (endvertex <= 65536)
11746                         {
11747                                 // make a 16bit (unsigned short) index array if possible
11748                                 rsurface.batchelement3s = R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11749                                 for (i = 0;i < numtriangles*3;i++)
11750                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11751                         }
11752                 }
11753                 return;
11754         }
11755
11756         // something needs software processing, do it for real...
11757         // we only directly handle separate array data in this case and then
11758         // generate interleaved data if needed...
11759         rsurface.batchgeneratedvertex = true;
11760
11761         // now copy the vertex data into a combined array and make an index array
11762         // (this is what Quake3 does all the time)
11763         //if (gaps || rsurface.batchfirstvertex)
11764         {
11765                 rsurface.batchvertex3fbuffer = NULL;
11766                 rsurface.batchvertexmesh = NULL;
11767                 rsurface.batchvertexmeshbuffer = NULL;
11768                 rsurface.batchvertex3f = NULL;
11769                 rsurface.batchvertex3f_vertexbuffer = NULL;
11770                 rsurface.batchvertex3f_bufferoffset = 0;
11771                 rsurface.batchsvector3f = NULL;
11772                 rsurface.batchsvector3f_vertexbuffer = NULL;
11773                 rsurface.batchsvector3f_bufferoffset = 0;
11774                 rsurface.batchtvector3f = NULL;
11775                 rsurface.batchtvector3f_vertexbuffer = NULL;
11776                 rsurface.batchtvector3f_bufferoffset = 0;
11777                 rsurface.batchnormal3f = NULL;
11778                 rsurface.batchnormal3f_vertexbuffer = NULL;
11779                 rsurface.batchnormal3f_bufferoffset = 0;
11780                 rsurface.batchlightmapcolor4f = NULL;
11781                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11782                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11783                 rsurface.batchtexcoordtexture2f = NULL;
11784                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11785                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11786                 rsurface.batchtexcoordlightmap2f = NULL;
11787                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11788                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11789                 rsurface.batchelement3i = R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11790                 rsurface.batchelement3i_indexbuffer = NULL;
11791                 rsurface.batchelement3i_bufferoffset = 0;
11792                 rsurface.batchelement3s = NULL;
11793                 rsurface.batchelement3s_indexbuffer = NULL;
11794                 rsurface.batchelement3s_bufferoffset = 0;
11795                 // we'll only be setting up certain arrays as needed
11796                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11797                         rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11798                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11799                         rsurface.batchvertex3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11800                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11801                         rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11802                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11803                 {
11804                         rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11805                         rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11806                 }
11807                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11808                         rsurface.batchlightmapcolor4f = R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11809                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11810                         rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11811                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11812                         rsurface.batchtexcoordlightmap2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11813                 numvertices = 0;
11814                 numtriangles = 0;
11815                 for (i = 0;i < texturenumsurfaces;i++)
11816                 {
11817                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11818                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11819                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11820                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11821                         // copy only the data requested
11822                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11823                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11824                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11825                         {
11826                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11827                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11828                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11829                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11830                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11831                                 {
11832                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11833                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11834                                 }
11835                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11836                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11837                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11838                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11839                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11840                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11841                         }
11842                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11843                         numvertices += surfacenumvertices;
11844                         numtriangles += surfacenumtriangles;
11845                 }
11846
11847                 // generate a 16bit index array as well if possible
11848                 // (in general, dynamic batches fit)
11849                 if (numvertices <= 65536)
11850                 {
11851                         rsurface.batchelement3s = R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11852                         for (i = 0;i < numtriangles*3;i++)
11853                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11854                 }
11855
11856                 // since we've copied everything, the batch now starts at 0
11857                 rsurface.batchfirstvertex = 0;
11858                 rsurface.batchnumvertices = batchnumvertices;
11859                 rsurface.batchfirsttriangle = 0;
11860                 rsurface.batchnumtriangles = batchnumtriangles;
11861         }
11862
11863         // q1bsp surfaces rendered in vertex color mode have to have colors
11864         // calculated based on lightstyles
11865         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11866         {
11867                 // generate color arrays for the surfaces in this list
11868                 int c[4];
11869                 int scale;
11870                 int size3;
11871                 const int *offsets;
11872                 const unsigned char *lm;
11873                 rsurface.batchlightmapcolor4f = R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11874                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11875                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11876                 numvertices = 0;
11877                 for (i = 0;i < texturenumsurfaces;i++)
11878                 {
11879                         surface = texturesurfacelist[i];
11880                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11881                         surfacenumvertices = surface->num_vertices;
11882                         if (surface->lightmapinfo->samples)
11883                         {
11884                                 for (j = 0;j < surfacenumvertices;j++)
11885                                 {
11886                                         lm = surface->lightmapinfo->samples + offsets[j];
11887                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11888                                         VectorScale(lm, scale, c);
11889                                         if (surface->lightmapinfo->styles[1] != 255)
11890                                         {
11891                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11892                                                 lm += size3;
11893                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11894                                                 VectorMA(c, scale, lm, c);
11895                                                 if (surface->lightmapinfo->styles[2] != 255)
11896                                                 {
11897                                                         lm += size3;
11898                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11899                                                         VectorMA(c, scale, lm, c);
11900                                                         if (surface->lightmapinfo->styles[3] != 255)
11901                                                         {
11902                                                                 lm += size3;
11903                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11904                                                                 VectorMA(c, scale, lm, c);
11905                                                         }
11906                                                 }
11907                                         }
11908                                         c[0] >>= 15;
11909                                         c[1] >>= 15;
11910                                         c[2] >>= 15;
11911                                         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);
11912                                         numvertices++;
11913                                 }
11914                         }
11915                         else
11916                         {
11917                                 for (j = 0;j < surfacenumvertices;j++)
11918                                 {
11919                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11920                                         numvertices++;
11921                                 }
11922                         }
11923                 }
11924         }
11925
11926         // if vertices are deformed (sprite flares and things in maps, possibly
11927         // water waves, bulges and other deformations), modify the copied vertices
11928         // in place
11929         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11930         {
11931                 switch (deform->deform)
11932                 {
11933                 default:
11934                 case Q3DEFORM_PROJECTIONSHADOW:
11935                 case Q3DEFORM_TEXT0:
11936                 case Q3DEFORM_TEXT1:
11937                 case Q3DEFORM_TEXT2:
11938                 case Q3DEFORM_TEXT3:
11939                 case Q3DEFORM_TEXT4:
11940                 case Q3DEFORM_TEXT5:
11941                 case Q3DEFORM_TEXT6:
11942                 case Q3DEFORM_TEXT7:
11943                 case Q3DEFORM_NONE:
11944                         break;
11945                 case Q3DEFORM_AUTOSPRITE:
11946                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11947                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11948                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11949                         VectorNormalize(newforward);
11950                         VectorNormalize(newright);
11951                         VectorNormalize(newup);
11952 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11953 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11954 //                      rsurface.batchvertex3f_bufferoffset = 0;
11955 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11956 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
11957 //                      rsurface.batchsvector3f_bufferoffset = 0;
11958 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11959 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
11960 //                      rsurface.batchtvector3f_bufferoffset = 0;
11961 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11962 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11963 //                      rsurface.batchnormal3f_bufferoffset = 0;
11964                         // a single autosprite surface can contain multiple sprites...
11965                         for (j = 0;j < batchnumvertices - 3;j += 4)
11966                         {
11967                                 VectorClear(center);
11968                                 for (i = 0;i < 4;i++)
11969                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11970                                 VectorScale(center, 0.25f, center);
11971                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11972                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11973                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11974                                 for (i = 0;i < 4;i++)
11975                                 {
11976                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11977                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11978                                 }
11979                         }
11980                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11981                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11982                         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);
11983                         break;
11984                 case Q3DEFORM_AUTOSPRITE2:
11985                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11986                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11987                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11988                         VectorNormalize(newforward);
11989                         VectorNormalize(newright);
11990                         VectorNormalize(newup);
11991 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11992 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11993 //                      rsurface.batchvertex3f_bufferoffset = 0;
11994                         {
11995                                 const float *v1, *v2;
11996                                 vec3_t start, end;
11997                                 float f, l;
11998                                 struct
11999                                 {
12000                                         float length2;
12001                                         const float *v1;
12002                                         const float *v2;
12003                                 }
12004                                 shortest[2];
12005                                 memset(shortest, 0, sizeof(shortest));
12006                                 // a single autosprite surface can contain multiple sprites...
12007                                 for (j = 0;j < batchnumvertices - 3;j += 4)
12008                                 {
12009                                         VectorClear(center);
12010                                         for (i = 0;i < 4;i++)
12011                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
12012                                         VectorScale(center, 0.25f, center);
12013                                         // find the two shortest edges, then use them to define the
12014                                         // axis vectors for rotating around the central axis
12015                                         for (i = 0;i < 6;i++)
12016                                         {
12017                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
12018                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
12019                                                 l = VectorDistance2(v1, v2);
12020                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
12021                                                 if (v1[2] != v2[2])
12022                                                         l += (1.0f / 1024.0f);
12023                                                 if (shortest[0].length2 > l || i == 0)
12024                                                 {
12025                                                         shortest[1] = shortest[0];
12026                                                         shortest[0].length2 = l;
12027                                                         shortest[0].v1 = v1;
12028                                                         shortest[0].v2 = v2;
12029                                                 }
12030                                                 else if (shortest[1].length2 > l || i == 1)
12031                                                 {
12032                                                         shortest[1].length2 = l;
12033                                                         shortest[1].v1 = v1;
12034                                                         shortest[1].v2 = v2;
12035                                                 }
12036                                         }
12037                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
12038                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
12039                                         // this calculates the right vector from the shortest edge
12040                                         // and the up vector from the edge midpoints
12041                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
12042                                         VectorNormalize(right);
12043                                         VectorSubtract(end, start, up);
12044                                         VectorNormalize(up);
12045                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
12046                                         VectorSubtract(rsurface.localvieworigin, center, forward);
12047                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
12048                                         VectorNegate(forward, forward);
12049                                         VectorReflect(forward, 0, up, forward);
12050                                         VectorNormalize(forward);
12051                                         CrossProduct(up, forward, newright);
12052                                         VectorNormalize(newright);
12053                                         // rotate the quad around the up axis vector, this is made
12054                                         // especially easy by the fact we know the quad is flat,
12055                                         // so we only have to subtract the center position and
12056                                         // measure distance along the right vector, and then
12057                                         // multiply that by the newright vector and add back the
12058                                         // center position
12059                                         // we also need to subtract the old position to undo the
12060                                         // displacement from the center, which we do with a
12061                                         // DotProduct, the subtraction/addition of center is also
12062                                         // optimized into DotProducts here
12063                                         l = DotProduct(right, center);
12064                                         for (i = 0;i < 4;i++)
12065                                         {
12066                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
12067                                                 f = DotProduct(right, v1) - l;
12068                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
12069                                         }
12070                                 }
12071                         }
12072                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
12073                         {
12074 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12075 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
12076 //                              rsurface.batchnormal3f_bufferoffset = 0;
12077                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12078                         }
12079                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12080                         {
12081 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12082 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12083 //                              rsurface.batchsvector3f_bufferoffset = 0;
12084 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12085 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12086 //                              rsurface.batchtvector3f_bufferoffset = 0;
12087                                 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);
12088                         }
12089                         break;
12090                 case Q3DEFORM_NORMAL:
12091                         // deform the normals to make reflections wavey
12092                         rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12093                         rsurface.batchnormal3f_vertexbuffer = NULL;
12094                         rsurface.batchnormal3f_bufferoffset = 0;
12095                         for (j = 0;j < batchnumvertices;j++)
12096                         {
12097                                 float vertex[3];
12098                                 float *normal = rsurface.batchnormal3f + 3*j;
12099                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
12100                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
12101                                 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]);
12102                                 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]);
12103                                 VectorNormalize(normal);
12104                         }
12105                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12106                         {
12107 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12108 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12109 //                              rsurface.batchsvector3f_bufferoffset = 0;
12110 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12111 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12112 //                              rsurface.batchtvector3f_bufferoffset = 0;
12113                                 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);
12114                         }
12115                         break;
12116                 case Q3DEFORM_WAVE:
12117                         // deform vertex array to make wavey water and flags and such
12118                         waveparms[0] = deform->waveparms[0];
12119                         waveparms[1] = deform->waveparms[1];
12120                         waveparms[2] = deform->waveparms[2];
12121                         waveparms[3] = deform->waveparms[3];
12122                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
12123                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12124                         // this is how a divisor of vertex influence on deformation
12125                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
12126                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12127 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12128 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12129 //                      rsurface.batchvertex3f_bufferoffset = 0;
12130 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12131 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12132 //                      rsurface.batchnormal3f_bufferoffset = 0;
12133                         for (j = 0;j < batchnumvertices;j++)
12134                         {
12135                                 // if the wavefunc depends on time, evaluate it per-vertex
12136                                 if (waveparms[3])
12137                                 {
12138                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
12139                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
12140                                 }
12141                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12142                         }
12143                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12144                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12145                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12146                         {
12147 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12148 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12149 //                              rsurface.batchsvector3f_bufferoffset = 0;
12150 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12151 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12152 //                              rsurface.batchtvector3f_bufferoffset = 0;
12153                                 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);
12154                         }
12155                         break;
12156                 case Q3DEFORM_BULGE:
12157                         // deform vertex array to make the surface have moving bulges
12158 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12159 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12160 //                      rsurface.batchvertex3f_bufferoffset = 0;
12161 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
12162 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
12163 //                      rsurface.batchnormal3f_bufferoffset = 0;
12164                         for (j = 0;j < batchnumvertices;j++)
12165                         {
12166                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
12167                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
12168                         }
12169                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
12170                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
12171                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
12172                         {
12173 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12174 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
12175 //                              rsurface.batchsvector3f_bufferoffset = 0;
12176 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
12177 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
12178 //                              rsurface.batchtvector3f_bufferoffset = 0;
12179                                 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);
12180                         }
12181                         break;
12182                 case Q3DEFORM_MOVE:
12183                         // deform vertex array
12184                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
12185                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
12186                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
12187                         VectorScale(deform->parms, scale, waveparms);
12188 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
12189 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
12190 //                      rsurface.batchvertex3f_bufferoffset = 0;
12191                         for (j = 0;j < batchnumvertices;j++)
12192                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
12193                         break;
12194                 }
12195         }
12196
12197         // generate texcoords based on the chosen texcoord source
12198         switch(rsurface.texture->tcgen.tcgen)
12199         {
12200         default:
12201         case Q3TCGEN_TEXTURE:
12202                 break;
12203         case Q3TCGEN_LIGHTMAP:
12204 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12205 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12206 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12207                 if (rsurface.batchtexcoordlightmap2f)
12208                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
12209                 break;
12210         case Q3TCGEN_VECTOR:
12211 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12212 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12213 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12214                 for (j = 0;j < batchnumvertices;j++)
12215                 {
12216                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
12217                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
12218                 }
12219                 break;
12220         case Q3TCGEN_ENVIRONMENT:
12221                 // make environment reflections using a spheremap
12222 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12223 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12224 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12225                 for (j = 0;j < batchnumvertices;j++)
12226                 {
12227                         // identical to Q3A's method, but executed in worldspace so
12228                         // carried models can be shiny too
12229
12230                         float viewer[3], d, reflected[3], worldreflected[3];
12231
12232                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
12233                         // VectorNormalize(viewer);
12234
12235                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
12236
12237                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
12238                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
12239                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
12240                         // note: this is proportinal to viewer, so we can normalize later
12241
12242                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
12243                         VectorNormalize(worldreflected);
12244
12245                         // note: this sphere map only uses world x and z!
12246                         // so positive and negative y will LOOK THE SAME.
12247                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
12248                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
12249                 }
12250                 break;
12251         }
12252         // the only tcmod that needs software vertex processing is turbulent, so
12253         // check for it here and apply the changes if needed
12254         // and we only support that as the first one
12255         // (handling a mixture of turbulent and other tcmods would be problematic
12256         //  without punting it entirely to a software path)
12257         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
12258         {
12259                 amplitude = rsurface.texture->tcmods[0].parms[1];
12260                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
12261 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
12262 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
12263 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
12264                 for (j = 0;j < batchnumvertices;j++)
12265                 {
12266                         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);
12267                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
12268                 }
12269         }
12270
12271         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
12272         {
12273                 // convert the modified arrays to vertex structs
12274 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
12275 //              rsurface.batchvertexmeshbuffer = NULL;
12276                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
12277                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12278                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
12279                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
12280                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12281                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
12282                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
12283                 {
12284                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12285                         {
12286                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
12287                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
12288                         }
12289                 }
12290                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
12291                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12292                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
12293                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
12294                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12295                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
12296                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
12297                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
12298                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
12299         }
12300 }
12301
12302 void RSurf_DrawBatch(void)
12303 {
12304         // sometimes a zero triangle surface (usually a degenerate patch) makes it
12305         // through the pipeline, killing it earlier in the pipeline would have
12306         // per-surface overhead rather than per-batch overhead, so it's best to
12307         // reject it here, before it hits glDraw.
12308         if (rsurface.batchnumtriangles == 0)
12309                 return;
12310 #if 0
12311         // batch debugging code
12312         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
12313         {
12314                 int i;
12315                 int j;
12316                 int c;
12317                 const int *e;
12318                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
12319                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
12320                 {
12321                         c = e[i];
12322                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
12323                         {
12324                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
12325                                 {
12326                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
12327                                                 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);
12328                                         break;
12329                                 }
12330                         }
12331                 }
12332         }
12333 #endif
12334         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);
12335 }
12336
12337 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
12338 {
12339         // pick the closest matching water plane
12340         int planeindex, vertexindex, bestplaneindex = -1;
12341         float d, bestd;
12342         vec3_t vert;
12343         const float *v;
12344         r_waterstate_waterplane_t *p;
12345         qboolean prepared = false;
12346         bestd = 0;
12347         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
12348         {
12349                 if(p->camera_entity != rsurface.texture->camera_entity)
12350                         continue;
12351                 d = 0;
12352                 if(!prepared)
12353                 {
12354                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12355                         prepared = true;
12356                         if(rsurface.batchnumvertices == 0)
12357                                 break;
12358                 }
12359                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
12360                 {
12361                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
12362                         d += fabs(PlaneDiff(vert, &p->plane));
12363                 }
12364                 if (bestd > d || bestplaneindex < 0)
12365                 {
12366                         bestd = d;
12367                         bestplaneindex = planeindex;
12368                 }
12369         }
12370         return bestplaneindex;
12371         // NOTE: this MAY return a totally unrelated water plane; we can ignore
12372         // this situation though, as it might be better to render single larger
12373         // batches with useless stuff (backface culled for example) than to
12374         // render multiple smaller batches
12375 }
12376
12377 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
12378 {
12379         int i;
12380         rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12381         rsurface.passcolor4f_vertexbuffer = 0;
12382         rsurface.passcolor4f_bufferoffset = 0;
12383         for (i = 0;i < rsurface.batchnumvertices;i++)
12384                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
12385 }
12386
12387 static void RSurf_DrawBatch_GL11_ApplyFog(void)
12388 {
12389         int i;
12390         float f;
12391         const float *v;
12392         const float *c;
12393         float *c2;
12394         rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12395         rsurface.passcolor4f_vertexbuffer = 0;
12396         rsurface.passcolor4f_bufferoffset = 0;
12397         if (rsurface.passcolor4f)
12398         {
12399                 // generate color arrays
12400                 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)
12401                 {
12402                         f = RSurf_FogVertex(v);
12403                         c2[0] = c[0] * f;
12404                         c2[1] = c[1] * f;
12405                         c2[2] = c[2] * f;
12406                         c2[3] = c[3];
12407                 }
12408         }
12409         else
12410         {
12411                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
12412                 {
12413                         f = RSurf_FogVertex(v);
12414                         c2[0] = f;
12415                         c2[1] = f;
12416                         c2[2] = f;
12417                         c2[3] = 1;
12418                 }
12419         }
12420 }
12421
12422 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
12423 {
12424         int i;
12425         float f;
12426         const float *v;
12427         const float *c;
12428         float *c2;
12429         if (!rsurface.passcolor4f)
12430                 return;
12431         rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12432         rsurface.passcolor4f_vertexbuffer = 0;
12433         rsurface.passcolor4f_bufferoffset = 0;
12434         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)
12435         {
12436                 f = RSurf_FogVertex(v);
12437                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
12438                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
12439                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
12440                 c2[3] = c[3];
12441         }
12442 }
12443
12444 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
12445 {
12446         int i;
12447         const float *c;
12448         float *c2;
12449         if (!rsurface.passcolor4f)
12450                 return;
12451         rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12452         rsurface.passcolor4f_vertexbuffer = 0;
12453         rsurface.passcolor4f_bufferoffset = 0;
12454         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12455         {
12456                 c2[0] = c[0] * r;
12457                 c2[1] = c[1] * g;
12458                 c2[2] = c[2] * b;
12459                 c2[3] = c[3] * a;
12460         }
12461 }
12462
12463 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
12464 {
12465         int i;
12466         const float *c;
12467         float *c2;
12468         if (!rsurface.passcolor4f)
12469                 return;
12470         rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12471         rsurface.passcolor4f_vertexbuffer = 0;
12472         rsurface.passcolor4f_bufferoffset = 0;
12473         for (i = 0, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
12474         {
12475                 c2[0] = c[0] + r_refdef.scene.ambient;
12476                 c2[1] = c[1] + r_refdef.scene.ambient;
12477                 c2[2] = c[2] + r_refdef.scene.ambient;
12478                 c2[3] = c[3];
12479         }
12480 }
12481
12482 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12483 {
12484         // TODO: optimize
12485         rsurface.passcolor4f = NULL;
12486         rsurface.passcolor4f_vertexbuffer = 0;
12487         rsurface.passcolor4f_bufferoffset = 0;
12488         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12489         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12490         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12491         GL_Color(r, g, b, a);
12492         R_Mesh_TexBind(0, rsurface.lightmaptexture);
12493         RSurf_DrawBatch();
12494 }
12495
12496 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12497 {
12498         // TODO: optimize applyfog && applycolor case
12499         // just apply fog if necessary, and tint the fog color array if necessary
12500         rsurface.passcolor4f = NULL;
12501         rsurface.passcolor4f_vertexbuffer = 0;
12502         rsurface.passcolor4f_bufferoffset = 0;
12503         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12504         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12505         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12506         GL_Color(r, g, b, a);
12507         RSurf_DrawBatch();
12508 }
12509
12510 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12511 {
12512         // TODO: optimize
12513         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12514         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12515         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12516         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12517         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12518         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12519         GL_Color(r, g, b, a);
12520         RSurf_DrawBatch();
12521 }
12522
12523 static void RSurf_DrawBatch_GL11_ClampColor(void)
12524 {
12525         int i;
12526         const float *c1;
12527         float *c2;
12528         if (!rsurface.passcolor4f)
12529                 return;
12530         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
12531         {
12532                 c2[0] = bound(0.0f, c1[0], 1.0f);
12533                 c2[1] = bound(0.0f, c1[1], 1.0f);
12534                 c2[2] = bound(0.0f, c1[2], 1.0f);
12535                 c2[3] = bound(0.0f, c1[3], 1.0f);
12536         }
12537 }
12538
12539 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
12540 {
12541         int i;
12542         float f;
12543         const float *v;
12544         const float *n;
12545         float *c;
12546         //vec3_t eyedir;
12547
12548         // fake shading
12549         rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12550         rsurface.passcolor4f_vertexbuffer = 0;
12551         rsurface.passcolor4f_bufferoffset = 0;
12552         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)
12553         {
12554                 f = -DotProduct(r_refdef.view.forward, n);
12555                 f = max(0, f);
12556                 f = f * 0.85 + 0.15; // work around so stuff won't get black
12557                 f *= r_refdef.lightmapintensity;
12558                 Vector4Set(c, f, f, f, 1);
12559         }
12560 }
12561
12562 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12563 {
12564         RSurf_DrawBatch_GL11_ApplyFakeLight();
12565         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12566         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12567         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12568         GL_Color(r, g, b, a);
12569         RSurf_DrawBatch();
12570 }
12571
12572 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
12573 {
12574         int i;
12575         float f;
12576         float alpha;
12577         const float *v;
12578         const float *n;
12579         float *c;
12580         vec3_t ambientcolor;
12581         vec3_t diffusecolor;
12582         vec3_t lightdir;
12583         // TODO: optimize
12584         // model lighting
12585         VectorCopy(rsurface.modellight_lightdir, lightdir);
12586         f = 0.5f * r_refdef.lightmapintensity;
12587         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12588         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12589         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12590         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12591         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12592         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12593         alpha = *a;
12594         if (VectorLength2(diffusecolor) > 0)
12595         {
12596                 // q3-style directional shading
12597                 rsurface.passcolor4f = R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12598                 rsurface.passcolor4f_vertexbuffer = 0;
12599                 rsurface.passcolor4f_bufferoffset = 0;
12600                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, n = rsurface.batchnormal3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, n += 3, c += 4)
12601                 {
12602                         if ((f = DotProduct(n, lightdir)) > 0)
12603                                 VectorMA(ambientcolor, f, diffusecolor, c);
12604                         else
12605                                 VectorCopy(ambientcolor, c);
12606                         c[3] = alpha;
12607                 }
12608                 *r = 1;
12609                 *g = 1;
12610                 *b = 1;
12611                 *a = 1;
12612                 *applycolor = false;
12613         }
12614         else
12615         {
12616                 *r = ambientcolor[0];
12617                 *g = ambientcolor[1];
12618                 *b = ambientcolor[2];
12619                 rsurface.passcolor4f = NULL;
12620                 rsurface.passcolor4f_vertexbuffer = 0;
12621                 rsurface.passcolor4f_bufferoffset = 0;
12622         }
12623 }
12624
12625 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12626 {
12627         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12628         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12629         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12630         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12631         GL_Color(r, g, b, a);
12632         RSurf_DrawBatch();
12633 }
12634
12635 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12636 {
12637         int i;
12638         float f;
12639         const float *v;
12640         float *c;
12641         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12642         {
12643                 f = 1 - RSurf_FogVertex(v);
12644                 c[0] = r;
12645                 c[1] = g;
12646                 c[2] = b;
12647                 c[3] = f * a;
12648         }
12649 }
12650
12651 void RSurf_SetupDepthAndCulling(void)
12652 {
12653         // submodels are biased to avoid z-fighting with world surfaces that they
12654         // may be exactly overlapping (avoids z-fighting artifacts on certain
12655         // doors and things in Quake maps)
12656         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12657         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12658         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12659         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12660 }
12661
12662 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12663 {
12664         // transparent sky would be ridiculous
12665         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12666                 return;
12667         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12668         skyrenderlater = true;
12669         RSurf_SetupDepthAndCulling();
12670         GL_DepthMask(true);
12671         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12672         // skymasking on them, and Quake3 never did sky masking (unlike
12673         // software Quake and software Quake2), so disable the sky masking
12674         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12675         // and skymasking also looks very bad when noclipping outside the
12676         // level, so don't use it then either.
12677         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12678         {
12679                 R_Mesh_ResetTextureState();
12680                 if (skyrendermasked)
12681                 {
12682                         R_SetupShader_DepthOrShadow();
12683                         // depth-only (masking)
12684                         GL_ColorMask(0,0,0,0);
12685                         // just to make sure that braindead drivers don't draw
12686                         // anything despite that colormask...
12687                         GL_BlendFunc(GL_ZERO, GL_ONE);
12688                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12689                         if (rsurface.batchvertex3fbuffer)
12690                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12691                         else
12692                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12693                 }
12694                 else
12695                 {
12696                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12697                         // fog sky
12698                         GL_BlendFunc(GL_ONE, GL_ZERO);
12699                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12700                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12701                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12702                 }
12703                 RSurf_DrawBatch();
12704                 if (skyrendermasked)
12705                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12706         }
12707         R_Mesh_ResetTextureState();
12708         GL_Color(1, 1, 1, 1);
12709 }
12710
12711 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12712 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12713 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12714 {
12715         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12716                 return;
12717         if (prepass)
12718         {
12719                 // render screenspace normalmap to texture
12720                 GL_DepthMask(true);
12721                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12722                 RSurf_DrawBatch();
12723                 return;
12724         }
12725
12726         // bind lightmap texture
12727
12728         // water/refraction/reflection/camera surfaces have to be handled specially
12729         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12730         {
12731                 int start, end, startplaneindex;
12732                 for (start = 0;start < texturenumsurfaces;start = end)
12733                 {
12734                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12735                         if(startplaneindex < 0)
12736                         {
12737                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12738                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12739                                 end = start + 1;
12740                                 continue;
12741                         }
12742                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12743                                 ;
12744                         // now that we have a batch using the same planeindex, render it
12745                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12746                         {
12747                                 // render water or distortion background
12748                                 GL_DepthMask(true);
12749                                 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));
12750                                 RSurf_DrawBatch();
12751                                 // blend surface on top
12752                                 GL_DepthMask(false);
12753                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12754                                 RSurf_DrawBatch();
12755                         }
12756                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12757                         {
12758                                 // render surface with reflection texture as input
12759                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12760                                 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));
12761                                 RSurf_DrawBatch();
12762                         }
12763                 }
12764                 return;
12765         }
12766
12767         // render surface batch normally
12768         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12769         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12770         RSurf_DrawBatch();
12771 }
12772
12773 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12774 {
12775         // OpenGL 1.3 path - anything not completely ancient
12776         qboolean applycolor;
12777         qboolean applyfog;
12778         int layerindex;
12779         const texturelayer_t *layer;
12780         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);
12781         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12782
12783         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12784         {
12785                 vec4_t layercolor;
12786                 int layertexrgbscale;
12787                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12788                 {
12789                         if (layerindex == 0)
12790                                 GL_AlphaTest(true);
12791                         else
12792                         {
12793                                 GL_AlphaTest(false);
12794                                 GL_DepthFunc(GL_EQUAL);
12795                         }
12796                 }
12797                 GL_DepthMask(layer->depthmask && writedepth);
12798                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12799                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12800                 {
12801                         layertexrgbscale = 4;
12802                         VectorScale(layer->color, 0.25f, layercolor);
12803                 }
12804                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12805                 {
12806                         layertexrgbscale = 2;
12807                         VectorScale(layer->color, 0.5f, layercolor);
12808                 }
12809                 else
12810                 {
12811                         layertexrgbscale = 1;
12812                         VectorScale(layer->color, 1.0f, layercolor);
12813                 }
12814                 layercolor[3] = layer->color[3];
12815                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12816                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12817                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12818                 switch (layer->type)
12819                 {
12820                 case TEXTURELAYERTYPE_LITTEXTURE:
12821                         // single-pass lightmapped texture with 2x rgbscale
12822                         R_Mesh_TexBind(0, r_texture_white);
12823                         R_Mesh_TexMatrix(0, NULL);
12824                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12825                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12826                         R_Mesh_TexBind(1, layer->texture);
12827                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12828                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12829                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12830                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12831                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12832                         else if (FAKELIGHT_ENABLED)
12833                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12834                         else if (rsurface.uselightmaptexture)
12835                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12836                         else
12837                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12838                         break;
12839                 case TEXTURELAYERTYPE_TEXTURE:
12840                         // singletexture unlit texture with transparency support
12841                         R_Mesh_TexBind(0, layer->texture);
12842                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12843                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12844                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12845                         R_Mesh_TexBind(1, 0);
12846                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12847                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12848                         break;
12849                 case TEXTURELAYERTYPE_FOG:
12850                         // singletexture fogging
12851                         if (layer->texture)
12852                         {
12853                                 R_Mesh_TexBind(0, layer->texture);
12854                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12855                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12856                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12857                         }
12858                         else
12859                         {
12860                                 R_Mesh_TexBind(0, 0);
12861                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12862                         }
12863                         R_Mesh_TexBind(1, 0);
12864                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12865                         // generate a color array for the fog pass
12866                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12867                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12868                         RSurf_DrawBatch();
12869                         break;
12870                 default:
12871                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12872                 }
12873         }
12874         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12875         {
12876                 GL_DepthFunc(GL_LEQUAL);
12877                 GL_AlphaTest(false);
12878         }
12879 }
12880
12881 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12882 {
12883         // OpenGL 1.1 - crusty old voodoo path
12884         qboolean applyfog;
12885         int layerindex;
12886         const texturelayer_t *layer;
12887         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);
12888         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12889
12890         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12891         {
12892                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12893                 {
12894                         if (layerindex == 0)
12895                                 GL_AlphaTest(true);
12896                         else
12897                         {
12898                                 GL_AlphaTest(false);
12899                                 GL_DepthFunc(GL_EQUAL);
12900                         }
12901                 }
12902                 GL_DepthMask(layer->depthmask && writedepth);
12903                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12904                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12905                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12906                 switch (layer->type)
12907                 {
12908                 case TEXTURELAYERTYPE_LITTEXTURE:
12909                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12910                         {
12911                                 // two-pass lit texture with 2x rgbscale
12912                                 // first the lightmap pass
12913                                 R_Mesh_TexBind(0, r_texture_white);
12914                                 R_Mesh_TexMatrix(0, NULL);
12915                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12916                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12917                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12918                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12919                                 else if (FAKELIGHT_ENABLED)
12920                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12921                                 else if (rsurface.uselightmaptexture)
12922                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12923                                 else
12924                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12925                                 // then apply the texture to it
12926                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12927                                 R_Mesh_TexBind(0, layer->texture);
12928                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12929                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12930                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12931                                 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);
12932                         }
12933                         else
12934                         {
12935                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12936                                 R_Mesh_TexBind(0, layer->texture);
12937                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12938                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12939                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12940                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12941                                         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);
12942                                 else
12943                                         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);
12944                         }
12945                         break;
12946                 case TEXTURELAYERTYPE_TEXTURE:
12947                         // singletexture unlit texture with transparency support
12948                         R_Mesh_TexBind(0, layer->texture);
12949                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12950                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12951                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12952                         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);
12953                         break;
12954                 case TEXTURELAYERTYPE_FOG:
12955                         // singletexture fogging
12956                         if (layer->texture)
12957                         {
12958                                 R_Mesh_TexBind(0, layer->texture);
12959                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12960                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12961                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12962                         }
12963                         else
12964                         {
12965                                 R_Mesh_TexBind(0, 0);
12966                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12967                         }
12968                         // generate a color array for the fog pass
12969                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12970                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12971                         RSurf_DrawBatch();
12972                         break;
12973                 default:
12974                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12975                 }
12976         }
12977         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12978         {
12979                 GL_DepthFunc(GL_LEQUAL);
12980                 GL_AlphaTest(false);
12981         }
12982 }
12983
12984 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12985 {
12986         int vi;
12987         int j;
12988         r_vertexgeneric_t *batchvertex;
12989         float c[4];
12990
12991         GL_AlphaTest(false);
12992 //      R_Mesh_ResetTextureState();
12993         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12994
12995         if(rsurface.texture && rsurface.texture->currentskinframe)
12996         {
12997                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12998                 c[3] *= rsurface.texture->currentalpha;
12999         }
13000         else
13001         {
13002                 c[0] = 1;
13003                 c[1] = 0;
13004                 c[2] = 1;
13005                 c[3] = 1;
13006         }
13007
13008         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
13009         {
13010                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
13011                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
13012                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
13013         }
13014
13015         // brighten it up (as texture value 127 means "unlit")
13016         c[0] *= 2 * r_refdef.view.colorscale;
13017         c[1] *= 2 * r_refdef.view.colorscale;
13018         c[2] *= 2 * r_refdef.view.colorscale;
13019
13020         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
13021                 c[3] *= r_wateralpha.value;
13022
13023         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
13024         {
13025                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13026                 GL_DepthMask(false);
13027         }
13028         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
13029         {
13030                 GL_BlendFunc(GL_ONE, GL_ONE);
13031                 GL_DepthMask(false);
13032         }
13033         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
13034         {
13035                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
13036                 GL_DepthMask(false);
13037         }
13038         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
13039         {
13040                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
13041                 GL_DepthMask(false);
13042         }
13043         else
13044         {
13045                 GL_BlendFunc(GL_ONE, GL_ZERO);
13046                 GL_DepthMask(writedepth);
13047         }
13048
13049         if (r_showsurfaces.integer == 3)
13050         {
13051                 rsurface.passcolor4f = NULL;
13052
13053                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
13054                 {
13055                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13056
13057                         rsurface.passcolor4f = NULL;
13058                         rsurface.passcolor4f_vertexbuffer = 0;
13059                         rsurface.passcolor4f_bufferoffset = 0;
13060                 }
13061                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
13062                 {
13063                         qboolean applycolor = true;
13064                         float one = 1.0;
13065
13066                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13067
13068                         r_refdef.lightmapintensity = 1;
13069                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
13070                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13071                 }
13072                 else if (FAKELIGHT_ENABLED)
13073                 {
13074                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13075
13076                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
13077                         RSurf_DrawBatch_GL11_ApplyFakeLight();
13078                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
13079                 }
13080                 else
13081                 {
13082                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13083
13084                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
13085                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
13086                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
13087                 }
13088
13089                 if(!rsurface.passcolor4f)
13090                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
13091
13092                 RSurf_DrawBatch_GL11_ApplyAmbient();
13093                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
13094                 if(r_refdef.fogenabled)
13095                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
13096                 RSurf_DrawBatch_GL11_ClampColor();
13097
13098                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
13099                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13100                 RSurf_DrawBatch();
13101         }
13102         else if (!r_refdef.view.showdebug)
13103         {
13104                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13105                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13106                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13107                 {
13108                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13109                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
13110                 }
13111                 R_Mesh_PrepareVertices_Generic_Unlock();
13112                 RSurf_DrawBatch();
13113         }
13114         else if (r_showsurfaces.integer == 4)
13115         {
13116                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13117                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
13118                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
13119                 {
13120                         unsigned char c = vi << 3;
13121                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13122                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
13123                 }
13124                 R_Mesh_PrepareVertices_Generic_Unlock();
13125                 RSurf_DrawBatch();
13126         }
13127         else if (r_showsurfaces.integer == 2)
13128         {
13129                 const int *e;
13130                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13131                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
13132                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
13133                 {
13134                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
13135                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
13136                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
13137                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
13138                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
13139                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
13140                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
13141                 }
13142                 R_Mesh_PrepareVertices_Generic_Unlock();
13143                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
13144         }
13145         else
13146         {
13147                 int texturesurfaceindex;
13148                 int k;
13149                 const msurface_t *surface;
13150                 unsigned char surfacecolor4ub[4];
13151                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
13152                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
13153                 vi = 0;
13154                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
13155                 {
13156                         surface = texturesurfacelist[texturesurfaceindex];
13157                         k = (int)(((size_t)surface) / sizeof(msurface_t));
13158                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
13159                         for (j = 0;j < surface->num_vertices;j++)
13160                         {
13161                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
13162                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
13163                                 vi++;
13164                         }
13165                 }
13166                 R_Mesh_PrepareVertices_Generic_Unlock();
13167                 RSurf_DrawBatch();
13168         }
13169 }
13170
13171 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13172 {
13173         CHECKGLERROR
13174         RSurf_SetupDepthAndCulling();
13175         if (r_showsurfaces.integer)
13176         {
13177                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13178                 return;
13179         }
13180         switch (vid.renderpath)
13181         {
13182         case RENDERPATH_GL20:
13183         case RENDERPATH_CGGL:
13184         case RENDERPATH_D3D9:
13185         case RENDERPATH_D3D10:
13186         case RENDERPATH_D3D11:
13187         case RENDERPATH_SOFT:
13188                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13189                 break;
13190         case RENDERPATH_GL13:
13191                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13192                 break;
13193         case RENDERPATH_GL11:
13194                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13195                 break;
13196         }
13197         CHECKGLERROR
13198 }
13199
13200 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
13201 {
13202         CHECKGLERROR
13203         RSurf_SetupDepthAndCulling();
13204         if (r_showsurfaces.integer)
13205         {
13206                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
13207                 return;
13208         }
13209         switch (vid.renderpath)
13210         {
13211         case RENDERPATH_GL20:
13212         case RENDERPATH_CGGL:
13213         case RENDERPATH_D3D9:
13214         case RENDERPATH_D3D10:
13215         case RENDERPATH_D3D11:
13216         case RENDERPATH_SOFT:
13217                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13218                 break;
13219         case RENDERPATH_GL13:
13220                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
13221                 break;
13222         case RENDERPATH_GL11:
13223                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
13224                 break;
13225         }
13226         CHECKGLERROR
13227 }
13228
13229 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13230 {
13231         int i, j;
13232         int texturenumsurfaces, endsurface;
13233         texture_t *texture;
13234         const msurface_t *surface;
13235 #define MAXBATCH_TRANSPARENTSURFACES 256
13236         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
13237
13238         // if the model is static it doesn't matter what value we give for
13239         // wantnormals and wanttangents, so this logic uses only rules applicable
13240         // to a model, knowing that they are meaningless otherwise
13241         if (ent == r_refdef.scene.worldentity)
13242                 RSurf_ActiveWorldEntity();
13243         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13244                 RSurf_ActiveModelEntity(ent, false, false, false);
13245         else
13246         {
13247                 switch (vid.renderpath)
13248                 {
13249                 case RENDERPATH_GL20:
13250                 case RENDERPATH_CGGL:
13251                 case RENDERPATH_D3D9:
13252                 case RENDERPATH_D3D10:
13253                 case RENDERPATH_D3D11:
13254                 case RENDERPATH_SOFT:
13255                         RSurf_ActiveModelEntity(ent, true, true, false);
13256                         break;
13257                 case RENDERPATH_GL13:
13258                 case RENDERPATH_GL11:
13259                         RSurf_ActiveModelEntity(ent, true, false, false);
13260                         break;
13261                 }
13262         }
13263
13264         if (r_transparentdepthmasking.integer)
13265         {
13266                 qboolean setup = false;
13267                 for (i = 0;i < numsurfaces;i = j)
13268                 {
13269                         j = i + 1;
13270                         surface = rsurface.modelsurfaces + surfacelist[i];
13271                         texture = surface->texture;
13272                         rsurface.texture = R_GetCurrentTexture(texture);
13273                         rsurface.lightmaptexture = NULL;
13274                         rsurface.deluxemaptexture = NULL;
13275                         rsurface.uselightmaptexture = false;
13276                         // scan ahead until we find a different texture
13277                         endsurface = min(i + 1024, numsurfaces);
13278                         texturenumsurfaces = 0;
13279                         texturesurfacelist[texturenumsurfaces++] = surface;
13280                         for (;j < endsurface;j++)
13281                         {
13282                                 surface = rsurface.modelsurfaces + surfacelist[j];
13283                                 if (texture != surface->texture)
13284                                         break;
13285                                 texturesurfacelist[texturenumsurfaces++] = surface;
13286                         }
13287                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
13288                                 continue;
13289                         // render the range of surfaces as depth
13290                         if (!setup)
13291                         {
13292                                 setup = true;
13293                                 GL_ColorMask(0,0,0,0);
13294                                 GL_Color(1,1,1,1);
13295                                 GL_DepthTest(true);
13296                                 GL_BlendFunc(GL_ONE, GL_ZERO);
13297                                 GL_DepthMask(true);
13298                                 GL_AlphaTest(false);
13299 //                              R_Mesh_ResetTextureState();
13300                                 R_SetupShader_DepthOrShadow();
13301                         }
13302                         RSurf_SetupDepthAndCulling();
13303                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13304                         if (rsurface.batchvertex3fbuffer)
13305                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13306                         else
13307                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13308                         RSurf_DrawBatch();
13309                 }
13310                 if (setup)
13311                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
13312         }
13313
13314         for (i = 0;i < numsurfaces;i = j)
13315         {
13316                 j = i + 1;
13317                 surface = rsurface.modelsurfaces + surfacelist[i];
13318                 texture = surface->texture;
13319                 rsurface.texture = R_GetCurrentTexture(texture);
13320                 // scan ahead until we find a different texture
13321                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
13322                 texturenumsurfaces = 0;
13323                 texturesurfacelist[texturenumsurfaces++] = surface;
13324                 if(FAKELIGHT_ENABLED)
13325                 {
13326                         rsurface.lightmaptexture = NULL;
13327                         rsurface.deluxemaptexture = NULL;
13328                         rsurface.uselightmaptexture = false;
13329                         for (;j < endsurface;j++)
13330                         {
13331                                 surface = rsurface.modelsurfaces + surfacelist[j];
13332                                 if (texture != surface->texture)
13333                                         break;
13334                                 texturesurfacelist[texturenumsurfaces++] = surface;
13335                         }
13336                 }
13337                 else
13338                 {
13339                         rsurface.lightmaptexture = surface->lightmaptexture;
13340                         rsurface.deluxemaptexture = surface->deluxemaptexture;
13341                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
13342                         for (;j < endsurface;j++)
13343                         {
13344                                 surface = rsurface.modelsurfaces + surfacelist[j];
13345                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
13346                                         break;
13347                                 texturesurfacelist[texturenumsurfaces++] = surface;
13348                         }
13349                 }
13350                 // render the range of surfaces
13351                 if (ent == r_refdef.scene.worldentity)
13352                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13353                 else
13354                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
13355         }
13356         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13357         GL_AlphaTest(false);
13358 }
13359
13360 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
13361 {
13362         // transparent surfaces get pushed off into the transparent queue
13363         int surfacelistindex;
13364         const msurface_t *surface;
13365         vec3_t tempcenter, center;
13366         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
13367         {
13368                 surface = texturesurfacelist[surfacelistindex];
13369                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
13370                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
13371                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
13372                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
13373                 if (queueentity->transparent_offset) // transparent offset
13374                 {
13375                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
13376                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
13377                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
13378                 }
13379                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
13380         }
13381 }
13382
13383 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
13384 {
13385         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
13386                 return;
13387         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
13388                 return;
13389         RSurf_SetupDepthAndCulling();
13390         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
13391         if (rsurface.batchvertex3fbuffer)
13392                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
13393         else
13394                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
13395         RSurf_DrawBatch();
13396 }
13397
13398 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
13399 {
13400         const entity_render_t *queueentity = r_refdef.scene.worldentity;
13401         CHECKGLERROR
13402         if (depthonly)
13403                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13404         else if (prepass)
13405         {
13406                 if (!rsurface.texture->currentnumlayers)
13407                         return;
13408                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13409                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13410                 else
13411                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13412         }
13413         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13414                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13415         else if (!rsurface.texture->currentnumlayers)
13416                 return;
13417         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13418         {
13419                 // in the deferred case, transparent surfaces were queued during prepass
13420                 if (!r_shadow_usingdeferredprepass)
13421                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13422         }
13423         else
13424         {
13425                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13426                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13427         }
13428         CHECKGLERROR
13429 }
13430
13431 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13432 {
13433         int i, j;
13434         texture_t *texture;
13435         R_FrameData_SetMark();
13436         // break the surface list down into batches by texture and use of lightmapping
13437         for (i = 0;i < numsurfaces;i = j)
13438         {
13439                 j = i + 1;
13440                 // texture is the base texture pointer, rsurface.texture is the
13441                 // current frame/skin the texture is directing us to use (for example
13442                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13443                 // use skin 1 instead)
13444                 texture = surfacelist[i]->texture;
13445                 rsurface.texture = R_GetCurrentTexture(texture);
13446                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13447                 {
13448                         // if this texture is not the kind we want, skip ahead to the next one
13449                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13450                                 ;
13451                         continue;
13452                 }
13453                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13454                 {
13455                         rsurface.lightmaptexture = NULL;
13456                         rsurface.deluxemaptexture = NULL;
13457                         rsurface.uselightmaptexture = false;
13458                         // simply scan ahead until we find a different texture or lightmap state
13459                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13460                                 ;
13461                 }
13462                 else
13463                 {
13464                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13465                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13466                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13467                         // simply scan ahead until we find a different texture or lightmap state
13468                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13469                                 ;
13470                 }
13471                 // render the range of surfaces
13472                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
13473         }
13474         R_FrameData_ReturnToMark();
13475 }
13476
13477 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
13478 {
13479         CHECKGLERROR
13480         if (depthonly)
13481                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
13482         else if (prepass)
13483         {
13484                 if (!rsurface.texture->currentnumlayers)
13485                         return;
13486                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
13487                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13488                 else
13489                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
13490         }
13491         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
13492                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
13493         else if (!rsurface.texture->currentnumlayers)
13494                 return;
13495         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
13496         {
13497                 // in the deferred case, transparent surfaces were queued during prepass
13498                 if (!r_shadow_usingdeferredprepass)
13499                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
13500         }
13501         else
13502         {
13503                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
13504                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
13505         }
13506         CHECKGLERROR
13507 }
13508
13509 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
13510 {
13511         int i, j;
13512         texture_t *texture;
13513         R_FrameData_SetMark();
13514         // break the surface list down into batches by texture and use of lightmapping
13515         for (i = 0;i < numsurfaces;i = j)
13516         {
13517                 j = i + 1;
13518                 // texture is the base texture pointer, rsurface.texture is the
13519                 // current frame/skin the texture is directing us to use (for example
13520                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
13521                 // use skin 1 instead)
13522                 texture = surfacelist[i]->texture;
13523                 rsurface.texture = R_GetCurrentTexture(texture);
13524                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
13525                 {
13526                         // if this texture is not the kind we want, skip ahead to the next one
13527                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13528                                 ;
13529                         continue;
13530                 }
13531                 if(FAKELIGHT_ENABLED || depthonly || prepass)
13532                 {
13533                         rsurface.lightmaptexture = NULL;
13534                         rsurface.deluxemaptexture = NULL;
13535                         rsurface.uselightmaptexture = false;
13536                         // simply scan ahead until we find a different texture or lightmap state
13537                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
13538                                 ;
13539                 }
13540                 else
13541                 {
13542                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
13543                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
13544                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
13545                         // simply scan ahead until we find a different texture or lightmap state
13546                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
13547                                 ;
13548                 }
13549                 // render the range of surfaces
13550                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
13551         }
13552         R_FrameData_ReturnToMark();
13553 }
13554
13555 float locboxvertex3f[6*4*3] =
13556 {
13557         1,0,1, 1,0,0, 1,1,0, 1,1,1,
13558         0,1,1, 0,1,0, 0,0,0, 0,0,1,
13559         1,1,1, 1,1,0, 0,1,0, 0,1,1,
13560         0,0,1, 0,0,0, 1,0,0, 1,0,1,
13561         0,0,1, 1,0,1, 1,1,1, 0,1,1,
13562         1,0,0, 0,0,0, 0,1,0, 1,1,0
13563 };
13564
13565 unsigned short locboxelements[6*2*3] =
13566 {
13567          0, 1, 2, 0, 2, 3,
13568          4, 5, 6, 4, 6, 7,
13569          8, 9,10, 8,10,11,
13570         12,13,14, 12,14,15,
13571         16,17,18, 16,18,19,
13572         20,21,22, 20,22,23
13573 };
13574
13575 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
13576 {
13577         int i, j;
13578         cl_locnode_t *loc = (cl_locnode_t *)ent;
13579         vec3_t mins, size;
13580         float vertex3f[6*4*3];
13581         CHECKGLERROR
13582         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13583         GL_DepthMask(false);
13584         GL_DepthRange(0, 1);
13585         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13586         GL_DepthTest(true);
13587         GL_CullFace(GL_NONE);
13588         R_EntityMatrix(&identitymatrix);
13589
13590 //      R_Mesh_ResetTextureState();
13591
13592         i = surfacelist[0];
13593         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13594                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13595                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13596                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13597
13598         if (VectorCompare(loc->mins, loc->maxs))
13599         {
13600                 VectorSet(size, 2, 2, 2);
13601                 VectorMA(loc->mins, -0.5f, size, mins);
13602         }
13603         else
13604         {
13605                 VectorCopy(loc->mins, mins);
13606                 VectorSubtract(loc->maxs, loc->mins, size);
13607         }
13608
13609         for (i = 0;i < 6*4*3;)
13610                 for (j = 0;j < 3;j++, i++)
13611                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13612
13613         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13614         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13615         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13616 }
13617
13618 void R_DrawLocs(void)
13619 {
13620         int index;
13621         cl_locnode_t *loc, *nearestloc;
13622         vec3_t center;
13623         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13624         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13625         {
13626                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13627                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13628         }
13629 }
13630
13631 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13632 {
13633         if (decalsystem->decals)
13634                 Mem_Free(decalsystem->decals);
13635         memset(decalsystem, 0, sizeof(*decalsystem));
13636 }
13637
13638 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)
13639 {
13640         tridecal_t *decal;
13641         tridecal_t *decals;
13642         int i;
13643
13644         // expand or initialize the system
13645         if (decalsystem->maxdecals <= decalsystem->numdecals)
13646         {
13647                 decalsystem_t old = *decalsystem;
13648                 qboolean useshortelements;
13649                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13650                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13651                 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)));
13652                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13653                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13654                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13655                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13656                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13657                 if (decalsystem->numdecals)
13658                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13659                 if (old.decals)
13660                         Mem_Free(old.decals);
13661                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13662                         decalsystem->element3i[i] = i;
13663                 if (useshortelements)
13664                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13665                                 decalsystem->element3s[i] = i;
13666         }
13667
13668         // grab a decal and search for another free slot for the next one
13669         decals = decalsystem->decals;
13670         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13671         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13672                 ;
13673         decalsystem->freedecal = i;
13674         if (decalsystem->numdecals <= i)
13675                 decalsystem->numdecals = i + 1;
13676
13677         // initialize the decal
13678         decal->lived = 0;
13679         decal->triangleindex = triangleindex;
13680         decal->surfaceindex = surfaceindex;
13681         decal->decalsequence = decalsequence;
13682         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13683         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13684         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13685         decal->color4ub[0][3] = 255;
13686         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13687         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13688         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13689         decal->color4ub[1][3] = 255;
13690         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13691         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13692         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13693         decal->color4ub[2][3] = 255;
13694         decal->vertex3f[0][0] = v0[0];
13695         decal->vertex3f[0][1] = v0[1];
13696         decal->vertex3f[0][2] = v0[2];
13697         decal->vertex3f[1][0] = v1[0];
13698         decal->vertex3f[1][1] = v1[1];
13699         decal->vertex3f[1][2] = v1[2];
13700         decal->vertex3f[2][0] = v2[0];
13701         decal->vertex3f[2][1] = v2[1];
13702         decal->vertex3f[2][2] = v2[2];
13703         decal->texcoord2f[0][0] = t0[0];
13704         decal->texcoord2f[0][1] = t0[1];
13705         decal->texcoord2f[1][0] = t1[0];
13706         decal->texcoord2f[1][1] = t1[1];
13707         decal->texcoord2f[2][0] = t2[0];
13708         decal->texcoord2f[2][1] = t2[1];
13709 }
13710
13711 extern cvar_t cl_decals_bias;
13712 extern cvar_t cl_decals_models;
13713 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13714 // baseparms, parms, temps
13715 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)
13716 {
13717         int cornerindex;
13718         int index;
13719         float v[9][3];
13720         const float *vertex3f;
13721         int numpoints;
13722         float points[2][9][3];
13723         float temp[3];
13724         float tc[9][2];
13725         float f;
13726         float c[9][4];
13727         const int *e;
13728
13729         e = rsurface.modelelement3i + 3*triangleindex;
13730
13731         vertex3f = rsurface.modelvertex3f;
13732
13733         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13734         {
13735                 index = 3*e[cornerindex];
13736                 VectorCopy(vertex3f + index, v[cornerindex]);
13737         }
13738         // cull backfaces
13739         //TriangleNormal(v[0], v[1], v[2], normal);
13740         //if (DotProduct(normal, localnormal) < 0.0f)
13741         //      continue;
13742         // clip by each of the box planes formed from the projection matrix
13743         // if anything survives, we emit the decal
13744         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]);
13745         if (numpoints < 3)
13746                 return;
13747         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]);
13748         if (numpoints < 3)
13749                 return;
13750         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]);
13751         if (numpoints < 3)
13752                 return;
13753         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]);
13754         if (numpoints < 3)
13755                 return;
13756         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]);
13757         if (numpoints < 3)
13758                 return;
13759         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]);
13760         if (numpoints < 3)
13761                 return;
13762         // some part of the triangle survived, so we have to accept it...
13763         if (dynamic)
13764         {
13765                 // dynamic always uses the original triangle
13766                 numpoints = 3;
13767                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13768                 {
13769                         index = 3*e[cornerindex];
13770                         VectorCopy(vertex3f + index, v[cornerindex]);
13771                 }
13772         }
13773         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13774         {
13775                 // convert vertex positions to texcoords
13776                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13777                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13778                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13779                 // calculate distance fade from the projection origin
13780                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13781                 f = bound(0.0f, f, 1.0f);
13782                 c[cornerindex][0] = r * f;
13783                 c[cornerindex][1] = g * f;
13784                 c[cornerindex][2] = b * f;
13785                 c[cornerindex][3] = 1.0f;
13786                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13787         }
13788         if (dynamic)
13789                 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);
13790         else
13791                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13792                         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);
13793 }
13794 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)
13795 {
13796         matrix4x4_t projection;
13797         decalsystem_t *decalsystem;
13798         qboolean dynamic;
13799         dp_model_t *model;
13800         const msurface_t *surface;
13801         const msurface_t *surfaces;
13802         const int *surfacelist;
13803         const texture_t *texture;
13804         int numtriangles;
13805         int numsurfacelist;
13806         int surfacelistindex;
13807         int surfaceindex;
13808         int triangleindex;
13809         float localorigin[3];
13810         float localnormal[3];
13811         float localmins[3];
13812         float localmaxs[3];
13813         float localsize;
13814         //float normal[3];
13815         float planes[6][4];
13816         float angles[3];
13817         bih_t *bih;
13818         int bih_triangles_count;
13819         int bih_triangles[256];
13820         int bih_surfaces[256];
13821
13822         decalsystem = &ent->decalsystem;
13823         model = ent->model;
13824         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13825         {
13826                 R_DecalSystem_Reset(&ent->decalsystem);
13827                 return;
13828         }
13829
13830         if (!model->brush.data_leafs && !cl_decals_models.integer)
13831         {
13832                 if (decalsystem->model)
13833                         R_DecalSystem_Reset(decalsystem);
13834                 return;
13835         }
13836
13837         if (decalsystem->model != model)
13838                 R_DecalSystem_Reset(decalsystem);
13839         decalsystem->model = model;
13840
13841         RSurf_ActiveModelEntity(ent, false, false, false);
13842
13843         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13844         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13845         VectorNormalize(localnormal);
13846         localsize = worldsize*rsurface.inversematrixscale;
13847         localmins[0] = localorigin[0] - localsize;
13848         localmins[1] = localorigin[1] - localsize;
13849         localmins[2] = localorigin[2] - localsize;
13850         localmaxs[0] = localorigin[0] + localsize;
13851         localmaxs[1] = localorigin[1] + localsize;
13852         localmaxs[2] = localorigin[2] + localsize;
13853
13854         //VectorCopy(localnormal, planes[4]);
13855         //VectorVectors(planes[4], planes[2], planes[0]);
13856         AnglesFromVectors(angles, localnormal, NULL, false);
13857         AngleVectors(angles, planes[0], planes[2], planes[4]);
13858         VectorNegate(planes[0], planes[1]);
13859         VectorNegate(planes[2], planes[3]);
13860         VectorNegate(planes[4], planes[5]);
13861         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13862         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13863         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13864         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13865         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13866         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13867
13868 #if 1
13869 // works
13870 {
13871         matrix4x4_t forwardprojection;
13872         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13873         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13874 }
13875 #else
13876 // broken
13877 {
13878         float projectionvector[4][3];
13879         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13880         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13881         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13882         projectionvector[0][0] = planes[0][0] * ilocalsize;
13883         projectionvector[0][1] = planes[1][0] * ilocalsize;
13884         projectionvector[0][2] = planes[2][0] * ilocalsize;
13885         projectionvector[1][0] = planes[0][1] * ilocalsize;
13886         projectionvector[1][1] = planes[1][1] * ilocalsize;
13887         projectionvector[1][2] = planes[2][1] * ilocalsize;
13888         projectionvector[2][0] = planes[0][2] * ilocalsize;
13889         projectionvector[2][1] = planes[1][2] * ilocalsize;
13890         projectionvector[2][2] = planes[2][2] * ilocalsize;
13891         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13892         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13893         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13894         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13895 }
13896 #endif
13897
13898         dynamic = model->surfmesh.isanimated;
13899         numsurfacelist = model->nummodelsurfaces;
13900         surfacelist = model->sortedmodelsurfaces;
13901         surfaces = model->data_surfaces;
13902
13903         bih = NULL;
13904         bih_triangles_count = -1;
13905         if(!dynamic)
13906         {
13907                 if(model->render_bih.numleafs)
13908                         bih = &model->render_bih;
13909                 else if(model->collision_bih.numleafs)
13910                         bih = &model->collision_bih;
13911         }
13912         if(bih)
13913                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13914         if(bih_triangles_count == 0)
13915                 return;
13916         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13917                 return;
13918         if(bih_triangles_count > 0)
13919         {
13920                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13921                 {
13922                         surfaceindex = bih_surfaces[triangleindex];
13923                         surface = surfaces + surfaceindex;
13924                         texture = surface->texture;
13925                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13926                                 continue;
13927                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13928                                 continue;
13929                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13930                 }
13931         }
13932         else
13933         {
13934                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13935                 {
13936                         surfaceindex = surfacelist[surfacelistindex];
13937                         surface = surfaces + surfaceindex;
13938                         // check cull box first because it rejects more than any other check
13939                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13940                                 continue;
13941                         // skip transparent surfaces
13942                         texture = surface->texture;
13943                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13944                                 continue;
13945                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13946                                 continue;
13947                         numtriangles = surface->num_triangles;
13948                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13949                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13950                 }
13951         }
13952 }
13953
13954 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13955 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)
13956 {
13957         int renderentityindex;
13958         float worldmins[3];
13959         float worldmaxs[3];
13960         entity_render_t *ent;
13961
13962         if (!cl_decals_newsystem.integer)
13963                 return;
13964
13965         worldmins[0] = worldorigin[0] - worldsize;
13966         worldmins[1] = worldorigin[1] - worldsize;
13967         worldmins[2] = worldorigin[2] - worldsize;
13968         worldmaxs[0] = worldorigin[0] + worldsize;
13969         worldmaxs[1] = worldorigin[1] + worldsize;
13970         worldmaxs[2] = worldorigin[2] + worldsize;
13971
13972         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13973
13974         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13975         {
13976                 ent = r_refdef.scene.entities[renderentityindex];
13977                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13978                         continue;
13979
13980                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13981         }
13982 }
13983
13984 typedef struct r_decalsystem_splatqueue_s
13985 {
13986         vec3_t worldorigin;
13987         vec3_t worldnormal;
13988         float color[4];
13989         float tcrange[4];
13990         float worldsize;
13991         int decalsequence;
13992 }
13993 r_decalsystem_splatqueue_t;
13994
13995 int r_decalsystem_numqueued = 0;
13996 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13997
13998 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)
13999 {
14000         r_decalsystem_splatqueue_t *queue;
14001
14002         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
14003                 return;
14004
14005         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
14006         VectorCopy(worldorigin, queue->worldorigin);
14007         VectorCopy(worldnormal, queue->worldnormal);
14008         Vector4Set(queue->color, r, g, b, a);
14009         Vector4Set(queue->tcrange, s1, t1, s2, t2);
14010         queue->worldsize = worldsize;
14011         queue->decalsequence = cl.decalsequence++;
14012 }
14013
14014 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
14015 {
14016         int i;
14017         r_decalsystem_splatqueue_t *queue;
14018
14019         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
14020                 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);
14021         r_decalsystem_numqueued = 0;
14022 }
14023
14024 extern cvar_t cl_decals_max;
14025 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
14026 {
14027         int i;
14028         decalsystem_t *decalsystem = &ent->decalsystem;
14029         int numdecals;
14030         int killsequence;
14031         tridecal_t *decal;
14032         float frametime;
14033         float lifetime;
14034
14035         if (!decalsystem->numdecals)
14036                 return;
14037
14038         if (r_showsurfaces.integer)
14039                 return;
14040
14041         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14042         {
14043                 R_DecalSystem_Reset(decalsystem);
14044                 return;
14045         }
14046
14047         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
14048         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
14049
14050         if (decalsystem->lastupdatetime)
14051                 frametime = (cl.time - decalsystem->lastupdatetime);
14052         else
14053                 frametime = 0;
14054         decalsystem->lastupdatetime = cl.time;
14055         decal = decalsystem->decals;
14056         numdecals = decalsystem->numdecals;
14057
14058         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14059         {
14060                 if (decal->color4ub[0][3])
14061                 {
14062                         decal->lived += frametime;
14063                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
14064                         {
14065                                 memset(decal, 0, sizeof(*decal));
14066                                 if (decalsystem->freedecal > i)
14067                                         decalsystem->freedecal = i;
14068                         }
14069                 }
14070         }
14071         decal = decalsystem->decals;
14072         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
14073                 numdecals--;
14074
14075         // collapse the array by shuffling the tail decals into the gaps
14076         for (;;)
14077         {
14078                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
14079                         decalsystem->freedecal++;
14080                 if (decalsystem->freedecal == numdecals)
14081                         break;
14082                 decal[decalsystem->freedecal] = decal[--numdecals];
14083         }
14084
14085         decalsystem->numdecals = numdecals;
14086
14087         if (numdecals <= 0)
14088         {
14089                 // if there are no decals left, reset decalsystem
14090                 R_DecalSystem_Reset(decalsystem);
14091         }
14092 }
14093
14094 extern skinframe_t *decalskinframe;
14095 static void R_DrawModelDecals_Entity(entity_render_t *ent)
14096 {
14097         int i;
14098         decalsystem_t *decalsystem = &ent->decalsystem;
14099         int numdecals;
14100         tridecal_t *decal;
14101         float faderate;
14102         float alpha;
14103         float *v3f;
14104         float *c4f;
14105         float *t2f;
14106         const int *e;
14107         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
14108         int numtris = 0;
14109
14110         numdecals = decalsystem->numdecals;
14111         if (!numdecals)
14112                 return;
14113
14114         if (r_showsurfaces.integer)
14115                 return;
14116
14117         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
14118         {
14119                 R_DecalSystem_Reset(decalsystem);
14120                 return;
14121         }
14122
14123         // if the model is static it doesn't matter what value we give for
14124         // wantnormals and wanttangents, so this logic uses only rules applicable
14125         // to a model, knowing that they are meaningless otherwise
14126         if (ent == r_refdef.scene.worldentity)
14127                 RSurf_ActiveWorldEntity();
14128         else
14129                 RSurf_ActiveModelEntity(ent, false, false, false);
14130
14131         decalsystem->lastupdatetime = cl.time;
14132         decal = decalsystem->decals;
14133
14134         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
14135
14136         // update vertex positions for animated models
14137         v3f = decalsystem->vertex3f;
14138         c4f = decalsystem->color4f;
14139         t2f = decalsystem->texcoord2f;
14140         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
14141         {
14142                 if (!decal->color4ub[0][3])
14143                         continue;
14144
14145                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
14146                         continue;
14147
14148                 // update color values for fading decals
14149                 if (decal->lived >= cl_decals_time.value)
14150                 {
14151                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
14152                         alpha *= (1.0f/255.0f);
14153                 }
14154                 else
14155                         alpha = 1.0f/255.0f;
14156
14157                 c4f[ 0] = decal->color4ub[0][0] * alpha;
14158                 c4f[ 1] = decal->color4ub[0][1] * alpha;
14159                 c4f[ 2] = decal->color4ub[0][2] * alpha;
14160                 c4f[ 3] = 1;
14161                 c4f[ 4] = decal->color4ub[1][0] * alpha;
14162                 c4f[ 5] = decal->color4ub[1][1] * alpha;
14163                 c4f[ 6] = decal->color4ub[1][2] * alpha;
14164                 c4f[ 7] = 1;
14165                 c4f[ 8] = decal->color4ub[2][0] * alpha;
14166                 c4f[ 9] = decal->color4ub[2][1] * alpha;
14167                 c4f[10] = decal->color4ub[2][2] * alpha;
14168                 c4f[11] = 1;
14169
14170                 t2f[0] = decal->texcoord2f[0][0];
14171                 t2f[1] = decal->texcoord2f[0][1];
14172                 t2f[2] = decal->texcoord2f[1][0];
14173                 t2f[3] = decal->texcoord2f[1][1];
14174                 t2f[4] = decal->texcoord2f[2][0];
14175                 t2f[5] = decal->texcoord2f[2][1];
14176
14177                 // update vertex positions for animated models
14178                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
14179                 {
14180                         e = rsurface.modelelement3i + 3*decal->triangleindex;
14181                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
14182                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
14183                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
14184                 }
14185                 else
14186                 {
14187                         VectorCopy(decal->vertex3f[0], v3f);
14188                         VectorCopy(decal->vertex3f[1], v3f + 3);
14189                         VectorCopy(decal->vertex3f[2], v3f + 6);
14190                 }
14191
14192                 if (r_refdef.fogenabled)
14193                 {
14194                         alpha = RSurf_FogVertex(v3f);
14195                         VectorScale(c4f, alpha, c4f);
14196                         alpha = RSurf_FogVertex(v3f + 3);
14197                         VectorScale(c4f + 4, alpha, c4f + 4);
14198                         alpha = RSurf_FogVertex(v3f + 6);
14199                         VectorScale(c4f + 8, alpha, c4f + 8);
14200                 }
14201
14202                 v3f += 9;
14203                 c4f += 12;
14204                 t2f += 6;
14205                 numtris++;
14206         }
14207
14208         if (numtris > 0)
14209         {
14210                 r_refdef.stats.drawndecals += numtris;
14211
14212                 // now render the decals all at once
14213                 // (this assumes they all use one particle font texture!)
14214                 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);
14215 //              R_Mesh_ResetTextureState();
14216                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
14217                 GL_DepthMask(false);
14218                 GL_DepthRange(0, 1);
14219                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
14220                 GL_DepthTest(true);
14221                 GL_CullFace(GL_NONE);
14222                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
14223                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
14224                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
14225         }
14226 }
14227
14228 static void R_DrawModelDecals(void)
14229 {
14230         int i, numdecals;
14231
14232         // fade faster when there are too many decals
14233         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14234         for (i = 0;i < r_refdef.scene.numentities;i++)
14235                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14236
14237         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
14238         for (i = 0;i < r_refdef.scene.numentities;i++)
14239                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14240                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
14241
14242         R_DecalSystem_ApplySplatEntitiesQueue();
14243
14244         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
14245         for (i = 0;i < r_refdef.scene.numentities;i++)
14246                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
14247
14248         r_refdef.stats.totaldecals += numdecals;
14249
14250         if (r_showsurfaces.integer)
14251                 return;
14252
14253         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
14254
14255         for (i = 0;i < r_refdef.scene.numentities;i++)
14256         {
14257                 if (!r_refdef.viewcache.entityvisible[i])
14258                         continue;
14259                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
14260                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
14261         }
14262 }
14263
14264 extern cvar_t mod_collision_bih;
14265 void R_DrawDebugModel(void)
14266 {
14267         entity_render_t *ent = rsurface.entity;
14268         int i, j, k, l, flagsmask;
14269         const msurface_t *surface;
14270         dp_model_t *model = ent->model;
14271         vec3_t v;
14272
14273         switch(vid.renderpath)
14274         {
14275         case RENDERPATH_GL11:
14276         case RENDERPATH_GL13:
14277         case RENDERPATH_GL20:
14278         case RENDERPATH_CGGL:
14279                 break;
14280         case RENDERPATH_D3D9:
14281                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14282                 return;
14283         case RENDERPATH_D3D10:
14284                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14285                 return;
14286         case RENDERPATH_D3D11:
14287                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14288                 return;
14289         case RENDERPATH_SOFT:
14290                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
14291                 return;
14292         }
14293
14294         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
14295
14296 //      R_Mesh_ResetTextureState();
14297         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
14298         GL_DepthRange(0, 1);
14299         GL_DepthTest(!r_showdisabledepthtest.integer);
14300         GL_DepthMask(false);
14301         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14302
14303         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
14304         {
14305                 int triangleindex;
14306                 int bihleafindex;
14307                 qboolean cullbox = ent == r_refdef.scene.worldentity;
14308                 const q3mbrush_t *brush;
14309                 const bih_t *bih = &model->collision_bih;
14310                 const bih_leaf_t *bihleaf;
14311                 float vertex3f[3][3];
14312                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
14313                 cullbox = false;
14314                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
14315                 {
14316                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
14317                                 continue;
14318                         switch (bihleaf->type)
14319                         {
14320                         case BIH_BRUSH:
14321                                 brush = model->brush.data_brushes + bihleaf->itemindex;
14322                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
14323                                 {
14324                                         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);
14325                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
14326                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
14327                                 }
14328                                 break;
14329                         case BIH_COLLISIONTRIANGLE:
14330                                 triangleindex = bihleaf->itemindex;
14331                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
14332                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
14333                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
14334                                 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);
14335                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14336                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14337                                 break;
14338                         case BIH_RENDERTRIANGLE:
14339                                 triangleindex = bihleaf->itemindex;
14340                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
14341                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
14342                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
14343                                 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);
14344                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
14345                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
14346                                 break;
14347                         }
14348                 }
14349         }
14350
14351         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
14352
14353         if (r_showtris.integer || (r_shownormals.value != 0))
14354         {
14355                 if (r_showdisabledepthtest.integer)
14356                 {
14357                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
14358                         GL_DepthMask(false);
14359                 }
14360                 else
14361                 {
14362                         GL_BlendFunc(GL_ONE, GL_ZERO);
14363                         GL_DepthMask(true);
14364                 }
14365                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
14366                 {
14367                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
14368                                 continue;
14369                         rsurface.texture = R_GetCurrentTexture(surface->texture);
14370                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
14371                         {
14372                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
14373                                 if (r_showtris.value > 0)
14374                                 {
14375                                         if (!rsurface.texture->currentlayers->depthmask)
14376                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
14377                                         else if (ent == r_refdef.scene.worldentity)
14378                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
14379                                         else
14380                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
14381                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
14382                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
14383                                         RSurf_DrawBatch();
14384                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
14385                                         CHECKGLERROR
14386                                 }
14387                                 if (r_shownormals.value < 0)
14388                                 {
14389                                         qglBegin(GL_LINES);
14390                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14391                                         {
14392                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14393                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14394                                                 qglVertex3f(v[0], v[1], v[2]);
14395                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14396                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14397                                                 qglVertex3f(v[0], v[1], v[2]);
14398                                         }
14399                                         qglEnd();
14400                                         CHECKGLERROR
14401                                 }
14402                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
14403                                 {
14404                                         qglBegin(GL_LINES);
14405                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14406                                         {
14407                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14408                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
14409                                                 qglVertex3f(v[0], v[1], v[2]);
14410                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
14411                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14412                                                 qglVertex3f(v[0], v[1], v[2]);
14413                                         }
14414                                         qglEnd();
14415                                         CHECKGLERROR
14416                                         qglBegin(GL_LINES);
14417                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14418                                         {
14419                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14420                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
14421                                                 qglVertex3f(v[0], v[1], v[2]);
14422                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
14423                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14424                                                 qglVertex3f(v[0], v[1], v[2]);
14425                                         }
14426                                         qglEnd();
14427                                         CHECKGLERROR
14428                                         qglBegin(GL_LINES);
14429                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
14430                                         {
14431                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
14432                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
14433                                                 qglVertex3f(v[0], v[1], v[2]);
14434                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
14435                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
14436                                                 qglVertex3f(v[0], v[1], v[2]);
14437                                         }
14438                                         qglEnd();
14439                                         CHECKGLERROR
14440                                 }
14441                         }
14442                 }
14443                 rsurface.texture = NULL;
14444         }
14445 }
14446
14447 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
14448 int r_maxsurfacelist = 0;
14449 const msurface_t **r_surfacelist = NULL;
14450 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14451 {
14452         int i, j, endj, flagsmask;
14453         dp_model_t *model = r_refdef.scene.worldmodel;
14454         msurface_t *surfaces;
14455         unsigned char *update;
14456         int numsurfacelist = 0;
14457         if (model == NULL)
14458                 return;
14459
14460         if (r_maxsurfacelist < model->num_surfaces)
14461         {
14462                 r_maxsurfacelist = model->num_surfaces;
14463                 if (r_surfacelist)
14464                         Mem_Free((msurface_t**)r_surfacelist);
14465                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14466         }
14467
14468         RSurf_ActiveWorldEntity();
14469
14470         surfaces = model->data_surfaces;
14471         update = model->brushq1.lightmapupdateflags;
14472
14473         // update light styles on this submodel
14474         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14475         {
14476                 model_brush_lightstyleinfo_t *style;
14477                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14478                 {
14479                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14480                         {
14481                                 int *list = style->surfacelist;
14482                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14483                                 for (j = 0;j < style->numsurfaces;j++)
14484                                         update[list[j]] = true;
14485                         }
14486                 }
14487         }
14488
14489         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14490
14491         if (debug)
14492         {
14493                 R_DrawDebugModel();
14494                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14495                 return;
14496         }
14497
14498         rsurface.lightmaptexture = NULL;
14499         rsurface.deluxemaptexture = NULL;
14500         rsurface.uselightmaptexture = false;
14501         rsurface.texture = NULL;
14502         rsurface.rtlight = NULL;
14503         numsurfacelist = 0;
14504         // add visible surfaces to draw list
14505         for (i = 0;i < model->nummodelsurfaces;i++)
14506         {
14507                 j = model->sortedmodelsurfaces[i];
14508                 if (r_refdef.viewcache.world_surfacevisible[j])
14509                         r_surfacelist[numsurfacelist++] = surfaces + j;
14510         }
14511         // update lightmaps if needed
14512         if (model->brushq1.firstrender)
14513         {
14514                 model->brushq1.firstrender = false;
14515                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14516                         if (update[j])
14517                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14518         }
14519         else if (update)
14520         {
14521                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14522                         if (r_refdef.viewcache.world_surfacevisible[j])
14523                                 if (update[j])
14524                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
14525         }
14526         // don't do anything if there were no surfaces
14527         if (!numsurfacelist)
14528         {
14529                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14530                 return;
14531         }
14532         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14533         GL_AlphaTest(false);
14534
14535         // add to stats if desired
14536         if (r_speeds.integer && !skysurfaces && !depthonly)
14537         {
14538                 r_refdef.stats.world_surfaces += numsurfacelist;
14539                 for (j = 0;j < numsurfacelist;j++)
14540                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
14541         }
14542
14543         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14544 }
14545
14546 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
14547 {
14548         int i, j, endj, flagsmask;
14549         dp_model_t *model = ent->model;
14550         msurface_t *surfaces;
14551         unsigned char *update;
14552         int numsurfacelist = 0;
14553         if (model == NULL)
14554                 return;
14555
14556         if (r_maxsurfacelist < model->num_surfaces)
14557         {
14558                 r_maxsurfacelist = model->num_surfaces;
14559                 if (r_surfacelist)
14560                         Mem_Free((msurface_t **)r_surfacelist);
14561                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
14562         }
14563
14564         // if the model is static it doesn't matter what value we give for
14565         // wantnormals and wanttangents, so this logic uses only rules applicable
14566         // to a model, knowing that they are meaningless otherwise
14567         if (ent == r_refdef.scene.worldentity)
14568                 RSurf_ActiveWorldEntity();
14569         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
14570                 RSurf_ActiveModelEntity(ent, false, false, false);
14571         else if (prepass)
14572                 RSurf_ActiveModelEntity(ent, true, true, true);
14573         else if (depthonly)
14574         {
14575                 switch (vid.renderpath)
14576                 {
14577                 case RENDERPATH_GL20:
14578                 case RENDERPATH_CGGL:
14579                 case RENDERPATH_D3D9:
14580                 case RENDERPATH_D3D10:
14581                 case RENDERPATH_D3D11:
14582                 case RENDERPATH_SOFT:
14583                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14584                         break;
14585                 case RENDERPATH_GL13:
14586                 case RENDERPATH_GL11:
14587                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14588                         break;
14589                 }
14590         }
14591         else
14592         {
14593                 switch (vid.renderpath)
14594                 {
14595                 case RENDERPATH_GL20:
14596                 case RENDERPATH_CGGL:
14597                 case RENDERPATH_D3D9:
14598                 case RENDERPATH_D3D10:
14599                 case RENDERPATH_D3D11:
14600                 case RENDERPATH_SOFT:
14601                         RSurf_ActiveModelEntity(ent, true, true, false);
14602                         break;
14603                 case RENDERPATH_GL13:
14604                 case RENDERPATH_GL11:
14605                         RSurf_ActiveModelEntity(ent, true, false, false);
14606                         break;
14607                 }
14608         }
14609
14610         surfaces = model->data_surfaces;
14611         update = model->brushq1.lightmapupdateflags;
14612
14613         // update light styles
14614         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14615         {
14616                 model_brush_lightstyleinfo_t *style;
14617                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14618                 {
14619                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14620                         {
14621                                 int *list = style->surfacelist;
14622                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14623                                 for (j = 0;j < style->numsurfaces;j++)
14624                                         update[list[j]] = true;
14625                         }
14626                 }
14627         }
14628
14629         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14630
14631         if (debug)
14632         {
14633                 R_DrawDebugModel();
14634                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14635                 return;
14636         }
14637
14638         rsurface.lightmaptexture = NULL;
14639         rsurface.deluxemaptexture = NULL;
14640         rsurface.uselightmaptexture = false;
14641         rsurface.texture = NULL;
14642         rsurface.rtlight = NULL;
14643         numsurfacelist = 0;
14644         // add visible surfaces to draw list
14645         for (i = 0;i < model->nummodelsurfaces;i++)
14646                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14647         // don't do anything if there were no surfaces
14648         if (!numsurfacelist)
14649         {
14650                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14651                 return;
14652         }
14653         // update lightmaps if needed
14654         if (update)
14655         {
14656                 int updated = 0;
14657                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14658                 {
14659                         if (update[j])
14660                         {
14661                                 updated++;
14662                                 R_BuildLightMap(ent, surfaces + j);
14663                         }
14664                 }
14665         }
14666         if (update)
14667                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14668                         if (update[j])
14669                                 R_BuildLightMap(ent, surfaces + j);
14670         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14671         GL_AlphaTest(false);
14672
14673         // add to stats if desired
14674         if (r_speeds.integer && !skysurfaces && !depthonly)
14675         {
14676                 r_refdef.stats.entities_surfaces += numsurfacelist;
14677                 for (j = 0;j < numsurfacelist;j++)
14678                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14679         }
14680
14681         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14682 }
14683
14684 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14685 {
14686         static texture_t texture;
14687         static msurface_t surface;
14688         const msurface_t *surfacelist = &surface;
14689
14690         // fake enough texture and surface state to render this geometry
14691
14692         texture.update_lastrenderframe = -1; // regenerate this texture
14693         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14694         texture.currentskinframe = skinframe;
14695         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14696         texture.offsetmapping = OFFSETMAPPING_OFF;
14697         texture.offsetscale = 1;
14698         texture.specularscalemod = 1;
14699         texture.specularpowermod = 1;
14700
14701         surface.texture = &texture;
14702         surface.num_triangles = numtriangles;
14703         surface.num_firsttriangle = firsttriangle;
14704         surface.num_vertices = numvertices;
14705         surface.num_firstvertex = firstvertex;
14706
14707         // now render it
14708         rsurface.texture = R_GetCurrentTexture(surface.texture);
14709         rsurface.lightmaptexture = NULL;
14710         rsurface.deluxemaptexture = NULL;
14711         rsurface.uselightmaptexture = false;
14712         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14713 }
14714
14715 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)
14716 {
14717         static msurface_t surface;
14718         const msurface_t *surfacelist = &surface;
14719
14720         // fake enough texture and surface state to render this geometry
14721         surface.texture = texture;
14722         surface.num_triangles = numtriangles;
14723         surface.num_firsttriangle = firsttriangle;
14724         surface.num_vertices = numvertices;
14725         surface.num_firstvertex = firstvertex;
14726
14727         // now render it
14728         rsurface.texture = R_GetCurrentTexture(surface.texture);
14729         rsurface.lightmaptexture = NULL;
14730         rsurface.deluxemaptexture = NULL;
14731         rsurface.uselightmaptexture = false;
14732         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14733 }