]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
removed r_shadow_particletrace code and shader because it was never
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
120
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
132
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
156
157 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
187
188 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"};
189
190 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"};
191
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
193
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 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"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 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)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
203
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 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"};
206
207 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)"};
208
209 extern cvar_t v_glslgamma;
210
211 extern qboolean v_flipped_state;
212
213 static struct r_bloomstate_s
214 {
215         qboolean enabled;
216         qboolean hdr;
217
218         int bloomwidth, bloomheight;
219
220         int screentexturewidth, screentextureheight;
221         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
222
223         int bloomtexturewidth, bloomtextureheight;
224         rtexture_t *texture_bloom;
225
226         // arrays for rendering the screen passes
227         float screentexcoord2f[8];
228         float bloomtexcoord2f[8];
229         float offsettexcoord2f[8];
230
231         r_viewport_t viewport;
232 }
233 r_bloomstate;
234
235 r_waterstate_t r_waterstate;
236
237 /// shadow volume bsp struct with automatically growing nodes buffer
238 svbsp_t r_svbsp;
239
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
253
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
256 {
257         char basename[64];
258         rtexture_t *texture;
259 }
260 cubemapinfo_t;
261
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
264
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
268
269 typedef struct r_qwskincache_s
270 {
271         char name[MAX_QPATH];
272         skinframe_t *skinframe;
273 }
274 r_qwskincache_t;
275
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
278
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
283 {
284         0, 0, 0,
285         1, 0, 0,
286         1, 1, 0,
287         0, 1, 0
288 };
289 const float r_d3dscreenvertex3f[12] =
290 {
291         0, 1, 0,
292         1, 1, 0,
293         1, 0, 0,
294         0, 0, 0
295 };
296
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
298 {
299         int i;
300         for (i = 0;i < verts;i++)
301         {
302                 out[0] = in[0] * r;
303                 out[1] = in[1] * g;
304                 out[2] = in[2] * b;
305                 out[3] = in[3];
306                 in += 4;
307                 out += 4;
308         }
309 }
310
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
312 {
313         int i;
314         for (i = 0;i < verts;i++)
315         {
316                 out[0] = r;
317                 out[1] = g;
318                 out[2] = b;
319                 out[3] = a;
320                 out += 4;
321         }
322 }
323
324 // FIXME: move this to client?
325 void FOG_clear(void)
326 {
327         if (gamemode == GAME_NEHAHRA)
328         {
329                 Cvar_Set("gl_fogenable", "0");
330                 Cvar_Set("gl_fogdensity", "0.2");
331                 Cvar_Set("gl_fogred", "0.3");
332                 Cvar_Set("gl_foggreen", "0.3");
333                 Cvar_Set("gl_fogblue", "0.3");
334         }
335         r_refdef.fog_density = 0;
336         r_refdef.fog_red = 0;
337         r_refdef.fog_green = 0;
338         r_refdef.fog_blue = 0;
339         r_refdef.fog_alpha = 1;
340         r_refdef.fog_start = 0;
341         r_refdef.fog_end = 16384;
342         r_refdef.fog_height = 1<<30;
343         r_refdef.fog_fadedepth = 128;
344         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
345 }
346
347 static void R_BuildBlankTextures(void)
348 {
349         unsigned char data[4];
350         data[2] = 128; // normal X
351         data[1] = 128; // normal Y
352         data[0] = 255; // normal Z
353         data[3] = 128; // height
354         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
355         data[0] = 255;
356         data[1] = 255;
357         data[2] = 255;
358         data[3] = 255;
359         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360         data[0] = 128;
361         data[1] = 128;
362         data[2] = 128;
363         data[3] = 255;
364         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 0;
366         data[1] = 0;
367         data[2] = 0;
368         data[3] = 255;
369         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370 }
371
372 static void R_BuildNoTexture(void)
373 {
374         int x, y;
375         unsigned char pix[16][16][4];
376         // this makes a light grey/dark grey checkerboard texture
377         for (y = 0;y < 16;y++)
378         {
379                 for (x = 0;x < 16;x++)
380                 {
381                         if ((y < 8) ^ (x < 8))
382                         {
383                                 pix[y][x][0] = 128;
384                                 pix[y][x][1] = 128;
385                                 pix[y][x][2] = 128;
386                                 pix[y][x][3] = 255;
387                         }
388                         else
389                         {
390                                 pix[y][x][0] = 64;
391                                 pix[y][x][1] = 64;
392                                 pix[y][x][2] = 64;
393                                 pix[y][x][3] = 255;
394                         }
395                 }
396         }
397         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
398 }
399
400 static void R_BuildWhiteCube(void)
401 {
402         unsigned char data[6*1*1*4];
403         memset(data, 255, sizeof(data));
404         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
405 }
406
407 static void R_BuildNormalizationCube(void)
408 {
409         int x, y, side;
410         vec3_t v;
411         vec_t s, t, intensity;
412 #define NORMSIZE 64
413         unsigned char *data;
414         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415         for (side = 0;side < 6;side++)
416         {
417                 for (y = 0;y < NORMSIZE;y++)
418                 {
419                         for (x = 0;x < NORMSIZE;x++)
420                         {
421                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423                                 switch(side)
424                                 {
425                                 default:
426                                 case 0:
427                                         v[0] = 1;
428                                         v[1] = -t;
429                                         v[2] = -s;
430                                         break;
431                                 case 1:
432                                         v[0] = -1;
433                                         v[1] = -t;
434                                         v[2] = s;
435                                         break;
436                                 case 2:
437                                         v[0] = s;
438                                         v[1] = 1;
439                                         v[2] = t;
440                                         break;
441                                 case 3:
442                                         v[0] = s;
443                                         v[1] = -1;
444                                         v[2] = -t;
445                                         break;
446                                 case 4:
447                                         v[0] = s;
448                                         v[1] = -t;
449                                         v[2] = 1;
450                                         break;
451                                 case 5:
452                                         v[0] = -s;
453                                         v[1] = -t;
454                                         v[2] = -1;
455                                         break;
456                                 }
457                                 intensity = 127.0f / sqrt(DotProduct(v, v));
458                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461                                 data[((side*64+y)*64+x)*4+3] = 255;
462                         }
463                 }
464         }
465         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
466         Mem_Free(data);
467 }
468
469 static void R_BuildFogTexture(void)
470 {
471         int x, b;
472 #define FOGWIDTH 256
473         unsigned char data1[FOGWIDTH][4];
474         //unsigned char data2[FOGWIDTH][4];
475         double d, r, alpha;
476
477         r_refdef.fogmasktable_start = r_refdef.fog_start;
478         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479         r_refdef.fogmasktable_range = r_refdef.fogrange;
480         r_refdef.fogmasktable_density = r_refdef.fog_density;
481
482         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
484         {
485                 d = (x * r - r_refdef.fogmasktable_start);
486                 if(developer_extra.integer)
487                         Con_DPrintf("%f ", d);
488                 d = max(0, d);
489                 if (r_fog_exp2.integer)
490                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
491                 else
492                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493                 if(developer_extra.integer)
494                         Con_DPrintf(" : %f ", alpha);
495                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496                 if(developer_extra.integer)
497                         Con_DPrintf(" = %f\n", alpha);
498                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
499         }
500
501         for (x = 0;x < FOGWIDTH;x++)
502         {
503                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
504                 data1[x][0] = b;
505                 data1[x][1] = b;
506                 data1[x][2] = b;
507                 data1[x][3] = 255;
508                 //data2[x][0] = 255 - b;
509                 //data2[x][1] = 255 - b;
510                 //data2[x][2] = 255 - b;
511                 //data2[x][3] = 255;
512         }
513         if (r_texture_fogattenuation)
514         {
515                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
517         }
518         else
519         {
520                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
522         }
523 }
524
525 static void R_BuildFogHeightTexture(void)
526 {
527         unsigned char *inpixels;
528         int size;
529         int x;
530         int y;
531         int j;
532         float c[4];
533         float f;
534         inpixels = NULL;
535         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536         if (r_refdef.fogheighttexturename[0])
537                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
538         if (!inpixels)
539         {
540                 r_refdef.fog_height_tablesize = 0;
541                 if (r_texture_fogheighttexture)
542                         R_FreeTexture(r_texture_fogheighttexture);
543                 r_texture_fogheighttexture = NULL;
544                 if (r_refdef.fog_height_table2d)
545                         Mem_Free(r_refdef.fog_height_table2d);
546                 r_refdef.fog_height_table2d = NULL;
547                 if (r_refdef.fog_height_table1d)
548                         Mem_Free(r_refdef.fog_height_table1d);
549                 r_refdef.fog_height_table1d = NULL;
550                 return;
551         }
552         size = image_width;
553         r_refdef.fog_height_tablesize = size;
554         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
557         Mem_Free(inpixels);
558         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
559         // average fog color table accounting for every fog layer between a point
560         // and the camera.  (Note: attenuation is handled separately!)
561         for (y = 0;y < size;y++)
562         {
563                 for (x = 0;x < size;x++)
564                 {
565                         Vector4Clear(c);
566                         f = 0;
567                         if (x < y)
568                         {
569                                 for (j = x;j <= y;j++)
570                                 {
571                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
572                                         f++;
573                                 }
574                         }
575                         else
576                         {
577                                 for (j = x;j >= y;j--)
578                                 {
579                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
580                                         f++;
581                                 }
582                         }
583                         f = 1.0f / f;
584                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
588                 }
589         }
590         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
591 }
592
593 //=======================================================================================================================================================
594
595 static const char *builtinshaderstring =
596 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
597 "// written by Forest 'LordHavoc' Hale\n"
598 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
599 "\n"
600 "// GL ES shaders use precision modifiers, standard GL does not\n"
601 "#ifndef GL_ES\n"
602 "#define lowp\n"
603 "#define mediump\n"
604 "#define highp\n"
605 "#endif\n"
606 "\n"
607 "#ifdef VERTEX_SHADER\n"
608 "attribute vec4 Attrib_Position;  // vertex\n"
609 "attribute vec4 Attrib_Color;     // color\n"
610 "attribute vec4 Attrib_TexCoord0; // material texcoords\n"
611 "attribute vec3 Attrib_TexCoord1; // svector\n"
612 "attribute vec3 Attrib_TexCoord2; // tvector\n"
613 "attribute vec3 Attrib_TexCoord3; // normal\n"
614 "attribute vec4 Attrib_TexCoord4; // lightmap texcoords\n"
615 "#endif\n"
616 "varying lowp vec4 VertexColor;\n"
617 "\n"
618 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
619 "# define USEFOG\n"
620 "#endif\n"
621 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
622 "#define USELIGHTMAP\n"
623 "#endif\n"
624 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
625 "#define USEEYEVECTOR\n"
626 "#endif\n"
627 "\n"
628 "#ifdef USESHADOWMAP2D\n"
629 "# ifdef GL_EXT_gpu_shader4\n"
630 "#   extension GL_EXT_gpu_shader4 : enable\n"
631 "# endif\n"
632 "# ifdef GL_ARB_texture_gather\n"
633 "#   extension GL_ARB_texture_gather : enable\n"
634 "# else\n"
635 "#   ifdef GL_AMD_texture_texture4\n"
636 "#     extension GL_AMD_texture_texture4 : enable\n"
637 "#   endif\n"
638 "# endif\n"
639 "#endif\n"
640 "\n"
641 "//#ifdef USESHADOWSAMPLER\n"
642 "//# extension GL_ARB_shadow : enable\n"
643 "//#endif\n"
644 "\n"
645 "//#ifdef __GLSL_CG_DATA_TYPES\n"
646 "//# define myhalf half\n"
647 "//# define myhalf2 half2\n"
648 "//# define myhalf3 half3\n"
649 "//# define myhalf4 half4\n"
650 "//#else\n"
651 "# define myhalf mediump float\n"
652 "# define myhalf2 mediump vec2\n"
653 "# define myhalf3 mediump vec3\n"
654 "# define myhalf4 mediump vec4\n"
655 "//#endif\n"
656 "\n"
657 "#ifdef VERTEX_SHADER\n"
658 "uniform highp mat4 ModelViewProjectionMatrix;\n"
659 "#endif\n"
660 "\n"
661 "#ifdef MODE_DEPTH_OR_SHADOW\n"
662 "#ifdef VERTEX_SHADER\n"
663 "void main(void)\n"
664 "{\n"
665 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
666 "}\n"
667 "#endif\n"
668 "#else // !MODE_DEPTH_ORSHADOW\n"
669 "\n"
670 "\n"
671 "\n"
672 "\n"
673 "#ifdef MODE_SHOWDEPTH\n"
674 "#ifdef VERTEX_SHADER\n"
675 "void main(void)\n"
676 "{\n"
677 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
678 "       VertexColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
679 "}\n"
680 "#endif\n"
681 "\n"
682 "#ifdef FRAGMENT_SHADER\n"
683 "void main(void)\n"
684 "{\n"
685 "       gl_FragColor = VertexColor;\n"
686 "}\n"
687 "#endif\n"
688 "#else // !MODE_SHOWDEPTH\n"
689 "\n"
690 "\n"
691 "\n"
692 "\n"
693 "#ifdef MODE_POSTPROCESS\n"
694 "varying mediump vec2 TexCoord1;\n"
695 "varying mediump vec2 TexCoord2;\n"
696 "\n"
697 "#ifdef VERTEX_SHADER\n"
698 "void main(void)\n"
699 "{\n"
700 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
701 "       TexCoord1 = Attrib_TexCoord0.xy;\n"
702 "#ifdef USEBLOOM\n"
703 "       TexCoord2 = Attrib_TexCoord4.xy;\n"
704 "#endif\n"
705 "}\n"
706 "#endif\n"
707 "\n"
708 "#ifdef FRAGMENT_SHADER\n"
709 "uniform sampler2D Texture_First;\n"
710 "#ifdef USEBLOOM\n"
711 "uniform sampler2D Texture_Second;\n"
712 "uniform lowp vec4 BloomColorSubtract;\n"
713 "#endif\n"
714 "#ifdef USEGAMMARAMPS\n"
715 "uniform sampler2D Texture_GammaRamps;\n"
716 "#endif\n"
717 "#ifdef USESATURATION\n"
718 "uniform lowp float Saturation;\n"
719 "#endif\n"
720 "#ifdef USEVIEWTINT\n"
721 "uniform lowp vec4 ViewTintColor;\n"
722 "#endif\n"
723 "//uncomment these if you want to use them:\n"
724 "uniform mediump vec4 UserVec1;\n"
725 "uniform mediump vec4 UserVec2;\n"
726 "// uniform mediump vec4 UserVec3;\n"
727 "// uniform mediump vec4 UserVec4;\n"
728 "// uniform highp float ClientTime;\n"
729 "uniform mediump vec2 PixelSize;\n"
730 "void main(void)\n"
731 "{\n"
732 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
733 "#ifdef USEBLOOM\n"
734 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
735 "#endif\n"
736 "#ifdef USEVIEWTINT\n"
737 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
738 "#endif\n"
739 "\n"
740 "#ifdef USEPOSTPROCESSING\n"
741 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
742 "// 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"
743 "       float sobel = 1.0;\n"
744 "       // vec2 ts = textureSize(Texture_First, 0);\n"
745 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
746 "       vec2 px = PixelSize;\n"
747 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
748 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
749 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
750 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
751 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
752 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
753 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
754 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
755 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
756 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
757 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
758 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
759 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
760 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
761 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
762 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
763 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
764 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
765 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
766 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
767 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
768 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
769 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
770 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
771 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
772 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
773 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
774 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
775 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
776 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
777 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
778 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
779 "#endif\n"
780 "\n"
781 "#ifdef USESATURATION\n"
782 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
783 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
784 "       // 'vampire sight' effect, wheres red is compensated\n"
785 "       #ifdef SATURATION_REDCOMPENSATE\n"
786 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
787 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
788 "               gl_FragColor.r += rboost;\n"
789 "       #else\n"
790 "               // normal desaturation\n"
791 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
792 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
793 "       #endif\n"
794 "#endif\n"
795 "\n"
796 "#ifdef USEGAMMARAMPS\n"
797 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
798 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
799 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
800 "#endif\n"
801 "}\n"
802 "#endif\n"
803 "#else // !MODE_POSTPROCESS\n"
804 "\n"
805 "\n"
806 "\n"
807 "\n"
808 "#ifdef MODE_GENERIC\n"
809 "#ifdef USEDIFFUSE\n"
810 "varying mediump vec2 TexCoord1;\n"
811 "#endif\n"
812 "#ifdef USESPECULAR\n"
813 "varying mediump vec2 TexCoord2;\n"
814 "#endif\n"
815 "#ifdef VERTEX_SHADER\n"
816 "void main(void)\n"
817 "{\n"
818 "       VertexColor = Attrib_Color;\n"
819 "#ifdef USEDIFFUSE\n"
820 "       TexCoord1 = Attrib_TexCoord0.xy;\n"
821 "#endif\n"
822 "#ifdef USESPECULAR\n"
823 "       TexCoord2 = Attrib_TexCoord1.xy;\n"
824 "#endif\n"
825 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
826 "}\n"
827 "#endif\n"
828 "\n"
829 "#ifdef FRAGMENT_SHADER\n"
830 "#ifdef USEDIFFUSE\n"
831 "uniform sampler2D Texture_First;\n"
832 "#endif\n"
833 "#ifdef USESPECULAR\n"
834 "uniform sampler2D Texture_Second;\n"
835 "#endif\n"
836 "\n"
837 "void main(void)\n"
838 "{\n"
839 "#ifdef USEVIEWTINT\n"
840 "       gl_FragColor = VertexColor;\n"
841 "#else\n"
842 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
843 "#endif\n"
844 "#ifdef USEDIFFUSE\n"
845 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
846 "#endif\n"
847 "\n"
848 "#ifdef USESPECULAR\n"
849 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
850 "# ifdef USECOLORMAPPING\n"
851 "       gl_FragColor *= tex2;\n"
852 "# endif\n"
853 "# ifdef USEGLOW\n"
854 "       gl_FragColor += tex2;\n"
855 "# endif\n"
856 "# ifdef USEVERTEXTEXTUREBLEND\n"
857 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
858 "# endif\n"
859 "#endif\n"
860 "}\n"
861 "#endif\n"
862 "#else // !MODE_GENERIC\n"
863 "\n"
864 "\n"
865 "\n"
866 "\n"
867 "#ifdef MODE_BLOOMBLUR\n"
868 "varying mediump vec2 TexCoord;\n"
869 "#ifdef VERTEX_SHADER\n"
870 "void main(void)\n"
871 "{\n"
872 "       VertexColor = Attrib_Color;\n"
873 "       TexCoord = Attrib_TexCoord0.xy;\n"
874 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
875 "}\n"
876 "#endif\n"
877 "\n"
878 "#ifdef FRAGMENT_SHADER\n"
879 "uniform sampler2D Texture_First;\n"
880 "uniform mediump vec4 BloomBlur_Parameters;\n"
881 "\n"
882 "void main(void)\n"
883 "{\n"
884 "       int i;\n"
885 "       vec2 tc = TexCoord;\n"
886 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
887 "       tc += BloomBlur_Parameters.xy;\n"
888 "       for (i = 1;i < SAMPLES;i++)\n"
889 "       {\n"
890 "               color += texture2D(Texture_First, tc).rgb;\n"
891 "               tc += BloomBlur_Parameters.xy;\n"
892 "       }\n"
893 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
894 "}\n"
895 "#endif\n"
896 "#else // !MODE_BLOOMBLUR\n"
897 "#ifdef MODE_REFRACTION\n"
898 "varying mediump vec2 TexCoord;\n"
899 "varying highp vec4 ModelViewProjectionPosition;\n"
900 "uniform highp mat4 TexMatrix;\n"
901 "#ifdef VERTEX_SHADER\n"
902 "\n"
903 "void main(void)\n"
904 "{\n"
905 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
906 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
907 "       ModelViewProjectionPosition = gl_Position;\n"
908 "}\n"
909 "#endif\n"
910 "\n"
911 "#ifdef FRAGMENT_SHADER\n"
912 "uniform sampler2D Texture_Normal;\n"
913 "uniform sampler2D Texture_Refraction;\n"
914 "uniform sampler2D Texture_Reflection;\n"
915 "\n"
916 "uniform mediump vec4 DistortScaleRefractReflect;\n"
917 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
918 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
919 "uniform lowp vec4 RefractColor;\n"
920 "uniform lowp vec4 ReflectColor;\n"
921 "uniform mediump float ReflectFactor;\n"
922 "uniform mediump float ReflectOffset;\n"
923 "\n"
924 "void main(void)\n"
925 "{\n"
926 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
927 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
928 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
929 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
930 "       // FIXME temporary hack to detect the case that the reflection\n"
931 "       // gets blackened at edges due to leaving the area that contains actual\n"
932 "       // content.\n"
933 "       // Remove this 'ack once we have a better way to stop this thing from\n"
934 "       // 'appening.\n"
935 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
936 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
937 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
938 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
939 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
940 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
941 "}\n"
942 "#endif\n"
943 "#else // !MODE_REFRACTION\n"
944 "\n"
945 "\n"
946 "\n"
947 "\n"
948 "#ifdef MODE_WATER\n"
949 "varying mediump vec2 TexCoord;\n"
950 "varying highp vec3 EyeVector;\n"
951 "varying highp vec4 ModelViewProjectionPosition;\n"
952 "#ifdef VERTEX_SHADER\n"
953 "uniform highp vec3 EyePosition;\n"
954 "uniform highp mat4 TexMatrix;\n"
955 "\n"
956 "void main(void)\n"
957 "{\n"
958 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
959 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
960 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
961 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
962 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
963 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
964 "       ModelViewProjectionPosition = gl_Position;\n"
965 "}\n"
966 "#endif\n"
967 "\n"
968 "#ifdef FRAGMENT_SHADER\n"
969 "uniform sampler2D Texture_Normal;\n"
970 "uniform sampler2D Texture_Refraction;\n"
971 "uniform sampler2D Texture_Reflection;\n"
972 "\n"
973 "uniform mediump vec4 DistortScaleRefractReflect;\n"
974 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
975 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
976 "uniform lowp vec4 RefractColor;\n"
977 "uniform lowp vec4 ReflectColor;\n"
978 "uniform mediump float ReflectFactor;\n"
979 "uniform mediump float ReflectOffset;\n"
980 "uniform highp float ClientTime;\n"
981 "#ifdef USENORMALMAPSCROLLBLEND\n"
982 "uniform highp vec2 NormalmapScrollBlend;\n"
983 "#endif\n"
984 "\n"
985 "void main(void)\n"
986 "{\n"
987 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
988 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
989 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
990 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
991 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
992 "       #ifdef USENORMALMAPSCROLLBLEND\n"
993 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
994 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
995 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
996 "       #else\n"
997 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
998 "       #endif\n"
999 "       // FIXME temporary hack to detect the case that the reflection\n"
1000 "       // gets blackened at edges due to leaving the area that contains actual\n"
1001 "       // content.\n"
1002 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1003 "       // 'appening.\n"
1004 "       float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
1005 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
1006 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
1007 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
1008 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1009 "       f  = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
1010 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
1011 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
1012 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
1013 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1014 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1015 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
1016 "}\n"
1017 "#endif\n"
1018 "#else // !MODE_WATER\n"
1019 "\n"
1020 "\n"
1021 "\n"
1022 "\n"
1023 "// common definitions between vertex shader and fragment shader:\n"
1024 "\n"
1025 "varying mediump vec2 TexCoord;\n"
1026 "#ifdef USEVERTEXTEXTUREBLEND\n"
1027 "varying mediump vec2 TexCoord2;\n"
1028 "#endif\n"
1029 "#ifdef USELIGHTMAP\n"
1030 "varying mediump vec2 TexCoordLightmap;\n"
1031 "#endif\n"
1032 "\n"
1033 "#ifdef MODE_LIGHTSOURCE\n"
1034 "varying mediump vec3 CubeVector;\n"
1035 "#endif\n"
1036 "\n"
1037 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1038 "varying mediump vec3 LightVector;\n"
1039 "#endif\n"
1040 "\n"
1041 "#ifdef USEEYEVECTOR\n"
1042 "varying highp vec3 EyeVector;\n"
1043 "#endif\n"
1044 "#ifdef USEFOG\n"
1045 "varying highp vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1046 "#endif\n"
1047 "\n"
1048 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1049 "varying lowp vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1050 "varying lowp vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1051 "varying lowp vec3 VectorR; // direction of R texcoord (surface normal)\n"
1052 "#endif\n"
1053 "\n"
1054 "#ifdef USEREFLECTION\n"
1055 "varying highp vec4 ModelViewProjectionPosition;\n"
1056 "#endif\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform highp vec3 LightPosition;\n"
1059 "varying highp vec4 ModelViewPosition;\n"
1060 "#endif\n"
1061 "\n"
1062 "#ifdef MODE_LIGHTSOURCE\n"
1063 "uniform highp vec3 LightPosition;\n"
1064 "#endif\n"
1065 "uniform highp vec3 EyePosition;\n"
1066 "#ifdef MODE_LIGHTDIRECTION\n"
1067 "uniform highp vec3 LightDir;\n"
1068 "#endif\n"
1069 "uniform highp vec4 FogPlane;\n"
1070 "\n"
1071 "#ifdef USESHADOWMAPORTHO\n"
1072 "varying mediump vec3 ShadowMapTC;\n"
1073 "#endif\n"
1074 "\n"
1075 "#ifdef USEBOUNCEGRID\n"
1076 "varying mediump vec3 BounceGridTexCoord;\n"
1077 "#endif\n"
1078 "\n"
1079 "\n"
1080 "\n"
1081 "\n"
1082 "\n"
1083 "\n"
1084 "// 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"
1085 "\n"
1086 "// fragment shader specific:\n"
1087 "#ifdef FRAGMENT_SHADER\n"
1088 "\n"
1089 "uniform sampler2D Texture_Normal;\n"
1090 "uniform sampler2D Texture_Color;\n"
1091 "uniform sampler2D Texture_Gloss;\n"
1092 "#ifdef USEGLOW\n"
1093 "uniform sampler2D Texture_Glow;\n"
1094 "#endif\n"
1095 "#ifdef USEVERTEXTEXTUREBLEND\n"
1096 "uniform sampler2D Texture_SecondaryNormal;\n"
1097 "uniform sampler2D Texture_SecondaryColor;\n"
1098 "uniform sampler2D Texture_SecondaryGloss;\n"
1099 "#ifdef USEGLOW\n"
1100 "uniform sampler2D Texture_SecondaryGlow;\n"
1101 "#endif\n"
1102 "#endif\n"
1103 "#ifdef USECOLORMAPPING\n"
1104 "uniform sampler2D Texture_Pants;\n"
1105 "uniform sampler2D Texture_Shirt;\n"
1106 "#endif\n"
1107 "#ifdef USEFOG\n"
1108 "#ifdef USEFOGHEIGHTTEXTURE\n"
1109 "uniform sampler2D Texture_FogHeightTexture;\n"
1110 "#endif\n"
1111 "uniform sampler2D Texture_FogMask;\n"
1112 "#endif\n"
1113 "#ifdef USELIGHTMAP\n"
1114 "uniform sampler2D Texture_Lightmap;\n"
1115 "#endif\n"
1116 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1117 "uniform sampler2D Texture_Deluxemap;\n"
1118 "#endif\n"
1119 "#ifdef USEREFLECTION\n"
1120 "uniform sampler2D Texture_Reflection;\n"
1121 "#endif\n"
1122 "\n"
1123 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1124 "uniform sampler2D Texture_ScreenDepth;\n"
1125 "uniform sampler2D Texture_ScreenNormalMap;\n"
1126 "#endif\n"
1127 "#ifdef USEDEFERREDLIGHTMAP\n"
1128 "uniform sampler2D Texture_ScreenDiffuse;\n"
1129 "uniform sampler2D Texture_ScreenSpecular;\n"
1130 "#endif\n"
1131 "\n"
1132 "uniform lowp vec3 Color_Pants;\n"
1133 "uniform lowp vec3 Color_Shirt;\n"
1134 "uniform lowp vec3 FogColor;\n"
1135 "\n"
1136 "#ifdef USEFOG\n"
1137 "uniform highp float FogRangeRecip;\n"
1138 "uniform highp float FogPlaneViewDist;\n"
1139 "uniform highp float FogHeightFade;\n"
1140 "vec3 FogVertex(vec3 surfacecolor)\n"
1141 "{\n"
1142 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1143 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1144 "       float fogfrac;\n"
1145 "#ifdef USEFOGHEIGHTTEXTURE\n"
1146 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1147 "       fogfrac = fogheightpixel.a;\n"
1148 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1149 "#else\n"
1150 "# ifdef USEFOGOUTSIDE\n"
1151 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1152 "# else\n"
1153 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1154 "# endif\n"
1155 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1156 "#endif\n"
1157 "}\n"
1158 "#endif\n"
1159 "\n"
1160 "#ifdef USEOFFSETMAPPING\n"
1161 "uniform mediump float OffsetMapping_Scale;\n"
1162 "vec2 OffsetMapping(vec2 TexCoord)\n"
1163 "{\n"
1164 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1165 "       // 14 sample relief mapping: linear search and then binary search\n"
1166 "       // this basically steps forward a small amount repeatedly until it finds\n"
1167 "       // itself inside solid, then jitters forward and back using decreasing\n"
1168 "       // amounts to find the impact\n"
1169 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1170 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1171 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1172 "       vec3 RT = vec3(TexCoord, 1);\n"
1173 "       OffsetVector *= 0.1;\n"
1174 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1175 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1176 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1177 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1178 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1179 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1180 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1181 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1182 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1183 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1184 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1185 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1186 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1187 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1188 "       return RT.xy;\n"
1189 "#else\n"
1190 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1191 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1192 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1193 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1194 "       OffsetVector *= 0.5;\n"
1195 "       TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1196 "       TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1197 "       return TexCoord;\n"
1198 "#endif\n"
1199 "}\n"
1200 "#endif // USEOFFSETMAPPING\n"
1201 "\n"
1202 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1203 "uniform sampler2D Texture_Attenuation;\n"
1204 "uniform samplerCube Texture_Cube;\n"
1205 "#endif\n"
1206 "\n"
1207 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1208 "\n"
1209 "#ifdef USESHADOWMAP2D\n"
1210 "# ifdef USESHADOWSAMPLER\n"
1211 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1212 "# else\n"
1213 "uniform sampler2D Texture_ShadowMap2D;\n"
1214 "# endif\n"
1215 "#endif\n"
1216 "\n"
1217 "#ifdef USESHADOWMAPVSDCT\n"
1218 "uniform samplerCube Texture_CubeProjection;\n"
1219 "#endif\n"
1220 "\n"
1221 "#if defined(USESHADOWMAP2D)\n"
1222 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1223 "uniform mediump vec4 ShadowMap_Parameters;\n"
1224 "#endif\n"
1225 "\n"
1226 "#if defined(USESHADOWMAP2D)\n"
1227 "# ifdef USESHADOWMAPORTHO\n"
1228 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1229 "# else\n"
1230 "#  ifdef USESHADOWMAPVSDCT\n"
1231 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1232 "{\n"
1233 "       vec3 adir = abs(dir);\n"
1234 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1235 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1236 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1237 "}\n"
1238 "#  else\n"
1239 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1240 "{\n"
1241 "       vec3 adir = abs(dir);\n"
1242 "       float ma = adir.z;\n"
1243 "       vec4 proj = vec4(dir, 2.5);\n"
1244 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1245 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1246 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1247 "       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"
1248 "}\n"
1249 "#  endif\n"
1250 "# endif\n"
1251 "#endif // defined(USESHADOWMAP2D)\n"
1252 "\n"
1253 "# ifdef USESHADOWMAP2D\n"
1254 "float ShadowMapCompare(vec3 dir)\n"
1255 "{\n"
1256 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1257 "       float f;\n"
1258 "\n"
1259 "#  ifdef USESHADOWSAMPLER\n"
1260 "#    ifdef USESHADOWMAPPCF\n"
1261 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1262 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1263 "       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"
1264 "#    else\n"
1265 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1266 "#    endif\n"
1267 "#  else\n"
1268 "#    ifdef USESHADOWMAPPCF\n"
1269 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1270 "#      ifdef GL_ARB_texture_gather\n"
1271 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1272 "#      else\n"
1273 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1274 "#      endif\n"
1275 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1276 "#      if USESHADOWMAPPCF > 1\n"
1277 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1278 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1279 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1280 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1281 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1282 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1283 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1284 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1285 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1286 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1287 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1288 "       locols.yz += group2.ab;\n"
1289 "       hicols.yz += group8.rg;\n"
1290 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1291 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1292 "                               mix(locols, hicols, offset.y);\n"
1293 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1294 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1295 "       f = dot(cols, vec4(1.0/25.0));\n"
1296 "#      else\n"
1297 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1298 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1299 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1300 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1301 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1302 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1303 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1304 "#      endif\n"
1305 "#     else\n"
1306 "#      ifdef GL_EXT_gpu_shader4\n"
1307 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1308 "#      else\n"
1309 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1310 "#      endif\n"
1311 "#      if USESHADOWMAPPCF > 1\n"
1312 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1313 "       center *= ShadowMap_TextureScale;\n"
1314 "       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"
1315 "       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"
1316 "       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"
1317 "       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"
1318 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1319 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1320 "#      else\n"
1321 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1322 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1323 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1324 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1325 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1326 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1327 "#      endif\n"
1328 "#     endif\n"
1329 "#    else\n"
1330 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1331 "#    endif\n"
1332 "#  endif\n"
1333 "#  ifdef USESHADOWMAPORTHO\n"
1334 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1335 "#  else\n"
1336 "       return f;\n"
1337 "#  endif\n"
1338 "}\n"
1339 "# endif\n"
1340 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1341 "#endif // FRAGMENT_SHADER\n"
1342 "\n"
1343 "\n"
1344 "\n"
1345 "\n"
1346 "#ifdef MODE_DEFERREDGEOMETRY\n"
1347 "#ifdef VERTEX_SHADER\n"
1348 "uniform highp mat4 TexMatrix;\n"
1349 "#ifdef USEVERTEXTEXTUREBLEND\n"
1350 "uniform highp mat4 BackgroundTexMatrix;\n"
1351 "#endif\n"
1352 "uniform highp mat4 ModelViewMatrix;\n"
1353 "void main(void)\n"
1354 "{\n"
1355 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1356 "#ifdef USEVERTEXTEXTUREBLEND\n"
1357 "       VertexColor = Attrib_Color;\n"
1358 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1359 "#endif\n"
1360 "\n"
1361 "       // transform unnormalized eye direction into tangent space\n"
1362 "#ifdef USEOFFSETMAPPING\n"
1363 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1364 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1365 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1366 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1367 "#endif\n"
1368 "\n"
1369 "       VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1370 "       VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1371 "       VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1372 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1373 "}\n"
1374 "#endif // VERTEX_SHADER\n"
1375 "\n"
1376 "#ifdef FRAGMENT_SHADER\n"
1377 "void main(void)\n"
1378 "{\n"
1379 "#ifdef USEOFFSETMAPPING\n"
1380 "       // apply offsetmapping\n"
1381 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1382 "#define TexCoord TexCoordOffset\n"
1383 "#endif\n"
1384 "\n"
1385 "#ifdef USEALPHAKILL\n"
1386 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1387 "               discard;\n"
1388 "#endif\n"
1389 "\n"
1390 "#ifdef USEVERTEXTEXTUREBLEND\n"
1391 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1392 "       float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1393 "       //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1394 "       //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1395 "#endif\n"
1396 "\n"
1397 "#ifdef USEVERTEXTEXTUREBLEND\n"
1398 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1399 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1400 "#else\n"
1401 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1402 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1403 "#endif\n"
1404 "\n"
1405 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1406 "}\n"
1407 "#endif // FRAGMENT_SHADER\n"
1408 "#else // !MODE_DEFERREDGEOMETRY\n"
1409 "\n"
1410 "\n"
1411 "\n"
1412 "\n"
1413 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1414 "#ifdef VERTEX_SHADER\n"
1415 "uniform highp mat4 ModelViewMatrix;\n"
1416 "void main(void)\n"
1417 "{\n"
1418 "       ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1419 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1420 "}\n"
1421 "#endif // VERTEX_SHADER\n"
1422 "\n"
1423 "#ifdef FRAGMENT_SHADER\n"
1424 "uniform highp mat4 ViewToLight;\n"
1425 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1426 "uniform highp vec2 ScreenToDepth;\n"
1427 "uniform myhalf3 DeferredColor_Ambient;\n"
1428 "uniform myhalf3 DeferredColor_Diffuse;\n"
1429 "#ifdef USESPECULAR\n"
1430 "uniform myhalf3 DeferredColor_Specular;\n"
1431 "uniform myhalf SpecularPower;\n"
1432 "#endif\n"
1433 "uniform myhalf2 PixelToScreenTexCoord;\n"
1434 "void main(void)\n"
1435 "{\n"
1436 "       // calculate viewspace pixel position\n"
1437 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1438 "       vec3 position;\n"
1439 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1440 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1441 "       // decode viewspace pixel normal\n"
1442 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1443 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1444 "       // surfacenormal = pixel normal in viewspace\n"
1445 "       // LightVector = pixel to light in viewspace\n"
1446 "       // CubeVector = position in lightspace\n"
1447 "       // eyevector = pixel to view in viewspace\n"
1448 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1449 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1450 "#ifdef USEDIFFUSE\n"
1451 "       // calculate diffuse shading\n"
1452 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1453 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1454 "#endif\n"
1455 "#ifdef USESPECULAR\n"
1456 "       // calculate directional shading\n"
1457 "       vec3 eyevector = position * -1.0;\n"
1458 "#  ifdef USEEXACTSPECULARMATH\n"
1459 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1460 "#  else\n"
1461 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1462 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1463 "#  endif\n"
1464 "#endif\n"
1465 "\n"
1466 "#if defined(USESHADOWMAP2D)\n"
1467 "       fade *= ShadowMapCompare(CubeVector);\n"
1468 "#endif\n"
1469 "\n"
1470 "#ifdef USEDIFFUSE\n"
1471 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1472 "#else\n"
1473 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1474 "#endif\n"
1475 "#ifdef USESPECULAR\n"
1476 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1477 "#else\n"
1478 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1479 "#endif\n"
1480 "\n"
1481 "# ifdef USECUBEFILTER\n"
1482 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1483 "       gl_FragData[0].rgb *= cubecolor;\n"
1484 "       gl_FragData[1].rgb *= cubecolor;\n"
1485 "# endif\n"
1486 "}\n"
1487 "#endif // FRAGMENT_SHADER\n"
1488 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1489 "\n"
1490 "\n"
1491 "\n"
1492 "\n"
1493 "#ifdef VERTEX_SHADER\n"
1494 "uniform highp mat4 TexMatrix;\n"
1495 "#ifdef USEVERTEXTEXTUREBLEND\n"
1496 "uniform highp mat4 BackgroundTexMatrix;\n"
1497 "#endif\n"
1498 "#ifdef MODE_LIGHTSOURCE\n"
1499 "uniform highp mat4 ModelToLight;\n"
1500 "#endif\n"
1501 "#ifdef USESHADOWMAPORTHO\n"
1502 "uniform highp mat4 ShadowMapMatrix;\n"
1503 "#endif\n"
1504 "#ifdef USEBOUNCEGRID\n"
1505 "uniform highp mat4 BounceGridMatrix;\n"
1506 "#endif\n"
1507 "void main(void)\n"
1508 "{\n"
1509 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1510 "       VertexColor = Attrib_Color;\n"
1511 "#endif\n"
1512 "       // copy the surface texcoord\n"
1513 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1514 "#ifdef USEVERTEXTEXTUREBLEND\n"
1515 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1516 "#endif\n"
1517 "#ifdef USELIGHTMAP\n"
1518 "       TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1519 "#endif\n"
1520 "\n"
1521 "#ifdef USEBOUNCEGRID\n"
1522 "       BounceGridTexCoord = vec3(BounceGridMatrix * Attrib_Position);\n"
1523 "#endif\n"
1524 "\n"
1525 "#ifdef MODE_LIGHTSOURCE\n"
1526 "       // transform vertex position into light attenuation/cubemap space\n"
1527 "       // (-1 to +1 across the light box)\n"
1528 "       CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1529 "\n"
1530 "# ifdef USEDIFFUSE\n"
1531 "       // transform unnormalized light direction into tangent space\n"
1532 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1533 "       //  normalize it per pixel)\n"
1534 "       vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1535 "       LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1536 "       LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1537 "       LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1538 "# endif\n"
1539 "#endif\n"
1540 "\n"
1541 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1542 "       LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1543 "       LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1544 "       LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1545 "#endif\n"
1546 "\n"
1547 "       // transform unnormalized eye direction into tangent space\n"
1548 "#ifdef USEEYEVECTOR\n"
1549 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1550 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1551 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1552 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1553 "#endif\n"
1554 "\n"
1555 "#ifdef USEFOG\n"
1556 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1557 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1558 "#endif\n"
1559 "\n"
1560 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1561 "       VectorS = Attrib_TexCoord1.xyz;\n"
1562 "       VectorT = Attrib_TexCoord2.xyz;\n"
1563 "       VectorR = Attrib_TexCoord3.xyz;\n"
1564 "#endif\n"
1565 "\n"
1566 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1567 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1568 "\n"
1569 "#ifdef USESHADOWMAPORTHO\n"
1570 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1571 "#endif\n"
1572 "\n"
1573 "#ifdef USEREFLECTION\n"
1574 "       ModelViewProjectionPosition = gl_Position;\n"
1575 "#endif\n"
1576 "}\n"
1577 "#endif // VERTEX_SHADER\n"
1578 "\n"
1579 "\n"
1580 "\n"
1581 "\n"
1582 "#ifdef FRAGMENT_SHADER\n"
1583 "#ifdef USEDEFERREDLIGHTMAP\n"
1584 "uniform myhalf2 PixelToScreenTexCoord;\n"
1585 "uniform myhalf3 DeferredMod_Diffuse;\n"
1586 "uniform myhalf3 DeferredMod_Specular;\n"
1587 "#endif\n"
1588 "uniform myhalf3 Color_Ambient;\n"
1589 "uniform myhalf3 Color_Diffuse;\n"
1590 "uniform myhalf3 Color_Specular;\n"
1591 "uniform myhalf SpecularPower;\n"
1592 "#ifdef USEGLOW\n"
1593 "uniform myhalf3 Color_Glow;\n"
1594 "#endif\n"
1595 "uniform myhalf Alpha;\n"
1596 "#ifdef USEREFLECTION\n"
1597 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1598 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1599 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1600 "uniform lowp vec4 ReflectColor;\n"
1601 "#endif\n"
1602 "#ifdef USEREFLECTCUBE\n"
1603 "uniform highp mat4 ModelToReflectCube;\n"
1604 "uniform sampler2D Texture_ReflectMask;\n"
1605 "uniform samplerCube Texture_ReflectCube;\n"
1606 "#endif\n"
1607 "#ifdef MODE_LIGHTDIRECTION\n"
1608 "uniform myhalf3 LightColor;\n"
1609 "#endif\n"
1610 "#ifdef MODE_LIGHTSOURCE\n"
1611 "uniform myhalf3 LightColor;\n"
1612 "#endif\n"
1613 "#ifdef USEBOUNCEGRID\n"
1614 "uniform sampler3D Texture_BounceGrid;\n"
1615 "uniform float BounceGridIntensity;\n"
1616 "#endif\n"
1617 "void main(void)\n"
1618 "{\n"
1619 "#ifdef USEOFFSETMAPPING\n"
1620 "       // apply offsetmapping\n"
1621 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1622 "#define TexCoord TexCoordOffset\n"
1623 "#endif\n"
1624 "\n"
1625 "       // combine the diffuse textures (base, pants, shirt)\n"
1626 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1627 "#ifdef USEALPHAKILL\n"
1628 "       if (color.a < 0.5)\n"
1629 "               discard;\n"
1630 "#endif\n"
1631 "       color.a *= Alpha;\n"
1632 "#ifdef USECOLORMAPPING\n"
1633 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1634 "#endif\n"
1635 "#ifdef USEVERTEXTEXTUREBLEND\n"
1636 "       myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1637 "       //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1638 "       //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1639 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1640 "       color.a = 1.0;\n"
1641 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1642 "#endif\n"
1643 "\n"
1644 "       // get the surface normal\n"
1645 "#ifdef USEVERTEXTEXTUREBLEND\n"
1646 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1647 "#else\n"
1648 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1649 "#endif\n"
1650 "\n"
1651 "       // get the material colors\n"
1652 "       myhalf3 diffusetex = color.rgb;\n"
1653 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1654 "# ifdef USEVERTEXTEXTUREBLEND\n"
1655 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1656 "# else\n"
1657 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1658 "# endif\n"
1659 "#endif\n"
1660 "\n"
1661 "#ifdef USEREFLECTCUBE\n"
1662 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1663 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1664 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1665 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1666 "#endif\n"
1667 "\n"
1668 "\n"
1669 "\n"
1670 "\n"
1671 "#ifdef MODE_LIGHTSOURCE\n"
1672 "       // light source\n"
1673 "#ifdef USEDIFFUSE\n"
1674 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1675 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1676 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1677 "#ifdef USESPECULAR\n"
1678 "#ifdef USEEXACTSPECULARMATH\n"
1679 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1680 "#else\n"
1681 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1682 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1683 "#endif\n"
1684 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1685 "#endif\n"
1686 "#else\n"
1687 "       color.rgb = diffusetex * Color_Ambient;\n"
1688 "#endif\n"
1689 "       color.rgb *= LightColor;\n"
1690 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1691 "#if defined(USESHADOWMAP2D)\n"
1692 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1693 "#endif\n"
1694 "# ifdef USECUBEFILTER\n"
1695 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1696 "# endif\n"
1697 "#endif // MODE_LIGHTSOURCE\n"
1698 "\n"
1699 "\n"
1700 "\n"
1701 "\n"
1702 "#ifdef MODE_LIGHTDIRECTION\n"
1703 "#define SHADING\n"
1704 "#ifdef USEDIFFUSE\n"
1705 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1706 "#endif\n"
1707 "#define lightcolor LightColor\n"
1708 "#endif // MODE_LIGHTDIRECTION\n"
1709 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1710 "#define SHADING\n"
1711 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1712 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1713 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1714 "       // convert modelspace light vector to tangentspace\n"
1715 "       myhalf3 lightnormal;\n"
1716 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1717 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1718 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1719 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1720 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1721 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1722 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1723 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1724 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1725 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1726 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1727 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1728 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1729 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1730 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1731 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1732 "#define SHADING\n"
1733 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1734 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1735 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1736 "#endif\n"
1737 "\n"
1738 "\n"
1739 "\n"
1740 "\n"
1741 "#ifdef MODE_FAKELIGHT\n"
1742 "#define SHADING\n"
1743 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1744 "myhalf3 lightcolor = myhalf3(1.0);\n"
1745 "#endif // MODE_FAKELIGHT\n"
1746 "\n"
1747 "\n"
1748 "\n"
1749 "\n"
1750 "#ifdef MODE_LIGHTMAP\n"
1751 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1752 "#endif // MODE_LIGHTMAP\n"
1753 "#ifdef MODE_VERTEXCOLOR\n"
1754 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1755 "#endif // MODE_VERTEXCOLOR\n"
1756 "#ifdef MODE_FLATCOLOR\n"
1757 "       color.rgb = diffusetex * Color_Ambient;\n"
1758 "#endif // MODE_FLATCOLOR\n"
1759 "\n"
1760 "\n"
1761 "\n"
1762 "\n"
1763 "#ifdef SHADING\n"
1764 "# ifdef USEDIFFUSE\n"
1765 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1766 "#  ifdef USESPECULAR\n"
1767 "#   ifdef USEEXACTSPECULARMATH\n"
1768 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1769 "#   else\n"
1770 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1771 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1772 "#   endif\n"
1773 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1774 "#  else\n"
1775 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1776 "#  endif\n"
1777 "# else\n"
1778 "       color.rgb = diffusetex * Color_Ambient;\n"
1779 "# endif\n"
1780 "#endif\n"
1781 "\n"
1782 "#ifdef USESHADOWMAPORTHO\n"
1783 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1784 "#endif\n"
1785 "\n"
1786 "#ifdef USEDEFERREDLIGHTMAP\n"
1787 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1788 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1789 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1790 "#endif\n"
1791 "\n"
1792 "#ifdef USEBOUNCEGRID\n"
1793 "       color.rgb += diffusetex * myhalf3(texture3D(Texture_BounceGrid, BounceGridTexCoord)) * BounceGridIntensity;\n"
1794 "#endif\n"
1795 "\n"
1796 "#ifdef USEGLOW\n"
1797 "#ifdef USEVERTEXTEXTUREBLEND\n"
1798 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1799 "#else\n"
1800 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1801 "#endif\n"
1802 "#endif\n"
1803 "\n"
1804 "#ifdef USEFOG\n"
1805 "       color.rgb = FogVertex(color.rgb);\n"
1806 "#endif\n"
1807 "\n"
1808 "       // 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"
1809 "#ifdef USEREFLECTION\n"
1810 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1811 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1812 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1813 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1814 "       // FIXME temporary hack to detect the case that the reflection\n"
1815 "       // gets blackened at edges due to leaving the area that contains actual\n"
1816 "       // content.\n"
1817 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1818 "       // 'appening.\n"
1819 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1820 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1821 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1822 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1823 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1824 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1825 "#endif\n"
1826 "\n"
1827 "       gl_FragColor = vec4(color);\n"
1828 "}\n"
1829 "#endif // FRAGMENT_SHADER\n"
1830 "\n"
1831 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1832 "#endif // !MODE_DEFERREDGEOMETRY\n"
1833 "#endif // !MODE_WATER\n"
1834 "#endif // !MODE_REFRACTION\n"
1835 "#endif // !MODE_BLOOMBLUR\n"
1836 "#endif // !MODE_GENERIC\n"
1837 "#endif // !MODE_POSTPROCESS\n"
1838 "#endif // !MODE_SHOWDEPTH\n"
1839 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1840 ;
1841
1842 /*
1843 =========================================================================================================================================================
1844
1845
1846
1847 =========================================================================================================================================================
1848
1849
1850
1851 =========================================================================================================================================================
1852
1853
1854
1855 =========================================================================================================================================================
1856
1857
1858
1859 =========================================================================================================================================================
1860
1861
1862
1863 =========================================================================================================================================================
1864
1865
1866
1867 =========================================================================================================================================================
1868 */
1869
1870 const char *builtinhlslshaderstring =
1871 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1872 "// written by Forest 'LordHavoc' Hale\n"
1873 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1874 "\n"
1875 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1876 "#if defined(USEREFLECTION)\n"
1877 "#undef USESHADOWMAPORTHO\n"
1878 "#endif\n"
1879 "\n"
1880 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1881 "# define USEFOG\n"
1882 "#endif\n"
1883 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1884 "#define USELIGHTMAP\n"
1885 "#endif\n"
1886 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1887 "#define USEEYEVECTOR\n"
1888 "#endif\n"
1889 "\n"
1890 "#ifdef FRAGMENT_SHADER\n"
1891 "#ifdef HLSL\n"
1892 "//#undef USESHADOWMAPPCF\n"
1893 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1894 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1895 "#else\n"
1896 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1897 "#endif\n"
1898 "#endif\n"
1899 "\n"
1900 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1901 "#ifdef VERTEX_SHADER\n"
1902 "void main\n"
1903 "(\n"
1904 "float4 gl_Vertex : POSITION,\n"
1905 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1906 "out float4 gl_Position : POSITION,\n"
1907 "out float Depth : TEXCOORD0\n"
1908 ")\n"
1909 "{\n"
1910 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1911 "       Depth = gl_Position.z;\n"
1912 "}\n"
1913 "#endif\n"
1914 "\n"
1915 "#ifdef FRAGMENT_SHADER\n"
1916 "void main\n"
1917 "(\n"
1918 "float Depth : TEXCOORD0,\n"
1919 "out float4 gl_FragColor : COLOR\n"
1920 ")\n"
1921 "{\n"
1922 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1923 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1924 "       temp.yz -= floor(temp.yz);\n"
1925 "       gl_FragColor = temp;\n"
1926 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1927 "}\n"
1928 "#endif\n"
1929 "#else // !MODE_DEPTH_ORSHADOW\n"
1930 "\n"
1931 "\n"
1932 "\n"
1933 "\n"
1934 "#ifdef MODE_SHOWDEPTH\n"
1935 "#ifdef VERTEX_SHADER\n"
1936 "void main\n"
1937 "(\n"
1938 "float4 gl_Vertex : POSITION,\n"
1939 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1940 "out float4 gl_Position : POSITION,\n"
1941 "out float4 gl_FrontColor : COLOR0\n"
1942 ")\n"
1943 "{\n"
1944 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1945 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1946 "}\n"
1947 "#endif\n"
1948 "\n"
1949 "#ifdef FRAGMENT_SHADER\n"
1950 "void main\n"
1951 "(\n"
1952 "float4 gl_FrontColor : COLOR0,\n"
1953 "out float4 gl_FragColor : COLOR\n"
1954 ")\n"
1955 "{\n"
1956 "       gl_FragColor = gl_FrontColor;\n"
1957 "}\n"
1958 "#endif\n"
1959 "#else // !MODE_SHOWDEPTH\n"
1960 "\n"
1961 "\n"
1962 "\n"
1963 "\n"
1964 "#ifdef MODE_POSTPROCESS\n"
1965 "\n"
1966 "#ifdef VERTEX_SHADER\n"
1967 "void main\n"
1968 "(\n"
1969 "float4 gl_Vertex : POSITION,\n"
1970 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1971 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1972 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1973 "out float4 gl_Position : POSITION,\n"
1974 "out float2 TexCoord1 : TEXCOORD0,\n"
1975 "out float2 TexCoord2 : TEXCOORD1\n"
1976 ")\n"
1977 "{\n"
1978 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1979 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1980 "#ifdef USEBLOOM\n"
1981 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1982 "#endif\n"
1983 "}\n"
1984 "#endif\n"
1985 "\n"
1986 "#ifdef FRAGMENT_SHADER\n"
1987 "void main\n"
1988 "(\n"
1989 "float2 TexCoord1 : TEXCOORD0,\n"
1990 "float2 TexCoord2 : TEXCOORD1,\n"
1991 "uniform sampler Texture_First : register(s0),\n"
1992 "#ifdef USEBLOOM\n"
1993 "uniform sampler Texture_Second : register(s1),\n"
1994 "#endif\n"
1995 "#ifdef USEGAMMARAMPS\n"
1996 "uniform sampler Texture_GammaRamps : register(s2),\n"
1997 "#endif\n"
1998 "#ifdef USESATURATION\n"
1999 "uniform float Saturation : register(c30),\n"
2000 "#endif\n"
2001 "#ifdef USEVIEWTINT\n"
2002 "uniform float4 ViewTintColor : register(c41),\n"
2003 "#endif\n"
2004 "uniform float4 UserVec1 : register(c37),\n"
2005 "uniform float4 UserVec2 : register(c38),\n"
2006 "uniform float4 UserVec3 : register(c39),\n"
2007 "uniform float4 UserVec4 : register(c40),\n"
2008 "uniform float ClientTime : register(c2),\n"
2009 "uniform float2 PixelSize : register(c25),\n"
2010 "uniform float4 BloomColorSubtract : register(c43),\n"
2011 "out float4 gl_FragColor : COLOR\n"
2012 ")\n"
2013 "{\n"
2014 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2015 "#ifdef USEBLOOM\n"
2016 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2017 "#endif\n"
2018 "#ifdef USEVIEWTINT\n"
2019 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2020 "#endif\n"
2021 "\n"
2022 "#ifdef USEPOSTPROCESSING\n"
2023 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2024 "// 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"
2025 "       float sobel = 1.0;\n"
2026 "       // float2 ts = textureSize(Texture_First, 0);\n"
2027 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2028 "       float2 px = PixelSize;\n"
2029 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2030 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2031 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2032 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2033 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2034 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2035 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2036 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2037 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2038 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2039 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2040 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2041 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2042 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2043 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2044 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2045 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2046 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2047 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2048 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2049 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2050 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2051 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2052 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2053 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2054 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2055 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2056 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2057 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2058 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2059 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2060 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2061 "#endif\n"
2062 "\n"
2063 "#ifdef USESATURATION\n"
2064 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2065 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2066 "       // 'vampire sight' effect, wheres red is compensated\n"
2067 "       #ifdef SATURATION_REDCOMPENSATE\n"
2068 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2069 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2070 "               gl_FragColor.r += r;\n"
2071 "       #else\n"
2072 "               // normal desaturation\n"
2073 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2074 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2075 "       #endif\n"
2076 "#endif\n"
2077 "\n"
2078 "#ifdef USEGAMMARAMPS\n"
2079 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2080 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2081 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2082 "#endif\n"
2083 "}\n"
2084 "#endif\n"
2085 "#else // !MODE_POSTPROCESS\n"
2086 "\n"
2087 "\n"
2088 "\n"
2089 "\n"
2090 "#ifdef MODE_GENERIC\n"
2091 "#ifdef VERTEX_SHADER\n"
2092 "void main\n"
2093 "(\n"
2094 "float4 gl_Vertex : POSITION,\n"
2095 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2096 "float4 gl_Color : COLOR0,\n"
2097 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2098 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2099 "out float4 gl_Position : POSITION,\n"
2100 "#ifdef USEDIFFUSE\n"
2101 "out float2 TexCoord1 : TEXCOORD0,\n"
2102 "#endif\n"
2103 "#ifdef USESPECULAR\n"
2104 "out float2 TexCoord2 : TEXCOORD1,\n"
2105 "#endif\n"
2106 "out float4 gl_FrontColor : COLOR\n"
2107 ")\n"
2108 "{\n"
2109 "#ifdef HLSL\n"
2110 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2111 "#else\n"
2112 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2113 "#endif\n"
2114 "#ifdef USEDIFFUSE\n"
2115 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2116 "#endif\n"
2117 "#ifdef USESPECULAR\n"
2118 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2119 "#endif\n"
2120 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2121 "}\n"
2122 "#endif\n"
2123 "\n"
2124 "#ifdef FRAGMENT_SHADER\n"
2125 "\n"
2126 "void main\n"
2127 "(\n"
2128 "float4 gl_FrontColor : COLOR0,\n"
2129 "float2 TexCoord1 : TEXCOORD0,\n"
2130 "float2 TexCoord2 : TEXCOORD1,\n"
2131 "#ifdef USEDIFFUSE\n"
2132 "uniform sampler Texture_First : register(s0),\n"
2133 "#endif\n"
2134 "#ifdef USESPECULAR\n"
2135 "uniform sampler Texture_Second : register(s1),\n"
2136 "#endif\n"
2137 "out float4 gl_FragColor : COLOR\n"
2138 ")\n"
2139 "{\n"
2140 "#ifdef USEVIEWTINT\n"
2141 "       gl_FragColor = gl_FrontColor;\n"
2142 "#else\n"
2143 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2144 "#endif\n"
2145 "#ifdef USEDIFFUSE\n"
2146 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2147 "#endif\n"
2148 "\n"
2149 "#ifdef USESPECULAR\n"
2150 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2151 "# ifdef USECOLORMAPPING\n"
2152 "       gl_FragColor *= tex2;\n"
2153 "# endif\n"
2154 "# ifdef USEGLOW\n"
2155 "       gl_FragColor += tex2;\n"
2156 "# endif\n"
2157 "# ifdef USEVERTEXTEXTUREBLEND\n"
2158 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2159 "# endif\n"
2160 "#endif\n"
2161 "}\n"
2162 "#endif\n"
2163 "#else // !MODE_GENERIC\n"
2164 "\n"
2165 "\n"
2166 "\n"
2167 "\n"
2168 "#ifdef MODE_BLOOMBLUR\n"
2169 "#ifdef VERTEX_SHADER\n"
2170 "void main\n"
2171 "(\n"
2172 "float4 gl_Vertex : POSITION,\n"
2173 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2174 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2175 "out float4 gl_Position : POSITION,\n"
2176 "out float2 TexCoord : TEXCOORD0\n"
2177 ")\n"
2178 "{\n"
2179 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2180 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2181 "}\n"
2182 "#endif\n"
2183 "\n"
2184 "#ifdef FRAGMENT_SHADER\n"
2185 "\n"
2186 "void main\n"
2187 "(\n"
2188 "float2 TexCoord : TEXCOORD0,\n"
2189 "uniform sampler Texture_First : register(s0),\n"
2190 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2191 "out float4 gl_FragColor : COLOR\n"
2192 ")\n"
2193 "{\n"
2194 "       int i;\n"
2195 "       float2 tc = TexCoord;\n"
2196 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2197 "       tc += BloomBlur_Parameters.xy;\n"
2198 "       for (i = 1;i < SAMPLES;i++)\n"
2199 "       {\n"
2200 "               color += tex2D(Texture_First, tc).rgb;\n"
2201 "               tc += BloomBlur_Parameters.xy;\n"
2202 "       }\n"
2203 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2204 "}\n"
2205 "#endif\n"
2206 "#else // !MODE_BLOOMBLUR\n"
2207 "#ifdef MODE_REFRACTION\n"
2208 "#ifdef VERTEX_SHADER\n"
2209 "void main\n"
2210 "(\n"
2211 "float4 gl_Vertex : POSITION,\n"
2212 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2213 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2214 "uniform float4x4 TexMatrix : register(c0),\n"
2215 "uniform float3 EyePosition : register(c24),\n"
2216 "out float4 gl_Position : POSITION,\n"
2217 "out float2 TexCoord : TEXCOORD0,\n"
2218 "out float3 EyeVector : TEXCOORD1,\n"
2219 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2220 ")\n"
2221 "{\n"
2222 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2223 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2224 "       ModelViewProjectionPosition = gl_Position;\n"
2225 "}\n"
2226 "#endif\n"
2227 "\n"
2228 "#ifdef FRAGMENT_SHADER\n"
2229 "void main\n"
2230 "(\n"
2231 "float2 TexCoord : TEXCOORD0,\n"
2232 "float3 EyeVector : TEXCOORD1,\n"
2233 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2234 "uniform sampler Texture_Normal : register(s0),\n"
2235 "uniform sampler Texture_Refraction : register(s3),\n"
2236 "uniform sampler Texture_Reflection : register(s7),\n"
2237 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2238 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2239 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2240 "uniform float4 RefractColor : register(c29),\n"
2241 "out float4 gl_FragColor : COLOR\n"
2242 ")\n"
2243 "{\n"
2244 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2245 "       //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"
2246 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2247 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2248 "       // FIXME temporary hack to detect the case that the reflection\n"
2249 "       // gets blackened at edges due to leaving the area that contains actual\n"
2250 "       // content.\n"
2251 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2252 "       // 'appening.\n"
2253 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2254 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2255 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2256 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2257 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2258 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2259 "}\n"
2260 "#endif\n"
2261 "#else // !MODE_REFRACTION\n"
2262 "\n"
2263 "\n"
2264 "\n"
2265 "\n"
2266 "#ifdef MODE_WATER\n"
2267 "#ifdef VERTEX_SHADER\n"
2268 "\n"
2269 "void main\n"
2270 "(\n"
2271 "float4 gl_Vertex : POSITION,\n"
2272 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2273 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2274 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2275 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2276 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2277 "uniform float4x4 TexMatrix : register(c0),\n"
2278 "uniform float3 EyePosition : register(c24),\n"
2279 "out float4 gl_Position : POSITION,\n"
2280 "out float2 TexCoord : TEXCOORD0,\n"
2281 "out float3 EyeVector : TEXCOORD1,\n"
2282 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2283 ")\n"
2284 "{\n"
2285 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2286 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2287 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2288 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2289 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2290 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2291 "       ModelViewProjectionPosition = gl_Position;\n"
2292 "}\n"
2293 "#endif\n"
2294 "\n"
2295 "#ifdef FRAGMENT_SHADER\n"
2296 "void main\n"
2297 "(\n"
2298 "float2 TexCoord : TEXCOORD0,\n"
2299 "float3 EyeVector : TEXCOORD1,\n"
2300 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2301 "uniform sampler Texture_Normal : register(s0),\n"
2302 "uniform sampler Texture_Refraction : register(s3),\n"
2303 "uniform sampler Texture_Reflection : register(s7),\n"
2304 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2305 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2306 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2307 "uniform float4 RefractColor : register(c29),\n"
2308 "uniform float4 ReflectColor : register(c26),\n"
2309 "uniform float ReflectFactor : register(c27),\n"
2310 "uniform float ReflectOffset : register(c28),\n"
2311 "out float4 gl_FragColor : COLOR\n"
2312 ")\n"
2313 "{\n"
2314 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2315 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2316 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2317 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2318 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2319 "       // FIXME temporary hack to detect the case that the reflection\n"
2320 "       // gets blackened at edges due to leaving the area that contains actual\n"
2321 "       // content.\n"
2322 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2323 "       // 'appening.\n"
2324 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2325 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2326 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2327 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2328 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2329 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2330 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2331 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2332 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2333 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2334 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2335 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2336 "}\n"
2337 "#endif\n"
2338 "#else // !MODE_WATER\n"
2339 "\n"
2340 "\n"
2341 "\n"
2342 "\n"
2343 "// 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"
2344 "\n"
2345 "// fragment shader specific:\n"
2346 "#ifdef FRAGMENT_SHADER\n"
2347 "\n"
2348 "#ifdef USEFOG\n"
2349 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2350 "{\n"
2351 "       float fogfrac;\n"
2352 "#ifdef USEFOGHEIGHTTEXTURE\n"
2353 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2354 "       fogfrac = fogheightpixel.a;\n"
2355 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2356 "#else\n"
2357 "# ifdef USEFOGOUTSIDE\n"
2358 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2359 "# else\n"
2360 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2361 "# endif\n"
2362 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2363 "#endif\n"
2364 "}\n"
2365 "#endif\n"
2366 "\n"
2367 "#ifdef USEOFFSETMAPPING\n"
2368 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2369 "{\n"
2370 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2371 "       // 14 sample relief mapping: linear search and then binary search\n"
2372 "       // this basically steps forward a small amount repeatedly until it finds\n"
2373 "       // itself inside solid, then jitters forward and back using decreasing\n"
2374 "       // amounts to find the impact\n"
2375 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2376 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2377 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2378 "       float3 RT = float3(TexCoord, 1);\n"
2379 "       OffsetVector *= 0.1;\n"
2380 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2381 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2382 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2383 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2384 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2385 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2386 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2387 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2388 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2389 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2390 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2391 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2392 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2393 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2394 "       return RT.xy;\n"
2395 "#else\n"
2396 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2397 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2398 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2399 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2400 "       OffsetVector *= 0.5;\n"
2401 "       TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2402 "       TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2403 "       return TexCoord;\n"
2404 "#endif\n"
2405 "}\n"
2406 "#endif // USEOFFSETMAPPING\n"
2407 "\n"
2408 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2409 "#if defined(USESHADOWMAP2D)\n"
2410 "# ifdef USESHADOWMAPORTHO\n"
2411 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2412 "# else\n"
2413 "#  ifdef USESHADOWMAPVSDCT\n"
2414 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2415 "{\n"
2416 "       float3 adir = abs(dir);\n"
2417 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2418 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2419 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2420 "}\n"
2421 "#  else\n"
2422 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2423 "{\n"
2424 "       float3 adir = abs(dir);\n"
2425 "       float ma = adir.z;\n"
2426 "       float4 proj = float4(dir, 2.5);\n"
2427 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2428 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2429 "#ifdef HLSL\n"
2430 "       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"
2431 "#else\n"
2432 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2433 "       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"
2434 "#endif\n"
2435 "}\n"
2436 "#  endif\n"
2437 "# endif\n"
2438 "#endif // defined(USESHADOWMAP2D)\n"
2439 "\n"
2440 "# ifdef USESHADOWMAP2D\n"
2441 "#ifdef USESHADOWMAPVSDCT\n"
2442 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2443 "#else\n"
2444 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2445 "#endif\n"
2446 "{\n"
2447 "#ifdef USESHADOWMAPVSDCT\n"
2448 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2449 "#else\n"
2450 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2451 "#endif\n"
2452 "       float f;\n"
2453 "\n"
2454 "#  ifdef USESHADOWSAMPLER\n"
2455 "#    ifdef USESHADOWMAPPCF\n"
2456 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2457 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2458 "       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"
2459 "#    else\n"
2460 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2461 "#    endif\n"
2462 "#  else\n"
2463 "#    ifdef USESHADOWMAPPCF\n"
2464 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2465 "#      ifdef GL_ARB_texture_gather\n"
2466 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2467 "#      else\n"
2468 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2469 "#      endif\n"
2470 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2471 "#      if USESHADOWMAPPCF > 1\n"
2472 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2473 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2474 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2475 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2476 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2477 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2478 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2479 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2480 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2481 "       float4 locols = float4(group1.ab, group3.ab);\n"
2482 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2483 "       locols.yz += group2.ab;\n"
2484 "       hicols.yz += group8.rg;\n"
2485 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2486 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2487 "                               lerp(locols, hicols, offset.y);\n"
2488 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2489 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2490 "       f = dot(cols, float4(1.0/25.0));\n"
2491 "#      else\n"
2492 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2493 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2494 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2495 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2496 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2497 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2498 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2499 "#      endif\n"
2500 "#     else\n"
2501 "#      ifdef GL_EXT_gpu_shader4\n"
2502 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2503 "#      else\n"
2504 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2505 "#      endif\n"
2506 "#      if USESHADOWMAPPCF > 1\n"
2507 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2508 "       center *= ShadowMap_TextureScale;\n"
2509 "       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"
2510 "       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"
2511 "       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"
2512 "       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"
2513 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2514 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2515 "#      else\n"
2516 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2517 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2518 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2519 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2520 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2521 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2522 "#      endif\n"
2523 "#     endif\n"
2524 "#    else\n"
2525 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2526 "#    endif\n"
2527 "#  endif\n"
2528 "#  ifdef USESHADOWMAPORTHO\n"
2529 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2530 "#  else\n"
2531 "       return f;\n"
2532 "#  endif\n"
2533 "}\n"
2534 "# endif\n"
2535 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2536 "#endif // FRAGMENT_SHADER\n"
2537 "\n"
2538 "\n"
2539 "\n"
2540 "\n"
2541 "#ifdef MODE_DEFERREDGEOMETRY\n"
2542 "#ifdef VERTEX_SHADER\n"
2543 "void main\n"
2544 "(\n"
2545 "float4 gl_Vertex : POSITION,\n"
2546 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2547 "#ifdef USEVERTEXTEXTUREBLEND\n"
2548 "float4 gl_Color : COLOR0,\n"
2549 "#endif\n"
2550 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2551 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2552 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2553 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2554 "uniform float4x4 TexMatrix : register(c0),\n"
2555 "#ifdef USEVERTEXTEXTUREBLEND\n"
2556 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2557 "#endif\n"
2558 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2559 "#ifdef USEOFFSETMAPPING\n"
2560 "uniform float3 EyePosition : register(c24),\n"
2561 "#endif\n"
2562 "out float4 gl_Position : POSITION,\n"
2563 "#ifdef USEVERTEXTEXTUREBLEND\n"
2564 "out float4 gl_FrontColor : COLOR,\n"
2565 "#endif\n"
2566 "out float4 TexCoordBoth : TEXCOORD0,\n"
2567 "#ifdef USEOFFSETMAPPING\n"
2568 "out float3 EyeVector : TEXCOORD2,\n"
2569 "#endif\n"
2570 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2571 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2572 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2573 ")\n"
2574 "{\n"
2575 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2576 "#ifdef USEVERTEXTEXTUREBLEND\n"
2577 "#ifdef HLSL\n"
2578 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2579 "#else\n"
2580 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2581 "#endif\n"
2582 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2583 "#endif\n"
2584 "\n"
2585 "       // transform unnormalized eye direction into tangent space\n"
2586 "#ifdef USEOFFSETMAPPING\n"
2587 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2588 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2589 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2590 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2591 "#endif\n"
2592 "\n"
2593 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2594 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2595 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2596 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2597 "       VectorR.w = gl_Position.z;\n"
2598 "}\n"
2599 "#endif // VERTEX_SHADER\n"
2600 "\n"
2601 "#ifdef FRAGMENT_SHADER\n"
2602 "void main\n"
2603 "(\n"
2604 "float4 TexCoordBoth : TEXCOORD0,\n"
2605 "float3 EyeVector : TEXCOORD2,\n"
2606 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2607 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2608 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2609 "uniform sampler Texture_Normal : register(s0),\n"
2610 "#ifdef USEALPHAKILL\n"
2611 "uniform sampler Texture_Color : register(s1),\n"
2612 "#endif\n"
2613 "uniform sampler Texture_Gloss : register(s2),\n"
2614 "#ifdef USEVERTEXTEXTUREBLEND\n"
2615 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2616 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2617 "#endif\n"
2618 "#ifdef USEOFFSETMAPPING\n"
2619 "uniform float OffsetMapping_Scale : register(c24),\n"
2620 "#endif\n"
2621 "uniform half SpecularPower : register(c36),\n"
2622 "#ifdef HLSL\n"
2623 "out float4 gl_FragData0 : COLOR0,\n"
2624 "out float4 gl_FragData1 : COLOR1\n"
2625 "#else\n"
2626 "out float4 gl_FragColor : COLOR\n"
2627 "#endif\n"
2628 ")\n"
2629 "{\n"
2630 "       float2 TexCoord = TexCoordBoth.xy;\n"
2631 "#ifdef USEOFFSETMAPPING\n"
2632 "       // apply offsetmapping\n"
2633 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2634 "#define TexCoord TexCoordOffset\n"
2635 "#endif\n"
2636 "\n"
2637 "#ifdef USEALPHAKILL\n"
2638 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2639 "               discard;\n"
2640 "#endif\n"
2641 "\n"
2642 "#ifdef USEVERTEXTEXTUREBLEND\n"
2643 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2644 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2645 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2646 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2647 "#endif\n"
2648 "\n"
2649 "#ifdef USEVERTEXTEXTUREBLEND\n"
2650 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2651 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2652 "#else\n"
2653 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2654 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2655 "#endif\n"
2656 "\n"
2657 "#ifdef HLSL\n"
2658 "       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"
2659 "       float Depth = VectorR.w / 256.0;\n"
2660 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2661 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2662 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2663 "       gl_FragData1 = depthcolor;\n"
2664 "#else\n"
2665 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2666 "#endif\n"
2667 "}\n"
2668 "#endif // FRAGMENT_SHADER\n"
2669 "#else // !MODE_DEFERREDGEOMETRY\n"
2670 "\n"
2671 "\n"
2672 "\n"
2673 "\n"
2674 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2675 "#ifdef VERTEX_SHADER\n"
2676 "void main\n"
2677 "(\n"
2678 "float4 gl_Vertex : POSITION,\n"
2679 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2680 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2681 "out float4 gl_Position : POSITION,\n"
2682 "out float4 ModelViewPosition : TEXCOORD0\n"
2683 ")\n"
2684 "{\n"
2685 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2686 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2687 "}\n"
2688 "#endif // VERTEX_SHADER\n"
2689 "\n"
2690 "#ifdef FRAGMENT_SHADER\n"
2691 "void main\n"
2692 "(\n"
2693 "#ifdef HLSL\n"
2694 "float2 Pixel : VPOS,\n"
2695 "#else\n"
2696 "float2 Pixel : WPOS,\n"
2697 "#endif\n"
2698 "float4 ModelViewPosition : TEXCOORD0,\n"
2699 "uniform float4x4 ViewToLight : register(c44),\n"
2700 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2701 "uniform float3 LightPosition : register(c23),\n"
2702 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2703 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2704 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2705 "#ifdef USESPECULAR\n"
2706 "uniform half3 DeferredColor_Specular : register(c11),\n"
2707 "uniform half SpecularPower : register(c36),\n"
2708 "#endif\n"
2709 "uniform sampler Texture_Attenuation : register(s9),\n"
2710 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2711 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2712 "\n"
2713 "#ifdef USECUBEFILTER\n"
2714 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2715 "#endif\n"
2716 "\n"
2717 "#ifdef USESHADOWMAP2D\n"
2718 "# ifdef USESHADOWSAMPLER\n"
2719 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2720 "# else\n"
2721 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2722 "# endif\n"
2723 "#endif\n"
2724 "\n"
2725 "#ifdef USESHADOWMAPVSDCT\n"
2726 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2727 "#endif\n"
2728 "\n"
2729 "#if defined(USESHADOWMAP2D)\n"
2730 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2731 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2732 "#endif\n"
2733 "\n"
2734 "out float4 gl_FragData0 : COLOR0,\n"
2735 "out float4 gl_FragData1 : COLOR1\n"
2736 ")\n"
2737 "{\n"
2738 "       // calculate viewspace pixel position\n"
2739 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2740 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2741 "       float3 position;\n"
2742 "#ifdef HLSL\n"
2743 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2744 "#else\n"
2745 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2746 "#endif\n"
2747 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2748 "       // decode viewspace pixel normal\n"
2749 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2750 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2751 "       // surfacenormal = pixel normal in viewspace\n"
2752 "       // LightVector = pixel to light in viewspace\n"
2753 "       // CubeVector = position in lightspace\n"
2754 "       // eyevector = pixel to view in viewspace\n"
2755 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2756 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2757 "#ifdef USEDIFFUSE\n"
2758 "       // calculate diffuse shading\n"
2759 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2760 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2761 "#endif\n"
2762 "#ifdef USESPECULAR\n"
2763 "       // calculate directional shading\n"
2764 "       float3 eyevector = position * -1.0;\n"
2765 "#  ifdef USEEXACTSPECULARMATH\n"
2766 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2767 "#  else\n"
2768 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2769 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2770 "#  endif\n"
2771 "#endif\n"
2772 "\n"
2773 "#if defined(USESHADOWMAP2D)\n"
2774 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2775 "#ifdef USESHADOWMAPVSDCT\n"
2776 ", Texture_CubeProjection\n"
2777 "#endif\n"
2778 "       ));\n"
2779 "#endif\n"
2780 "\n"
2781 "#ifdef USEDIFFUSE\n"
2782 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2783 "#else\n"
2784 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2785 "#endif\n"
2786 "#ifdef USESPECULAR\n"
2787 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2788 "#else\n"
2789 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2790 "#endif\n"
2791 "\n"
2792 "# ifdef USECUBEFILTER\n"
2793 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2794 "       gl_FragData0.rgb *= cubecolor;\n"
2795 "       gl_FragData1.rgb *= cubecolor;\n"
2796 "# endif\n"
2797 "}\n"
2798 "#endif // FRAGMENT_SHADER\n"
2799 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2800 "\n"
2801 "\n"
2802 "\n"
2803 "\n"
2804 "#ifdef VERTEX_SHADER\n"
2805 "void main\n"
2806 "(\n"
2807 "float4 gl_Vertex : POSITION,\n"
2808 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2809 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2810 "float4 gl_Color : COLOR0,\n"
2811 "#endif\n"
2812 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2813 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2814 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2815 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2816 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2817 "\n"
2818 "uniform float3 EyePosition : register(c24),\n"
2819 "uniform float4x4 TexMatrix : register(c0),\n"
2820 "#ifdef USEVERTEXTEXTUREBLEND\n"
2821 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2822 "#endif\n"
2823 "#ifdef MODE_LIGHTSOURCE\n"
2824 "uniform float4x4 ModelToLight : register(c20),\n"
2825 "#endif\n"
2826 "#ifdef MODE_LIGHTSOURCE\n"
2827 "uniform float3 LightPosition : register(c27),\n"
2828 "#endif\n"
2829 "#ifdef MODE_LIGHTDIRECTION\n"
2830 "uniform float3 LightDir : register(c26),\n"
2831 "#endif\n"
2832 "uniform float4 FogPlane : register(c25),\n"
2833 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2834 "uniform float3 LightPosition : register(c27),\n"
2835 "#endif\n"
2836 "#ifdef USESHADOWMAPORTHO\n"
2837 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2838 "#endif\n"
2839 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2840 "out float4 gl_FrontColor : COLOR,\n"
2841 "#endif\n"
2842 "out float4 TexCoordBoth : TEXCOORD0,\n"
2843 "#ifdef USELIGHTMAP\n"
2844 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2845 "#endif\n"
2846 "#ifdef USEEYEVECTOR\n"
2847 "out float3 EyeVector : TEXCOORD2,\n"
2848 "#endif\n"
2849 "#ifdef USEREFLECTION\n"
2850 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2851 "#endif\n"
2852 "#ifdef USEFOG\n"
2853 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2854 "#endif\n"
2855 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2856 "out float3 LightVector : TEXCOORD1,\n"
2857 "#endif\n"
2858 "#ifdef MODE_LIGHTSOURCE\n"
2859 "out float3 CubeVector : TEXCOORD3,\n"
2860 "#endif\n"
2861 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2862 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2863 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2864 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2865 "#endif\n"
2866 "#ifdef USESHADOWMAPORTHO\n"
2867 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2868 "#endif\n"
2869 "out float4 gl_Position : POSITION\n"
2870 ")\n"
2871 "{\n"
2872 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2873 "#ifdef HLSL\n"
2874 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2875 "#else\n"
2876 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2877 "#endif\n"
2878 "#endif\n"
2879 "       // copy the surface texcoord\n"
2880 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2881 "#ifdef USEVERTEXTEXTUREBLEND\n"
2882 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2883 "#endif\n"
2884 "#ifdef USELIGHTMAP\n"
2885 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2886 "#endif\n"
2887 "\n"
2888 "#ifdef MODE_LIGHTSOURCE\n"
2889 "       // transform vertex position into light attenuation/cubemap space\n"
2890 "       // (-1 to +1 across the light box)\n"
2891 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2892 "\n"
2893 "# ifdef USEDIFFUSE\n"
2894 "       // transform unnormalized light direction into tangent space\n"
2895 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2896 "       //  normalize it per pixel)\n"
2897 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2898 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2899 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2900 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2901 "# endif\n"
2902 "#endif\n"
2903 "\n"
2904 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2905 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2906 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2907 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2908 "#endif\n"
2909 "\n"
2910 "       // transform unnormalized eye direction into tangent space\n"
2911 "#ifdef USEEYEVECTOR\n"
2912 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2913 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2914 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2915 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2916 "#endif\n"
2917 "\n"
2918 "#ifdef USEFOG\n"
2919 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2920 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2921 "#endif\n"
2922 "\n"
2923 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2924 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2925 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2926 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2927 "#endif\n"
2928 "\n"
2929 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2930 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2931 "\n"
2932 "#ifdef USESHADOWMAPORTHO\n"
2933 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2934 "#endif\n"
2935 "\n"
2936 "#ifdef USEREFLECTION\n"
2937 "       ModelViewProjectionPosition = gl_Position;\n"
2938 "#endif\n"
2939 "}\n"
2940 "#endif // VERTEX_SHADER\n"
2941 "\n"
2942 "\n"
2943 "\n"
2944 "\n"
2945 "#ifdef FRAGMENT_SHADER\n"
2946 "void main\n"
2947 "(\n"
2948 "#ifdef USEDEFERREDLIGHTMAP\n"
2949 "#ifdef HLSL\n"
2950 "float2 Pixel : VPOS,\n"
2951 "#else\n"
2952 "float2 Pixel : WPOS,\n"
2953 "#endif\n"
2954 "#endif\n"
2955 "float4 gl_FrontColor : COLOR,\n"
2956 "float4 TexCoordBoth : TEXCOORD0,\n"
2957 "#ifdef USELIGHTMAP\n"
2958 "float2 TexCoordLightmap : TEXCOORD1,\n"
2959 "#endif\n"
2960 "#ifdef USEEYEVECTOR\n"
2961 "float3 EyeVector : TEXCOORD2,\n"
2962 "#endif\n"
2963 "#ifdef USEREFLECTION\n"
2964 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2965 "#endif\n"
2966 "#ifdef USEFOG\n"
2967 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2968 "#endif\n"
2969 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2970 "float3 LightVector : TEXCOORD1,\n"
2971 "#endif\n"
2972 "#ifdef MODE_LIGHTSOURCE\n"
2973 "float3 CubeVector : TEXCOORD3,\n"
2974 "#endif\n"
2975 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2976 "float4 ModelViewPosition : TEXCOORD0,\n"
2977 "#endif\n"
2978 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2979 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2980 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2981 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2982 "#endif\n"
2983 "#ifdef USESHADOWMAPORTHO\n"
2984 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2985 "#endif\n"
2986 "\n"
2987 "uniform sampler Texture_Normal : register(s0),\n"
2988 "uniform sampler Texture_Color : register(s1),\n"
2989 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2990 "uniform sampler Texture_Gloss : register(s2),\n"
2991 "#endif\n"
2992 "#ifdef USEGLOW\n"
2993 "uniform sampler Texture_Glow : register(s3),\n"
2994 "#endif\n"
2995 "#ifdef USEVERTEXTEXTUREBLEND\n"
2996 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2997 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2998 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2999 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3000 "#endif\n"
3001 "#ifdef USEGLOW\n"
3002 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3003 "#endif\n"
3004 "#endif\n"
3005 "#ifdef USECOLORMAPPING\n"
3006 "uniform sampler Texture_Pants : register(s4),\n"
3007 "uniform sampler Texture_Shirt : register(s7),\n"
3008 "#endif\n"
3009 "#ifdef USEFOG\n"
3010 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3011 "uniform sampler Texture_FogMask : register(s8),\n"
3012 "#endif\n"
3013 "#ifdef USELIGHTMAP\n"
3014 "uniform sampler Texture_Lightmap : register(s9),\n"
3015 "#endif\n"
3016 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3017 "uniform sampler Texture_Deluxemap : register(s10),\n"
3018 "#endif\n"
3019 "#ifdef USEREFLECTION\n"
3020 "uniform sampler Texture_Reflection : register(s7),\n"
3021 "#endif\n"
3022 "\n"
3023 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3024 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3025 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3026 "#endif\n"
3027 "#ifdef USEDEFERREDLIGHTMAP\n"
3028 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3029 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3030 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3031 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3032 "#endif\n"
3033 "\n"
3034 "#ifdef USECOLORMAPPING\n"
3035 "uniform half3 Color_Pants : register(c7),\n"
3036 "uniform half3 Color_Shirt : register(c8),\n"
3037 "#endif\n"
3038 "#ifdef USEFOG\n"
3039 "uniform float3 FogColor : register(c16),\n"
3040 "uniform float FogRangeRecip : register(c20),\n"
3041 "uniform float FogPlaneViewDist : register(c19),\n"
3042 "uniform float FogHeightFade : register(c17),\n"
3043 "#endif\n"
3044 "\n"
3045 "#ifdef USEOFFSETMAPPING\n"
3046 "uniform float OffsetMapping_Scale : register(c24),\n"
3047 "#endif\n"
3048 "\n"
3049 "#ifdef USEDEFERREDLIGHTMAP\n"
3050 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3051 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3052 "uniform half3 DeferredMod_Specular : register(c13),\n"
3053 "#endif\n"
3054 "uniform half3 Color_Ambient : register(c3),\n"
3055 "uniform half3 Color_Diffuse : register(c4),\n"
3056 "uniform half3 Color_Specular : register(c5),\n"
3057 "uniform half SpecularPower : register(c36),\n"
3058 "#ifdef USEGLOW\n"
3059 "uniform half3 Color_Glow : register(c6),\n"
3060 "#endif\n"
3061 "uniform half Alpha : register(c0),\n"
3062 "#ifdef USEREFLECTION\n"
3063 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3064 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3065 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3066 "uniform half4 ReflectColor : register(c26),\n"
3067 "#endif\n"
3068 "#ifdef USEREFLECTCUBE\n"
3069 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3070 "uniform sampler Texture_ReflectMask : register(s5),\n"
3071 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3072 "#endif\n"
3073 "#ifdef MODE_LIGHTDIRECTION\n"
3074 "uniform half3 LightColor : register(c21),\n"
3075 "#endif\n"
3076 "#ifdef MODE_LIGHTSOURCE\n"
3077 "uniform half3 LightColor : register(c21),\n"
3078 "#endif\n"
3079 "\n"
3080 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3081 "uniform sampler Texture_Attenuation : register(s9),\n"
3082 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3083 "#endif\n"
3084 "\n"
3085 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3086 "\n"
3087 "#ifdef USESHADOWMAP2D\n"
3088 "# ifdef USESHADOWSAMPLER\n"
3089 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3090 "# else\n"
3091 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3092 "# endif\n"
3093 "#endif\n"
3094 "\n"
3095 "#ifdef USESHADOWMAPVSDCT\n"
3096 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3097 "#endif\n"
3098 "\n"
3099 "#if defined(USESHADOWMAP2D)\n"
3100 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3101 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3102 "#endif\n"
3103 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3104 "\n"
3105 "out float4 gl_FragColor : COLOR\n"
3106 ")\n"
3107 "{\n"
3108 "       float2 TexCoord = TexCoordBoth.xy;\n"
3109 "#ifdef USEVERTEXTEXTUREBLEND\n"
3110 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3111 "#endif\n"
3112 "#ifdef USEOFFSETMAPPING\n"
3113 "       // apply offsetmapping\n"
3114 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3115 "#define TexCoord TexCoordOffset\n"
3116 "#endif\n"
3117 "\n"
3118 "       // combine the diffuse textures (base, pants, shirt)\n"
3119 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3120 "#ifdef USEALPHAKILL\n"
3121 "       if (color.a < 0.5)\n"
3122 "               discard;\n"
3123 "#endif\n"
3124 "       color.a *= Alpha;\n"
3125 "#ifdef USECOLORMAPPING\n"
3126 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3127 "#endif\n"
3128 "#ifdef USEVERTEXTEXTUREBLEND\n"
3129 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3130 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3131 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3132 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3133 "       color.a = 1.0;\n"
3134 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3135 "#endif\n"
3136 "\n"
3137 "       // get the surface normal\n"
3138 "#ifdef USEVERTEXTEXTUREBLEND\n"
3139 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3140 "#else\n"
3141 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3142 "#endif\n"
3143 "\n"
3144 "       // get the material colors\n"
3145 "       half3 diffusetex = color.rgb;\n"
3146 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3147 "# ifdef USEVERTEXTEXTUREBLEND\n"
3148 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3149 "# else\n"
3150 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3151 "# endif\n"
3152 "#endif\n"
3153 "\n"
3154 "#ifdef USEREFLECTCUBE\n"
3155 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3156 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3157 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3158 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3159 "#endif\n"
3160 "\n"
3161 "\n"
3162 "\n"
3163 "\n"
3164 "#ifdef MODE_LIGHTSOURCE\n"
3165 "       // light source\n"
3166 "#ifdef USEDIFFUSE\n"
3167 "       half3 lightnormal = half3(normalize(LightVector));\n"
3168 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3169 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3170 "#ifdef USESPECULAR\n"
3171 "#ifdef USEEXACTSPECULARMATH\n"
3172 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3173 "#else\n"
3174 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3175 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3176 "#endif\n"
3177 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3178 "#endif\n"
3179 "#else\n"
3180 "       color.rgb = diffusetex * Color_Ambient;\n"
3181 "#endif\n"
3182 "       color.rgb *= LightColor;\n"
3183 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3184 "#if defined(USESHADOWMAP2D)\n"
3185 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3186 "#ifdef USESHADOWMAPVSDCT\n"
3187 ", Texture_CubeProjection\n"
3188 "#endif\n"
3189 "       ));\n"
3190 "\n"
3191 "#endif\n"
3192 "# ifdef USECUBEFILTER\n"
3193 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3194 "# endif\n"
3195 "\n"
3196 "#ifdef USESHADOWMAP2D\n"
3197 "#ifdef USESHADOWMAPVSDCT\n"
3198 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3199 "#else\n"
3200 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3201 "#endif\n"
3202 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3203 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3204 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3205 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3206 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3207 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3208 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3209 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3210 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3211 "//     color.r = half(shadowmaptc.z);\n"
3212 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3213 "//     color.r = half(shadowmaptc.z);\n"
3214 "//     color.r = 1;\n"
3215 "//     color.rgb = abs(CubeVector);\n"
3216 "#endif\n"
3217 "//     color.rgb = half3(1,1,1);\n"
3218 "#endif // MODE_LIGHTSOURCE\n"
3219 "\n"
3220 "\n"
3221 "\n"
3222 "\n"
3223 "#ifdef MODE_LIGHTDIRECTION\n"
3224 "#define SHADING\n"
3225 "#ifdef USEDIFFUSE\n"
3226 "       half3 lightnormal = half3(normalize(LightVector));\n"
3227 "#endif\n"
3228 "#define lightcolor LightColor\n"
3229 "#endif // MODE_LIGHTDIRECTION\n"
3230 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3231 "#define SHADING\n"
3232 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3233 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3234 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3235 "       // convert modelspace light vector to tangentspace\n"
3236 "       half3 lightnormal;\n"
3237 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3238 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3239 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3240 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3241 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3242 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3243 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3244 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3245 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3246 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3247 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3248 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3249 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3250 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3251 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3252 "#define SHADING\n"
3253 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3254 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3255 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3256 "#endif\n"
3257 "\n"
3258 "\n"
3259 "\n"
3260 "\n"
3261 "#ifdef MODE_FAKELIGHT\n"
3262 "#define SHADING\n"
3263 "half3 lightnormal = half3(normalize(EyeVector));\n"
3264 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3265 "#endif // MODE_FAKELIGHT\n"
3266 "\n"
3267 "\n"
3268 "\n"
3269 "\n"
3270 "#ifdef MODE_LIGHTMAP\n"
3271 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3272 "#endif // MODE_LIGHTMAP\n"
3273 "#ifdef MODE_VERTEXCOLOR\n"
3274 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3275 "#endif // MODE_VERTEXCOLOR\n"
3276 "#ifdef MODE_FLATCOLOR\n"
3277 "       color.rgb = diffusetex * Color_Ambient;\n"
3278 "#endif // MODE_FLATCOLOR\n"
3279 "\n"
3280 "\n"
3281 "\n"
3282 "\n"
3283 "#ifdef SHADING\n"
3284 "# ifdef USEDIFFUSE\n"
3285 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3286 "#  ifdef USESPECULAR\n"
3287 "#   ifdef USEEXACTSPECULARMATH\n"
3288 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3289 "#   else\n"
3290 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3291 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3292 "#   endif\n"
3293 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3294 "#  else\n"
3295 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3296 "#  endif\n"
3297 "# else\n"
3298 "       color.rgb = diffusetex * Color_Ambient;\n"
3299 "# endif\n"
3300 "#endif\n"
3301 "\n"
3302 "#ifdef USESHADOWMAPORTHO\n"
3303 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3304 "#endif\n"
3305 "\n"
3306 "#ifdef USEDEFERREDLIGHTMAP\n"
3307 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3308 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3309 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3310 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3311 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3312 "#endif\n"
3313 "\n"
3314 "#ifdef USEGLOW\n"
3315 "#ifdef USEVERTEXTEXTUREBLEND\n"
3316 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3317 "#else\n"
3318 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3319 "#endif\n"
3320 "#endif\n"
3321 "\n"
3322 "#ifdef USEFOG\n"
3323 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3324 "#endif\n"
3325 "\n"
3326 "       // 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"
3327 "#ifdef USEREFLECTION\n"
3328 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3329 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3330 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3331 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3332 "       // FIXME temporary hack to detect the case that the reflection\n"
3333 "       // gets blackened at edges due to leaving the area that contains actual\n"
3334 "       // content.\n"
3335 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3336 "       // 'appening.\n"
3337 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3338 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3339 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3340 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3341 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3342 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3343 "#endif\n"
3344 "\n"
3345 "       gl_FragColor = float4(color);\n"
3346 "}\n"
3347 "#endif // FRAGMENT_SHADER\n"
3348 "\n"
3349 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3350 "#endif // !MODE_DEFERREDGEOMETRY\n"
3351 "#endif // !MODE_WATER\n"
3352 "#endif // !MODE_REFRACTION\n"
3353 "#endif // !MODE_BLOOMBLUR\n"
3354 "#endif // !MODE_GENERIC\n"
3355 "#endif // !MODE_POSTPROCESS\n"
3356 "#endif // !MODE_SHOWDEPTH\n"
3357 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3358 ;
3359
3360 char *glslshaderstring = NULL;
3361 char *hlslshaderstring = NULL;
3362
3363 //=======================================================================================================================================================
3364
3365 typedef struct shaderpermutationinfo_s
3366 {
3367         const char *pretext;
3368         const char *name;
3369 }
3370 shaderpermutationinfo_t;
3371
3372 typedef struct shadermodeinfo_s
3373 {
3374         const char *vertexfilename;
3375         const char *geometryfilename;
3376         const char *fragmentfilename;
3377         const char *pretext;
3378         const char *name;
3379 }
3380 shadermodeinfo_t;
3381
3382 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3383 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3384 {
3385         {"#define USEDIFFUSE\n", " diffuse"},
3386         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3387         {"#define USEVIEWTINT\n", " viewtint"},
3388         {"#define USECOLORMAPPING\n", " colormapping"},
3389         {"#define USESATURATION\n", " saturation"},
3390         {"#define USEFOGINSIDE\n", " foginside"},
3391         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3392         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3393         {"#define USEGAMMARAMPS\n", " gammaramps"},
3394         {"#define USECUBEFILTER\n", " cubefilter"},
3395         {"#define USEGLOW\n", " glow"},
3396         {"#define USEBLOOM\n", " bloom"},
3397         {"#define USESPECULAR\n", " specular"},
3398         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3399         {"#define USEREFLECTION\n", " reflection"},
3400         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3401         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3402         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3403         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3404         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3405         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3406         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3407         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3408         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3409         {"#define USEALPHAKILL\n", " alphakill"},
3410         {"#define USEREFLECTCUBE\n", " reflectcube"},
3411         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3412         {"#define USEBOUNCEGRID\n", " bouncegrid"},
3413 };
3414
3415 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3416 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3417 {
3418         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3419         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3420         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3421         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3422         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3423         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3424         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3425         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3426         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3427         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3428         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3429         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3430         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3431         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3432         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3433         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3434 };
3435
3436 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3437 {
3438         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3439         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3440         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3441         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3442         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3443         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3444         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3445         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3446         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3447         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3448         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3449         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3450         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3451         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3452         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3453         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3454 };
3455
3456 struct r_glsl_permutation_s;
3457 typedef struct r_glsl_permutation_s
3458 {
3459         /// hash lookup data
3460         struct r_glsl_permutation_s *hashnext;
3461         unsigned int mode;
3462         unsigned int permutation;
3463
3464         /// indicates if we have tried compiling this permutation already
3465         qboolean compiled;
3466         /// 0 if compilation failed
3467         int program;
3468         // texture units assigned to each detected uniform
3469         int tex_Texture_First;
3470         int tex_Texture_Second;
3471         int tex_Texture_GammaRamps;
3472         int tex_Texture_Normal;
3473         int tex_Texture_Color;
3474         int tex_Texture_Gloss;
3475         int tex_Texture_Glow;
3476         int tex_Texture_SecondaryNormal;
3477         int tex_Texture_SecondaryColor;
3478         int tex_Texture_SecondaryGloss;
3479         int tex_Texture_SecondaryGlow;
3480         int tex_Texture_Pants;
3481         int tex_Texture_Shirt;
3482         int tex_Texture_FogHeightTexture;
3483         int tex_Texture_FogMask;
3484         int tex_Texture_Lightmap;
3485         int tex_Texture_Deluxemap;
3486         int tex_Texture_Attenuation;
3487         int tex_Texture_Cube;
3488         int tex_Texture_Refraction;
3489         int tex_Texture_Reflection;
3490         int tex_Texture_ShadowMap2D;
3491         int tex_Texture_CubeProjection;
3492         int tex_Texture_ScreenDepth;
3493         int tex_Texture_ScreenNormalMap;
3494         int tex_Texture_ScreenDiffuse;
3495         int tex_Texture_ScreenSpecular;
3496         int tex_Texture_ReflectMask;
3497         int tex_Texture_ReflectCube;
3498         int tex_Texture_BounceGrid;
3499         /// locations of detected uniforms in program object, or -1 if not found
3500         int loc_Texture_First;
3501         int loc_Texture_Second;
3502         int loc_Texture_GammaRamps;
3503         int loc_Texture_Normal;
3504         int loc_Texture_Color;
3505         int loc_Texture_Gloss;
3506         int loc_Texture_Glow;
3507         int loc_Texture_SecondaryNormal;
3508         int loc_Texture_SecondaryColor;
3509         int loc_Texture_SecondaryGloss;
3510         int loc_Texture_SecondaryGlow;
3511         int loc_Texture_Pants;
3512         int loc_Texture_Shirt;
3513         int loc_Texture_FogHeightTexture;
3514         int loc_Texture_FogMask;
3515         int loc_Texture_Lightmap;
3516         int loc_Texture_Deluxemap;
3517         int loc_Texture_Attenuation;
3518         int loc_Texture_Cube;
3519         int loc_Texture_Refraction;
3520         int loc_Texture_Reflection;
3521         int loc_Texture_ShadowMap2D;
3522         int loc_Texture_CubeProjection;
3523         int loc_Texture_ScreenDepth;
3524         int loc_Texture_ScreenNormalMap;
3525         int loc_Texture_ScreenDiffuse;
3526         int loc_Texture_ScreenSpecular;
3527         int loc_Texture_ReflectMask;
3528         int loc_Texture_ReflectCube;
3529         int loc_Texture_BounceGrid;
3530         int loc_Alpha;
3531         int loc_BloomBlur_Parameters;
3532         int loc_ClientTime;
3533         int loc_Color_Ambient;
3534         int loc_Color_Diffuse;
3535         int loc_Color_Specular;
3536         int loc_Color_Glow;
3537         int loc_Color_Pants;
3538         int loc_Color_Shirt;
3539         int loc_DeferredColor_Ambient;
3540         int loc_DeferredColor_Diffuse;
3541         int loc_DeferredColor_Specular;
3542         int loc_DeferredMod_Diffuse;
3543         int loc_DeferredMod_Specular;
3544         int loc_DistortScaleRefractReflect;
3545         int loc_EyePosition;
3546         int loc_FogColor;
3547         int loc_FogHeightFade;
3548         int loc_FogPlane;
3549         int loc_FogPlaneViewDist;
3550         int loc_FogRangeRecip;
3551         int loc_LightColor;
3552         int loc_LightDir;
3553         int loc_LightPosition;
3554         int loc_OffsetMapping_Scale;
3555         int loc_PixelSize;
3556         int loc_ReflectColor;
3557         int loc_ReflectFactor;
3558         int loc_ReflectOffset;
3559         int loc_RefractColor;
3560         int loc_Saturation;
3561         int loc_ScreenCenterRefractReflect;
3562         int loc_ScreenScaleRefractReflect;
3563         int loc_ScreenToDepth;
3564         int loc_ShadowMap_Parameters;
3565         int loc_ShadowMap_TextureScale;
3566         int loc_SpecularPower;
3567         int loc_UserVec1;
3568         int loc_UserVec2;
3569         int loc_UserVec3;
3570         int loc_UserVec4;
3571         int loc_ViewTintColor;
3572         int loc_ViewToLight;
3573         int loc_ModelToLight;
3574         int loc_TexMatrix;
3575         int loc_BackgroundTexMatrix;
3576         int loc_ModelViewProjectionMatrix;
3577         int loc_ModelViewMatrix;
3578         int loc_PixelToScreenTexCoord;
3579         int loc_ModelToReflectCube;
3580         int loc_ShadowMapMatrix;
3581         int loc_BloomColorSubtract;
3582         int loc_NormalmapScrollBlend;
3583         int loc_BounceGridMatrix;
3584         int loc_BounceGridIntensity;
3585 }
3586 r_glsl_permutation_t;
3587
3588 #define SHADERPERMUTATION_HASHSIZE 256
3589
3590
3591 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3592 // these can NOT degrade! only use for simple stuff
3593 enum
3594 {
3595         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3596         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3597         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3598         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3599         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3600         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3601 };
3602 #define SHADERSTATICPARMS_COUNT 6
3603
3604 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3605 static int shaderstaticparms_count = 0;
3606
3607 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3608 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3609 qboolean R_CompileShader_CheckStaticParms(void)
3610 {
3611         static int r_compileshader_staticparms_save[1];
3612         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3613         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3614
3615         // detect all
3616         if (r_glsl_saturation_redcompensate.integer)
3617                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3618         if (r_shadow_glossexact.integer)
3619                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3620         if (r_glsl_postprocess.integer)
3621         {
3622                 if (r_glsl_postprocess_uservec1_enable.integer)
3623                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3624                 if (r_glsl_postprocess_uservec2_enable.integer)
3625                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3626                 if (r_glsl_postprocess_uservec3_enable.integer)
3627                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3628                 if (r_glsl_postprocess_uservec4_enable.integer)
3629                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3630         }
3631         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3632 }
3633
3634 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3635         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3636                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3637         else \
3638                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3639 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3640 {
3641         shaderstaticparms_count = 0;
3642
3643         // emit all
3644         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3645         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3646         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3647         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3648         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3649         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3650 }
3651
3652 /// information about each possible shader permutation
3653 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3654 /// currently selected permutation
3655 r_glsl_permutation_t *r_glsl_permutation;
3656 /// storage for permutations linked in the hash table
3657 memexpandablearray_t r_glsl_permutationarray;
3658
3659 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3660 {
3661         //unsigned int hashdepth = 0;
3662         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3663         r_glsl_permutation_t *p;
3664         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3665         {
3666                 if (p->mode == mode && p->permutation == permutation)
3667                 {
3668                         //if (hashdepth > 10)
3669                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3670                         return p;
3671                 }
3672                 //hashdepth++;
3673         }
3674         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3675         p->mode = mode;
3676         p->permutation = permutation;
3677         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3678         r_glsl_permutationhash[mode][hashindex] = p;
3679         //if (hashdepth > 10)
3680         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3681         return p;
3682 }
3683
3684 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3685 {
3686         char *shaderstring;
3687         if (!filename || !filename[0])
3688                 return NULL;
3689         if (!strcmp(filename, "glsl/default.glsl"))
3690         {
3691                 if (!glslshaderstring)
3692                 {
3693                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3694                         if (glslshaderstring)
3695                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3696                         else
3697                                 glslshaderstring = (char *)builtinshaderstring;
3698                 }
3699                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3700                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3701                 return shaderstring;
3702         }
3703         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3704         if (shaderstring)
3705         {
3706                 if (printfromdisknotice)
3707                         Con_DPrintf("from disk %s... ", filename);
3708                 return shaderstring;
3709         }
3710         return shaderstring;
3711 }
3712
3713 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3714 {
3715         int i;
3716         int sampler;
3717         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3718         char *vertexstring, *geometrystring, *fragmentstring;
3719         char permutationname[256];
3720         int vertstrings_count = 0;
3721         int geomstrings_count = 0;
3722         int fragstrings_count = 0;
3723         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3724         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3725         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3726
3727         if (p->compiled)
3728                 return;
3729         p->compiled = true;
3730         p->program = 0;
3731
3732         permutationname[0] = 0;
3733         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3734         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3735         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3736
3737         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3738
3739         // the first pretext is which type of shader to compile as
3740         // (later these will all be bound together as a program object)
3741         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3742         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3743         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3744
3745         // the second pretext is the mode (for example a light source)
3746         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3747         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3748         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3749         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3750
3751         // now add all the permutation pretexts
3752         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3753         {
3754                 if (permutation & (1<<i))
3755                 {
3756                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3757                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3758                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3759                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3760                 }
3761                 else
3762                 {
3763                         // keep line numbers correct
3764                         vertstrings_list[vertstrings_count++] = "\n";
3765                         geomstrings_list[geomstrings_count++] = "\n";
3766                         fragstrings_list[fragstrings_count++] = "\n";
3767                 }
3768         }
3769
3770         // add static parms
3771         R_CompileShader_AddStaticParms(mode, permutation);
3772         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3773         vertstrings_count += shaderstaticparms_count;
3774         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3775         geomstrings_count += shaderstaticparms_count;
3776         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3777         fragstrings_count += shaderstaticparms_count;
3778
3779         // now append the shader text itself
3780         vertstrings_list[vertstrings_count++] = vertexstring;
3781         geomstrings_list[geomstrings_count++] = geometrystring;
3782         fragstrings_list[fragstrings_count++] = fragmentstring;
3783
3784         // if any sources were NULL, clear the respective list
3785         if (!vertexstring)
3786                 vertstrings_count = 0;
3787         if (!geometrystring)
3788                 geomstrings_count = 0;
3789         if (!fragmentstring)
3790                 fragstrings_count = 0;
3791
3792         // compile the shader program
3793         if (vertstrings_count + geomstrings_count + fragstrings_count)
3794                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3795         if (p->program)
3796         {
3797                 CHECKGLERROR
3798                 qglUseProgram(p->program);CHECKGLERROR
3799                 // look up all the uniform variable names we care about, so we don't
3800                 // have to look them up every time we set them
3801
3802                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
3803                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
3804                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3805                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
3806                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
3807                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
3808                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
3809                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3810                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3811                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3812                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3813                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
3814                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
3815                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3816                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
3817                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
3818                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3819                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
3820                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
3821                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
3822                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
3823                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3824                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3825                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3826                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3827                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3828                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3829                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3830                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3831                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
3832                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
3833                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3834                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
3835                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
3836                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
3837                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
3838                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
3839                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
3840                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
3841                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3842                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3843                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3844                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3845                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3846                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3847                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
3848                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
3849                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
3850                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
3851                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3852                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
3853                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
3854                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
3855                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
3856                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3857                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
3858                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
3859                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
3860                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
3861                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
3862                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
3863                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3864                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3865                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
3866                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3867                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3868                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
3869                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
3870                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
3871                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
3872                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
3873                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
3874                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
3875                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
3876                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
3877                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3878                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
3879                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3880                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3881                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
3882                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3883                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
3884                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3885                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
3886                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
3887                 // initialize the samplers to refer to the texture units we use
3888                 p->tex_Texture_First = -1;
3889                 p->tex_Texture_Second = -1;
3890                 p->tex_Texture_GammaRamps = -1;
3891                 p->tex_Texture_Normal = -1;
3892                 p->tex_Texture_Color = -1;
3893                 p->tex_Texture_Gloss = -1;
3894                 p->tex_Texture_Glow = -1;
3895                 p->tex_Texture_SecondaryNormal = -1;
3896                 p->tex_Texture_SecondaryColor = -1;
3897                 p->tex_Texture_SecondaryGloss = -1;
3898                 p->tex_Texture_SecondaryGlow = -1;
3899                 p->tex_Texture_Pants = -1;
3900                 p->tex_Texture_Shirt = -1;
3901                 p->tex_Texture_FogHeightTexture = -1;
3902                 p->tex_Texture_FogMask = -1;
3903                 p->tex_Texture_Lightmap = -1;
3904                 p->tex_Texture_Deluxemap = -1;
3905                 p->tex_Texture_Attenuation = -1;
3906                 p->tex_Texture_Cube = -1;
3907                 p->tex_Texture_Refraction = -1;
3908                 p->tex_Texture_Reflection = -1;
3909                 p->tex_Texture_ShadowMap2D = -1;
3910                 p->tex_Texture_CubeProjection = -1;
3911                 p->tex_Texture_ScreenDepth = -1;
3912                 p->tex_Texture_ScreenNormalMap = -1;
3913                 p->tex_Texture_ScreenDiffuse = -1;
3914                 p->tex_Texture_ScreenSpecular = -1;
3915                 p->tex_Texture_ReflectMask = -1;
3916                 p->tex_Texture_ReflectCube = -1;
3917                 p->tex_Texture_BounceGrid = -1;
3918                 sampler = 0;
3919                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
3920                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
3921                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
3922                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
3923                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
3924                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
3925                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
3926                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3927                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
3928                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
3929                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
3930                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
3931                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
3932                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3933                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
3934                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
3935                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
3936                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
3937                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
3938                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
3939                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
3940                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
3941                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
3942                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
3943                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3944                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
3945                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
3946                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
3947                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
3948                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
3949                 CHECKGLERROR
3950                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3951         }
3952         else
3953                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3954
3955         // free the strings
3956         if (vertexstring)
3957                 Mem_Free(vertexstring);
3958         if (geometrystring)
3959                 Mem_Free(geometrystring);
3960         if (fragmentstring)
3961                 Mem_Free(fragmentstring);
3962 }
3963
3964 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3965 {
3966         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3967         if (r_glsl_permutation != perm)
3968         {
3969                 r_glsl_permutation = perm;
3970                 if (!r_glsl_permutation->program)
3971                 {
3972                         if (!r_glsl_permutation->compiled)
3973                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3974                         if (!r_glsl_permutation->program)
3975                         {
3976                                 // remove features until we find a valid permutation
3977                                 int i;
3978                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3979                                 {
3980                                         // reduce i more quickly whenever it would not remove any bits
3981                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3982                                         if (!(permutation & j))
3983                                                 continue;
3984                                         permutation -= j;
3985                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3986                                         if (!r_glsl_permutation->compiled)
3987                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3988                                         if (r_glsl_permutation->program)
3989                                                 break;
3990                                 }
3991                                 if (i >= SHADERPERMUTATION_COUNT)
3992                                 {
3993                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3994                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3995                                         qglUseProgram(0);CHECKGLERROR
3996                                         return; // no bit left to clear, entire mode is broken
3997                                 }
3998                         }
3999                 }
4000                 CHECKGLERROR
4001                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
4002         }
4003         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4004         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4005         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
4006 }
4007
4008 #ifdef SUPPORTD3D
4009
4010 #ifdef SUPPORTD3D
4011 #include <d3d9.h>
4012 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4013 extern D3DCAPS9 vid_d3d9caps;
4014 #endif
4015
4016 struct r_hlsl_permutation_s;
4017 typedef struct r_hlsl_permutation_s
4018 {
4019         /// hash lookup data
4020         struct r_hlsl_permutation_s *hashnext;
4021         unsigned int mode;
4022         unsigned int permutation;
4023
4024         /// indicates if we have tried compiling this permutation already
4025         qboolean compiled;
4026         /// NULL if compilation failed
4027         IDirect3DVertexShader9 *vertexshader;
4028         IDirect3DPixelShader9 *pixelshader;
4029 }
4030 r_hlsl_permutation_t;
4031
4032 typedef enum D3DVSREGISTER_e
4033 {
4034         D3DVSREGISTER_TexMatrix = 0, // float4x4
4035         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4036         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4037         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4038         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4039         D3DVSREGISTER_ModelToLight = 20, // float4x4
4040         D3DVSREGISTER_EyePosition = 24,
4041         D3DVSREGISTER_FogPlane = 25,
4042         D3DVSREGISTER_LightDir = 26,
4043         D3DVSREGISTER_LightPosition = 27,
4044 }
4045 D3DVSREGISTER_t;
4046
4047 typedef enum D3DPSREGISTER_e
4048 {
4049         D3DPSREGISTER_Alpha = 0,
4050         D3DPSREGISTER_BloomBlur_Parameters = 1,
4051         D3DPSREGISTER_ClientTime = 2,
4052         D3DPSREGISTER_Color_Ambient = 3,
4053         D3DPSREGISTER_Color_Diffuse = 4,
4054         D3DPSREGISTER_Color_Specular = 5,
4055         D3DPSREGISTER_Color_Glow = 6,
4056         D3DPSREGISTER_Color_Pants = 7,
4057         D3DPSREGISTER_Color_Shirt = 8,
4058         D3DPSREGISTER_DeferredColor_Ambient = 9,
4059         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4060         D3DPSREGISTER_DeferredColor_Specular = 11,
4061         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4062         D3DPSREGISTER_DeferredMod_Specular = 13,
4063         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4064         D3DPSREGISTER_EyePosition = 15, // unused
4065         D3DPSREGISTER_FogColor = 16,
4066         D3DPSREGISTER_FogHeightFade = 17,
4067         D3DPSREGISTER_FogPlane = 18,
4068         D3DPSREGISTER_FogPlaneViewDist = 19,
4069         D3DPSREGISTER_FogRangeRecip = 20,
4070         D3DPSREGISTER_LightColor = 21,
4071         D3DPSREGISTER_LightDir = 22, // unused
4072         D3DPSREGISTER_LightPosition = 23,
4073         D3DPSREGISTER_OffsetMapping_Scale = 24,
4074         D3DPSREGISTER_PixelSize = 25,
4075         D3DPSREGISTER_ReflectColor = 26,
4076         D3DPSREGISTER_ReflectFactor = 27,
4077         D3DPSREGISTER_ReflectOffset = 28,
4078         D3DPSREGISTER_RefractColor = 29,
4079         D3DPSREGISTER_Saturation = 30,
4080         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4081         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4082         D3DPSREGISTER_ScreenToDepth = 33,
4083         D3DPSREGISTER_ShadowMap_Parameters = 34,
4084         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4085         D3DPSREGISTER_SpecularPower = 36,
4086         D3DPSREGISTER_UserVec1 = 37,
4087         D3DPSREGISTER_UserVec2 = 38,
4088         D3DPSREGISTER_UserVec3 = 39,
4089         D3DPSREGISTER_UserVec4 = 40,
4090         D3DPSREGISTER_ViewTintColor = 41,
4091         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4092         D3DPSREGISTER_BloomColorSubtract = 43,
4093         D3DPSREGISTER_ViewToLight = 44, // float4x4
4094         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4095         D3DPSREGISTER_NormalmapScrollBlend = 52,
4096         // next at 53
4097 }
4098 D3DPSREGISTER_t;
4099
4100 /// information about each possible shader permutation
4101 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4102 /// currently selected permutation
4103 r_hlsl_permutation_t *r_hlsl_permutation;
4104 /// storage for permutations linked in the hash table
4105 memexpandablearray_t r_hlsl_permutationarray;
4106
4107 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4108 {
4109         //unsigned int hashdepth = 0;
4110         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4111         r_hlsl_permutation_t *p;
4112         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4113         {
4114                 if (p->mode == mode && p->permutation == permutation)
4115                 {
4116                         //if (hashdepth > 10)
4117                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4118                         return p;
4119                 }
4120                 //hashdepth++;
4121         }
4122         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4123         p->mode = mode;
4124         p->permutation = permutation;
4125         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4126         r_hlsl_permutationhash[mode][hashindex] = p;
4127         //if (hashdepth > 10)
4128         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4129         return p;
4130 }
4131
4132 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4133 {
4134         char *shaderstring;
4135         if (!filename || !filename[0])
4136                 return NULL;
4137         if (!strcmp(filename, "hlsl/default.hlsl"))
4138         {
4139                 if (!hlslshaderstring)
4140                 {
4141                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4142                         if (hlslshaderstring)
4143                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4144                         else
4145                                 hlslshaderstring = (char *)builtinhlslshaderstring;
4146                 }
4147                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4148                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4149                 return shaderstring;
4150         }
4151         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4152         if (shaderstring)
4153         {
4154                 if (printfromdisknotice)
4155                         Con_DPrintf("from disk %s... ", filename);
4156                 return shaderstring;
4157         }
4158         return shaderstring;
4159 }
4160
4161 #include <d3dx9.h>
4162 //#include <d3dx9shader.h>
4163 //#include <d3dx9mesh.h>
4164
4165 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4166 {
4167         DWORD *vsbin = NULL;
4168         DWORD *psbin = NULL;
4169         fs_offset_t vsbinsize;
4170         fs_offset_t psbinsize;
4171 //      IDirect3DVertexShader9 *vs = NULL;
4172 //      IDirect3DPixelShader9 *ps = NULL;
4173         ID3DXBuffer *vslog = NULL;
4174         ID3DXBuffer *vsbuffer = NULL;
4175         ID3DXConstantTable *vsconstanttable = NULL;
4176         ID3DXBuffer *pslog = NULL;
4177         ID3DXBuffer *psbuffer = NULL;
4178         ID3DXConstantTable *psconstanttable = NULL;
4179         int vsresult = 0;
4180         int psresult = 0;
4181         char temp[MAX_INPUTLINE];
4182         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4183         qboolean debugshader = gl_paranoid.integer != 0;
4184         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4185         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4186         if (!debugshader)
4187         {
4188                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4189                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4190         }
4191         if ((!vsbin && vertstring) || (!psbin && fragstring))
4192         {
4193                 const char* dllnames_d3dx9 [] =
4194                 {
4195                         "d3dx9_43.dll",
4196                         "d3dx9_42.dll",
4197                         "d3dx9_41.dll",
4198                         "d3dx9_40.dll",
4199                         "d3dx9_39.dll",
4200                         "d3dx9_38.dll",
4201                         "d3dx9_37.dll",
4202                         "d3dx9_36.dll",
4203                         "d3dx9_35.dll",
4204                         "d3dx9_34.dll",
4205                         "d3dx9_33.dll",
4206                         "d3dx9_32.dll",
4207                         "d3dx9_31.dll",
4208                         "d3dx9_30.dll",
4209                         "d3dx9_29.dll",
4210                         "d3dx9_28.dll",
4211                         "d3dx9_27.dll",
4212                         "d3dx9_26.dll",
4213                         "d3dx9_25.dll",
4214                         "d3dx9_24.dll",
4215                         NULL
4216                 };
4217                 dllhandle_t d3dx9_dll = NULL;
4218                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4219                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4220                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4221                 dllfunction_t d3dx9_dllfuncs[] =
4222                 {
4223                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4224                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4225                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4226                         {NULL, NULL}
4227                 };
4228                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4229                 {
4230                         DWORD shaderflags = 0;
4231                         if (debugshader)
4232                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4233                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4234                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4235                         if (vertstring && vertstring[0])
4236                         {
4237                                 if (debugshader)
4238                                 {
4239 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4240 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4241                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4242                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4243                                 }
4244                                 else
4245                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4246                                 if (vsbuffer)
4247                                 {
4248                                         vsbinsize = vsbuffer->GetBufferSize();
4249                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4250                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4251                                         vsbuffer->Release();
4252                                 }
4253                                 if (vslog)
4254                                 {
4255                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4256                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4257                                         vslog->Release();
4258                                 }
4259                         }
4260                         if (fragstring && fragstring[0])
4261                         {
4262                                 if (debugshader)
4263                                 {
4264 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4265 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4266                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4267                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4268                                 }
4269                                 else
4270                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4271                                 if (psbuffer)
4272                                 {
4273                                         psbinsize = psbuffer->GetBufferSize();
4274                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4275                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4276                                         psbuffer->Release();
4277                                 }
4278                                 if (pslog)
4279                                 {
4280                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4281                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4282                                         pslog->Release();
4283                                 }
4284                         }
4285                         Sys_UnloadLibrary(&d3dx9_dll);
4286                 }
4287                 else
4288                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4289         }
4290         if (vsbin && psbin)
4291         {
4292                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4293                 if (FAILED(vsresult))
4294                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4295                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4296                 if (FAILED(psresult))
4297                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4298         }
4299         // free the shader data
4300         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4301         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4302 }
4303
4304 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4305 {
4306         int i;
4307         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4308         int vertstring_length = 0;
4309         int geomstring_length = 0;
4310         int fragstring_length = 0;
4311         char *t;
4312         char *vertexstring, *geometrystring, *fragmentstring;
4313         char *vertstring, *geomstring, *fragstring;
4314         char permutationname[256];
4315         char cachename[256];
4316         int vertstrings_count = 0;
4317         int geomstrings_count = 0;
4318         int fragstrings_count = 0;
4319         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4320         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4321         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4322
4323         if (p->compiled)
4324                 return;
4325         p->compiled = true;
4326         p->vertexshader = NULL;
4327         p->pixelshader = NULL;
4328
4329         permutationname[0] = 0;
4330         cachename[0] = 0;
4331         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4332         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4333         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4334
4335         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4336         strlcat(cachename, "hlsl/", sizeof(cachename));
4337
4338         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4339         vertstrings_count = 0;
4340         geomstrings_count = 0;
4341         fragstrings_count = 0;
4342         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4343         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4344         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4345
4346         // the first pretext is which type of shader to compile as
4347         // (later these will all be bound together as a program object)
4348         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4349         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4350         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4351
4352         // the second pretext is the mode (for example a light source)
4353         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4354         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4355         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4356         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4357         strlcat(cachename, modeinfo->name, sizeof(cachename));
4358
4359         // now add all the permutation pretexts
4360         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4361         {
4362                 if (permutation & (1<<i))
4363                 {
4364                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4365                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4366                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4367                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4368                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4369                 }
4370                 else
4371                 {
4372                         // keep line numbers correct
4373                         vertstrings_list[vertstrings_count++] = "\n";
4374                         geomstrings_list[geomstrings_count++] = "\n";
4375                         fragstrings_list[fragstrings_count++] = "\n";
4376                 }
4377         }
4378
4379         // add static parms
4380         R_CompileShader_AddStaticParms(mode, permutation);
4381         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4382         vertstrings_count += shaderstaticparms_count;
4383         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4384         geomstrings_count += shaderstaticparms_count;
4385         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4386         fragstrings_count += shaderstaticparms_count;
4387
4388         // replace spaces in the cachename with _ characters
4389         for (i = 0;cachename[i];i++)
4390                 if (cachename[i] == ' ')
4391                         cachename[i] = '_';
4392
4393         // now append the shader text itself
4394         vertstrings_list[vertstrings_count++] = vertexstring;
4395         geomstrings_list[geomstrings_count++] = geometrystring;
4396         fragstrings_list[fragstrings_count++] = fragmentstring;
4397
4398         // if any sources were NULL, clear the respective list
4399         if (!vertexstring)
4400                 vertstrings_count = 0;
4401         if (!geometrystring)
4402                 geomstrings_count = 0;
4403         if (!fragmentstring)
4404                 fragstrings_count = 0;
4405
4406         vertstring_length = 0;
4407         for (i = 0;i < vertstrings_count;i++)
4408                 vertstring_length += strlen(vertstrings_list[i]);
4409         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4410         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4411                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4412
4413         geomstring_length = 0;
4414         for (i = 0;i < geomstrings_count;i++)
4415                 geomstring_length += strlen(geomstrings_list[i]);
4416         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4417         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4418                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4419
4420         fragstring_length = 0;
4421         for (i = 0;i < fragstrings_count;i++)
4422                 fragstring_length += strlen(fragstrings_list[i]);
4423         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4424         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4425                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4426
4427         // try to load the cached shader, or generate one
4428         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4429
4430         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4431                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4432         else
4433                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4434
4435         // free the strings
4436         if (vertstring)
4437                 Mem_Free(vertstring);
4438         if (geomstring)
4439                 Mem_Free(geomstring);
4440         if (fragstring)
4441                 Mem_Free(fragstring);
4442         if (vertexstring)
4443                 Mem_Free(vertexstring);
4444         if (geometrystring)
4445                 Mem_Free(geometrystring);
4446         if (fragmentstring)
4447                 Mem_Free(fragmentstring);
4448 }
4449
4450 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4451 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4452 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);}
4453 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);}
4454 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);}
4455 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);}
4456
4457 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4458 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4459 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);}
4460 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);}
4461 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);}
4462 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);}
4463
4464 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4465 {
4466         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4467         if (r_hlsl_permutation != perm)
4468         {
4469                 r_hlsl_permutation = perm;
4470                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4471                 {
4472                         if (!r_hlsl_permutation->compiled)
4473                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4474                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4475                         {
4476                                 // remove features until we find a valid permutation
4477                                 int i;
4478                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4479                                 {
4480                                         // reduce i more quickly whenever it would not remove any bits
4481                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4482                                         if (!(permutation & j))
4483                                                 continue;
4484                                         permutation -= j;
4485                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4486                                         if (!r_hlsl_permutation->compiled)
4487                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4488                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4489                                                 break;
4490                                 }
4491                                 if (i >= SHADERPERMUTATION_COUNT)
4492                                 {
4493                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4494                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4495                                         return; // no bit left to clear, entire mode is broken
4496                                 }
4497                         }
4498                 }
4499                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4500                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4501         }
4502         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4503         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4504         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4505 }
4506 #endif
4507
4508 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4509 {
4510         DPSOFTRAST_SetShader(mode, permutation);
4511         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4512         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4513         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4514 }
4515
4516 void R_GLSL_Restart_f(void)
4517 {
4518         unsigned int i, limit;
4519         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4520                 Mem_Free(glslshaderstring);
4521         glslshaderstring = NULL;
4522         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4523                 Mem_Free(hlslshaderstring);
4524         hlslshaderstring = NULL;
4525         switch(vid.renderpath)
4526         {
4527         case RENDERPATH_D3D9:
4528 #ifdef SUPPORTD3D
4529                 {
4530                         r_hlsl_permutation_t *p;
4531                         r_hlsl_permutation = NULL;
4532                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4533                         for (i = 0;i < limit;i++)
4534                         {
4535                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4536                                 {
4537                                         if (p->vertexshader)
4538                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4539                                         if (p->pixelshader)
4540                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4541                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4542                                 }
4543                         }
4544                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4545                 }
4546 #endif
4547                 break;
4548         case RENDERPATH_D3D10:
4549                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4550                 break;
4551         case RENDERPATH_D3D11:
4552                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4553                 break;
4554         case RENDERPATH_GL20:
4555         case RENDERPATH_GLES2:
4556                 {
4557                         r_glsl_permutation_t *p;
4558                         r_glsl_permutation = NULL;
4559                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4560                         for (i = 0;i < limit;i++)
4561                         {
4562                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4563                                 {
4564                                         GL_Backend_FreeProgram(p->program);
4565                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4566                                 }
4567                         }
4568                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4569                 }
4570                 break;
4571         case RENDERPATH_GL13:
4572         case RENDERPATH_GL11:
4573                 break;
4574         case RENDERPATH_SOFT:
4575                 break;
4576         }
4577 }
4578
4579 void R_GLSL_DumpShader_f(void)
4580 {
4581         int i;
4582         qfile_t *file;
4583
4584         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4585         if (file)
4586         {
4587                 FS_Print(file, "/* The engine may define the following macros:\n");
4588                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4589                 for (i = 0;i < SHADERMODE_COUNT;i++)
4590                         FS_Print(file, glslshadermodeinfo[i].pretext);
4591                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4592                         FS_Print(file, shaderpermutationinfo[i].pretext);
4593                 FS_Print(file, "*/\n");
4594                 FS_Print(file, builtinshaderstring);
4595                 FS_Close(file);
4596                 Con_Printf("glsl/default.glsl written\n");
4597         }
4598         else
4599                 Con_Printf("failed to write to glsl/default.glsl\n");
4600
4601         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4602         if (file)
4603         {
4604                 FS_Print(file, "/* The engine may define the following macros:\n");
4605                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4606                 for (i = 0;i < SHADERMODE_COUNT;i++)
4607                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4608                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4609                         FS_Print(file, shaderpermutationinfo[i].pretext);
4610                 FS_Print(file, "*/\n");
4611                 FS_Print(file, builtinhlslshaderstring);
4612                 FS_Close(file);
4613                 Con_Printf("hlsl/default.hlsl written\n");
4614         }
4615         else
4616                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4617 }
4618
4619 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4620 {
4621         if (!second)
4622                 texturemode = GL_MODULATE;
4623         switch (vid.renderpath)
4624         {
4625         case RENDERPATH_D3D9:
4626 #ifdef SUPPORTD3D
4627                 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))));
4628                 R_Mesh_TexBind(GL20TU_FIRST , first );
4629                 R_Mesh_TexBind(GL20TU_SECOND, second);
4630 #endif
4631                 break;
4632         case RENDERPATH_D3D10:
4633                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4634                 break;
4635         case RENDERPATH_D3D11:
4636                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4637                 break;
4638         case RENDERPATH_GL20:
4639         case RENDERPATH_GLES2:
4640                 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))));
4641                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4642                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4643                 break;
4644         case RENDERPATH_GL13:
4645                 R_Mesh_TexBind(0, first );
4646                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4647                 R_Mesh_TexBind(1, second);
4648                 if (second)
4649                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4650                 break;
4651         case RENDERPATH_GL11:
4652                 R_Mesh_TexBind(0, first );
4653                 break;
4654         case RENDERPATH_SOFT:
4655                 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))));
4656                 R_Mesh_TexBind(GL20TU_FIRST , first );
4657                 R_Mesh_TexBind(GL20TU_SECOND, second);
4658                 break;
4659         }
4660 }
4661
4662 void R_SetupShader_DepthOrShadow(void)
4663 {
4664         switch (vid.renderpath)
4665         {
4666         case RENDERPATH_D3D9:
4667 #ifdef SUPPORTD3D
4668                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4669 #endif
4670                 break;
4671         case RENDERPATH_D3D10:
4672                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4673                 break;
4674         case RENDERPATH_D3D11:
4675                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4676                 break;
4677         case RENDERPATH_GL20:
4678         case RENDERPATH_GLES2:
4679                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4680                 break;
4681         case RENDERPATH_GL13:
4682                 R_Mesh_TexBind(0, 0);
4683                 R_Mesh_TexBind(1, 0);
4684                 break;
4685         case RENDERPATH_GL11:
4686                 R_Mesh_TexBind(0, 0);
4687                 break;
4688         case RENDERPATH_SOFT:
4689                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4690                 break;
4691         }
4692 }
4693
4694 void R_SetupShader_ShowDepth(void)
4695 {
4696         switch (vid.renderpath)
4697         {
4698         case RENDERPATH_D3D9:
4699 #ifdef SUPPORTHLSL
4700                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4701 #endif
4702                 break;
4703         case RENDERPATH_D3D10:
4704                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4705                 break;
4706         case RENDERPATH_D3D11:
4707                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4708                 break;
4709         case RENDERPATH_GL20:
4710         case RENDERPATH_GLES2:
4711                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4712                 break;
4713         case RENDERPATH_GL13:
4714                 break;
4715         case RENDERPATH_GL11:
4716                 break;
4717         case RENDERPATH_SOFT:
4718                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4719                 break;
4720         }
4721 }
4722
4723 extern qboolean r_shadow_usingdeferredprepass;
4724 extern cvar_t r_shadow_deferred_8bitrange;
4725 extern rtexture_t *r_shadow_attenuationgradienttexture;
4726 extern rtexture_t *r_shadow_attenuation2dtexture;
4727 extern rtexture_t *r_shadow_attenuation3dtexture;
4728 extern qboolean r_shadow_usingshadowmap2d;
4729 extern qboolean r_shadow_usingshadowmaportho;
4730 extern float r_shadow_shadowmap_texturescale[2];
4731 extern float r_shadow_shadowmap_parameters[4];
4732 extern qboolean r_shadow_shadowmapvsdct;
4733 extern qboolean r_shadow_shadowmapsampler;
4734 extern int r_shadow_shadowmappcf;
4735 extern rtexture_t *r_shadow_shadowmap2dtexture;
4736 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4737 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4738 extern matrix4x4_t r_shadow_shadowmapmatrix;
4739 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4740 extern int r_shadow_prepass_width;
4741 extern int r_shadow_prepass_height;
4742 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4743 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4744 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4745 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4746 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4747 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4748 {
4749         // a blendfunc allows colormod if:
4750         // a) it can never keep the destination pixel invariant, or
4751         // b) it can keep the destination pixel invariant, and still can do so if colormodded
4752         // this is to prevent unintended side effects from colormod
4753
4754         // in formulas:
4755         // IF there is a (s, sa) for which for all (d, da),
4756         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4757         // THEN, for this (s, sa) and all (colormod, d, da):
4758         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4759         // OBVIOUSLY, this means that
4760         //   s*colormod * src(s*colormod, d, sa, da) = 0
4761         //   dst(s*colormod, d, sa, da)              = 1
4762
4763         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4764
4765         // main condition to leave dst color invariant:
4766         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4767         //   src == GL_ZERO:
4768         //     s * 0 + d * dst(s, d, sa, da) == d
4769         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4770         //       => colormod is a problem for GL_SRC_COLOR only
4771         //   src == GL_ONE:
4772         //     s + d * dst(s, d, sa, da) == d
4773         //       => s == 0
4774         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4775         //       => colormod is never problematic for these
4776         //   src == GL_SRC_COLOR:
4777         //     s*s + d * dst(s, d, sa, da) == d
4778         //       => s == 0
4779         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4780         //       => colormod is never problematic for these
4781         //   src == GL_ONE_MINUS_SRC_COLOR:
4782         //     s*(1-s) + d * dst(s, d, sa, da) == d
4783         //       => s == 0 or s == 1
4784         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4785         //       => colormod is a problem for GL_SRC_COLOR only
4786         //   src == GL_DST_COLOR
4787         //     s*d + d * dst(s, d, sa, da) == d
4788         //       => s == 1
4789         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4790         //       => colormod is always a problem
4791         //     or
4792         //       => s == 0
4793         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4794         //       => colormod is never problematic for these
4795         //       => BUT, we do not know s! We must assume it is problematic
4796         //       then... except in GL_ONE case, where we know all invariant
4797         //       cases are fine
4798         //   src == GL_ONE_MINUS_DST_COLOR
4799         //     s*(1-d) + d * dst(s, d, sa, da) == d
4800         //       => s == 0 (1-d is impossible to handle for our desired result)
4801         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4802         //       => colormod is never problematic for these
4803         //   src == GL_SRC_ALPHA
4804         //     s*sa + d * dst(s, d, sa, da) == d
4805         //       => s == 0, or sa == 0
4806         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4807         //       => colormod breaks in the case GL_SRC_COLOR only
4808         //   src == GL_ONE_MINUS_SRC_ALPHA
4809         //     s*(1-sa) + d * dst(s, d, sa, da) == d
4810         //       => s == 0, or sa == 1
4811         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4812         //       => colormod breaks in the case GL_SRC_COLOR only
4813         //   src == GL_DST_ALPHA
4814         //     s*da + d * dst(s, d, sa, da) == d
4815         //       => s == 0
4816         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4817         //       => colormod is never problematic for these
4818
4819         switch(src)
4820         {
4821                 case GL_ZERO:
4822                 case GL_ONE_MINUS_SRC_COLOR:
4823                 case GL_SRC_ALPHA:
4824                 case GL_ONE_MINUS_SRC_ALPHA:
4825                         if(dst == GL_SRC_COLOR)
4826                                 return false;
4827                         return true;
4828                 case GL_ONE:
4829                 case GL_SRC_COLOR:
4830                 case GL_ONE_MINUS_DST_COLOR:
4831                 case GL_DST_ALPHA:
4832                 case GL_ONE_MINUS_DST_ALPHA:
4833                         return true;
4834                 case GL_DST_COLOR:
4835                         if(dst == GL_ONE)
4836                                 return true;
4837                         return false;
4838                 default:
4839                         return false;
4840         }
4841 }
4842 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)
4843 {
4844         // select a permutation of the lighting shader appropriate to this
4845         // combination of texture, entity, light source, and fogging, only use the
4846         // minimum features necessary to avoid wasting rendering time in the
4847         // fragment shader on features that are not being used
4848         unsigned int permutation = 0;
4849         unsigned int mode = 0;
4850         qboolean allow_colormod;
4851         static float dummy_colormod[3] = {1, 1, 1};
4852         float *colormod = rsurface.colormod;
4853         float m16f[16];
4854         matrix4x4_t tempmatrix;
4855         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4856         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4857                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4858         if (rsurfacepass == RSURFPASS_BACKGROUND)
4859         {
4860                 // distorted background
4861                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4862                 {
4863                         mode = SHADERMODE_WATER;
4864                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4865                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4866                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4867                         {
4868                                 // this is the right thing to do for wateralpha
4869                                 GL_BlendFunc(GL_ONE, GL_ZERO);
4870                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4871                         }
4872                         else
4873                         {
4874                                 // this is the right thing to do for entity alpha
4875                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4876                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4877                         }
4878                 }
4879                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4880                 {
4881                         mode = SHADERMODE_REFRACTION;
4882                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4883                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4884                 }
4885                 else
4886                 {
4887                         mode = SHADERMODE_GENERIC;
4888                         permutation |= SHADERPERMUTATION_DIFFUSE;
4889                         GL_BlendFunc(GL_ONE, GL_ZERO);
4890                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4891                 }
4892         }
4893         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4894         {
4895                 if (r_glsl_offsetmapping.integer)
4896                 {
4897                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4898                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4899                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4900                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4901                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4902                         {
4903                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4904                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4905                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4906                         }
4907                 }
4908                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4909                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4910                 // normalmap (deferred prepass), may use alpha test on diffuse
4911                 mode = SHADERMODE_DEFERREDGEOMETRY;
4912                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4913                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4914                 GL_BlendFunc(GL_ONE, GL_ZERO);
4915                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4916         }
4917         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4918         {
4919                 if (r_glsl_offsetmapping.integer)
4920                 {
4921                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4922                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4923                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4924                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4925                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4926                         {
4927                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4928                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4929                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4930                         }
4931                 }
4932                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4933                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4934                 // light source
4935                 mode = SHADERMODE_LIGHTSOURCE;
4936                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4937                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4938                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4939                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4940                 if (diffusescale > 0)
4941                         permutation |= SHADERPERMUTATION_DIFFUSE;
4942                 if (specularscale > 0)
4943                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4944                 if (r_refdef.fogenabled)
4945                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4946                 if (rsurface.texture->colormapping)
4947                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4948                 if (r_shadow_usingshadowmap2d)
4949                 {
4950                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4951                         if(r_shadow_shadowmapvsdct)
4952                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4953
4954                         if (r_shadow_shadowmapsampler)
4955                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4956                         if (r_shadow_shadowmappcf > 1)
4957                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4958                         else if (r_shadow_shadowmappcf)
4959                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4960                 }
4961                 if (rsurface.texture->reflectmasktexture)
4962                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4963                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4964                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4965         }
4966         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4967         {
4968                 if (r_glsl_offsetmapping.integer)
4969                 {
4970                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4971                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4972                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4973                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4974                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4975                         {
4976                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4977                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4978                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4979                         }
4980                 }
4981                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4982                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4983                 // unshaded geometry (fullbright or ambient model lighting)
4984                 mode = SHADERMODE_FLATCOLOR;
4985                 ambientscale = diffusescale = specularscale = 0;
4986                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4987                         permutation |= SHADERPERMUTATION_GLOW;
4988                 if (r_refdef.fogenabled)
4989                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4990                 if (rsurface.texture->colormapping)
4991                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4992                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4993                 {
4994                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4995                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4996
4997                         if (r_shadow_shadowmapsampler)
4998                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4999                         if (r_shadow_shadowmappcf > 1)
5000                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5001                         else if (r_shadow_shadowmappcf)
5002                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5003                 }
5004                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5005                         permutation |= SHADERPERMUTATION_REFLECTION;
5006                 if (rsurface.texture->reflectmasktexture)
5007                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5008                 if (r_shadow_bouncegridtexture)
5009                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5010                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5011                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5012         }
5013         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5014         {
5015                 if (r_glsl_offsetmapping.integer)
5016                 {
5017                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5018                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5019                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5020                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5021                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5022                         {
5023                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5024                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5025                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5026                         }
5027                 }
5028                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5029                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5030                 // directional model lighting
5031                 mode = SHADERMODE_LIGHTDIRECTION;
5032                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5033                         permutation |= SHADERPERMUTATION_GLOW;
5034                 permutation |= SHADERPERMUTATION_DIFFUSE;
5035                 if (specularscale > 0)
5036                         permutation |= SHADERPERMUTATION_SPECULAR;
5037                 if (r_refdef.fogenabled)
5038                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5039                 if (rsurface.texture->colormapping)
5040                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5041                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5042                 {
5043                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5044                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5045
5046                         if (r_shadow_shadowmapsampler)
5047                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5048                         if (r_shadow_shadowmappcf > 1)
5049                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5050                         else if (r_shadow_shadowmappcf)
5051                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5052                 }
5053                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5054                         permutation |= SHADERPERMUTATION_REFLECTION;
5055                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5056                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5057                 if (rsurface.texture->reflectmasktexture)
5058                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5059                 if (r_shadow_bouncegridtexture)
5060                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5061                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5062                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5063         }
5064         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5065         {
5066                 if (r_glsl_offsetmapping.integer)
5067                 {
5068                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5069                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5070                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5071                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5072                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5073                         {
5074                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5075                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5076                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5077                         }
5078                 }
5079                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5080                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5081                 // ambient model lighting
5082                 mode = SHADERMODE_LIGHTDIRECTION;
5083                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5084                         permutation |= SHADERPERMUTATION_GLOW;
5085                 if (r_refdef.fogenabled)
5086                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5087                 if (rsurface.texture->colormapping)
5088                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5089                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5090                 {
5091                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5092                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5093
5094                         if (r_shadow_shadowmapsampler)
5095                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5096                         if (r_shadow_shadowmappcf > 1)
5097                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5098                         else if (r_shadow_shadowmappcf)
5099                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5100                 }
5101                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5102                         permutation |= SHADERPERMUTATION_REFLECTION;
5103                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5104                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5105                 if (rsurface.texture->reflectmasktexture)
5106                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5107                 if (r_shadow_bouncegridtexture)
5108                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5109                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5110                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5111         }
5112         else
5113         {
5114                 if (r_glsl_offsetmapping.integer)
5115                 {
5116                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5117                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5118                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5119                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5120                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5121                         {
5122                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5123                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5124                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5125                         }
5126                 }
5127                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5128                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5129                 // lightmapped wall
5130                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5131                         permutation |= SHADERPERMUTATION_GLOW;
5132                 if (r_refdef.fogenabled)
5133                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5134                 if (rsurface.texture->colormapping)
5135                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5136                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5137                 {
5138                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5139                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5140
5141                         if (r_shadow_shadowmapsampler)
5142                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5143                         if (r_shadow_shadowmappcf > 1)
5144                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5145                         else if (r_shadow_shadowmappcf)
5146                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5147                 }
5148                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5149                         permutation |= SHADERPERMUTATION_REFLECTION;
5150                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5151                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5152                 if (rsurface.texture->reflectmasktexture)
5153                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5154                 if (FAKELIGHT_ENABLED)
5155                 {
5156                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5157                         mode = SHADERMODE_FAKELIGHT;
5158                         permutation |= SHADERPERMUTATION_DIFFUSE;
5159                         if (specularscale > 0)
5160                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5161                 }
5162                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5163                 {
5164                         // deluxemapping (light direction texture)
5165                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5166                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5167                         else
5168                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5169                         permutation |= SHADERPERMUTATION_DIFFUSE;
5170                         if (specularscale > 0)
5171                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5172                 }
5173                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5174                 {
5175                         // fake deluxemapping (uniform light direction in tangentspace)
5176                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5177                         permutation |= SHADERPERMUTATION_DIFFUSE;
5178                         if (specularscale > 0)
5179                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5180                 }
5181                 else if (rsurface.uselightmaptexture)
5182                 {
5183                         // ordinary lightmapping (q1bsp, q3bsp)
5184                         mode = SHADERMODE_LIGHTMAP;
5185                 }
5186                 else
5187                 {
5188                         // ordinary vertex coloring (q3bsp)
5189                         mode = SHADERMODE_VERTEXCOLOR;
5190                 }
5191                 if (r_shadow_bouncegridtexture)
5192                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5193                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5194                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5195         }
5196         if(!allow_colormod)
5197                 colormod = dummy_colormod;
5198         switch(vid.renderpath)
5199         {
5200         case RENDERPATH_D3D9:
5201 #ifdef SUPPORTD3D
5202                 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);
5203                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5204                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5205                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5206                 if (mode == SHADERMODE_LIGHTSOURCE)
5207                 {
5208                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5209                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5210                 }
5211                 else
5212                 {
5213                         if (mode == SHADERMODE_LIGHTDIRECTION)
5214                         {
5215                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5216                         }
5217                 }
5218                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5219                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5220                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5221                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5222                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5223
5224                 if (mode == SHADERMODE_LIGHTSOURCE)
5225                 {
5226                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5227                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5228                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5229                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5230                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5231
5232                         // additive passes are only darkened by fog, not tinted
5233                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5234                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5235                 }
5236                 else
5237                 {
5238                         if (mode == SHADERMODE_FLATCOLOR)
5239                         {
5240                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5241                         }
5242                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5243                         {
5244                                 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]);
5245                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5246                                 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);
5247                                 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);
5248                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5249                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5250                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5251                         }
5252                         else
5253                         {
5254                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5255                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5256                                 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);
5257                                 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);
5258                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5259                         }
5260                         // additive passes are only darkened by fog, not tinted
5261                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5262                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5263                         else
5264                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5265                         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);
5266                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5267                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5268                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5269                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5270                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5271                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5272                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5273                         if (mode == SHADERMODE_WATER)
5274                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5275                 }
5276                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5277                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5278                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5279                 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));
5280                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5281                 if (rsurface.texture->pantstexture)
5282                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5283                 else
5284                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5285                 if (rsurface.texture->shirttexture)
5286                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5287                 else
5288                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5289                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5290                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5291                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5292                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5293                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5294                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5295                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5296
5297                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5298                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5299                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5300                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5301                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5302                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5303                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5304                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5305                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5306                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5307                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5308                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5309                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5310                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5311                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5312                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5313                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5314                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5315                 {
5316                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5317                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5318                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5319                 }
5320                 else
5321                 {
5322                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5323                 }
5324 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5325 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5326                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5327                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5328                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5329                 {
5330                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5331                         if (rsurface.rtlight)
5332                         {
5333                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5334                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5335                         }
5336                 }
5337 #endif
5338                 break;
5339         case RENDERPATH_D3D10:
5340                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5341                 break;
5342         case RENDERPATH_D3D11:
5343                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5344                 break;
5345         case RENDERPATH_GL20:
5346         case RENDERPATH_GLES2:
5347                 if (!vid.useinterleavedarrays)
5348                 {
5349                         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);
5350                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5351                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5352                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5353                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5354                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5355                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5356                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5357                 }
5358                 else
5359                 {
5360                         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);
5361                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5362                 }
5363                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5364                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5365                 if (mode == SHADERMODE_LIGHTSOURCE)
5366                 {
5367                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5368                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5369                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5370                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5371                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5372                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5373         
5374                         // additive passes are only darkened by fog, not tinted
5375                         if (r_glsl_permutation->loc_FogColor >= 0)
5376                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5377                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5378                 }
5379                 else
5380                 {
5381                         if (mode == SHADERMODE_FLATCOLOR)
5382                         {
5383                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5384                         }
5385                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5386                         {
5387                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
5388                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5389                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5390                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5391                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5392                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
5393                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5394                         }
5395                         else
5396                         {
5397                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5398                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5399                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5400                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5401                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5402                         }
5403                         // additive passes are only darkened by fog, not tinted
5404                         if (r_glsl_permutation->loc_FogColor >= 0)
5405                         {
5406                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5407                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5408                                 else
5409                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5410                         }
5411                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5412                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5413                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5414                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5415                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5416                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5417                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5418                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5419                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5420                 }
5421                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5422                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5423                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5424                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5425                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5426
5427                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5428                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5429                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5430                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5431                 {
5432                         if (rsurface.texture->pantstexture)
5433                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5434                         else
5435                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5436                 }
5437                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5438                 {
5439                         if (rsurface.texture->shirttexture)
5440                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5441                         else
5442                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5443                 }
5444                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5445                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5446                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5447                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5448                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5449                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5450                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5451                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
5452                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
5453
5454                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
5455                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
5456                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
5457                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
5458                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
5459                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
5460                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
5461                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
5462                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
5463                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
5464                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
5465                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
5466                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
5467                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
5468                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5469                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
5470                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
5471                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5472                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5473                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
5474                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5475                 {
5476                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5477                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5478                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5479                 }
5480                 else
5481                 {
5482                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5483                 }
5484                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
5485                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
5486                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
5487                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
5488                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5489                 {
5490                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
5491                         if (rsurface.rtlight)
5492                         {
5493                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
5494                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
5495                         }
5496                 }
5497                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
5498                 CHECKGLERROR
5499                 break;
5500         case RENDERPATH_GL13:
5501         case RENDERPATH_GL11:
5502                 break;
5503         case RENDERPATH_SOFT:
5504                 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);
5505                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5506                 R_SetupShader_SetPermutationSoft(mode, permutation);
5507                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5508                 if (mode == SHADERMODE_LIGHTSOURCE)
5509                 {
5510                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5511                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5512                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5513                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5514                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5515                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5516         
5517                         // additive passes are only darkened by fog, not tinted
5518                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5519                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5520                 }
5521                 else
5522                 {
5523                         if (mode == SHADERMODE_FLATCOLOR)
5524                         {
5525                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5526                         }
5527                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5528                         {
5529                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
5530                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5531                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5532                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
5533                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5534                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
5535                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5536                         }
5537                         else
5538                         {
5539                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5540                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5541                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
5542                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
5543                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5544                         }
5545                         // additive passes are only darkened by fog, not tinted
5546                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5547                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5548                         else
5549                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5550                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
5551                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5552                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5553                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5554                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5555                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5556                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5557                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5558                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5559                 }
5560                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5561                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5562                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5563                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5564                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5565
5566                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5567                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
5568                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5569                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5570                 {
5571                         if (rsurface.texture->pantstexture)
5572                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5573                         else
5574                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5575                 }
5576                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5577                 {
5578                         if (rsurface.texture->shirttexture)
5579                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5580                         else
5581                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5582                 }
5583                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5584                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5585                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5586                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5587                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5588                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5589                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5590
5591                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5592                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5593                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5594                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5595                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5596                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5597                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5598                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5599                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5600                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5601                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5602                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5603                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5604                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5605                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5606                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5607                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5608                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5609                 {
5610                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5611                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5612                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5613                 }
5614                 else
5615                 {
5616                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5617                 }
5618 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5619 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5620                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5621                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5622                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5623                 {
5624                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5625                         if (rsurface.rtlight)
5626                         {
5627                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5628                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5629                         }
5630                 }
5631                 break;
5632         }
5633 }
5634
5635 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5636 {
5637         // select a permutation of the lighting shader appropriate to this
5638         // combination of texture, entity, light source, and fogging, only use the
5639         // minimum features necessary to avoid wasting rendering time in the
5640         // fragment shader on features that are not being used
5641         unsigned int permutation = 0;
5642         unsigned int mode = 0;
5643         const float *lightcolorbase = rtlight->currentcolor;
5644         float ambientscale = rtlight->ambientscale;
5645         float diffusescale = rtlight->diffusescale;
5646         float specularscale = rtlight->specularscale;
5647         // this is the location of the light in view space
5648         vec3_t viewlightorigin;
5649         // this transforms from view space (camera) to light space (cubemap)
5650         matrix4x4_t viewtolight;
5651         matrix4x4_t lighttoview;
5652         float viewtolight16f[16];
5653         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5654         // light source
5655         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5656         if (rtlight->currentcubemap != r_texture_whitecube)
5657                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5658         if (diffusescale > 0)
5659                 permutation |= SHADERPERMUTATION_DIFFUSE;
5660         if (specularscale > 0)
5661                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5662         if (r_shadow_usingshadowmap2d)
5663         {
5664                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5665                 if (r_shadow_shadowmapvsdct)
5666                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5667
5668                 if (r_shadow_shadowmapsampler)
5669                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5670                 if (r_shadow_shadowmappcf > 1)
5671                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5672                 else if (r_shadow_shadowmappcf)
5673                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5674         }
5675         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5676         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5677         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5678         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5679         switch(vid.renderpath)
5680         {
5681         case RENDERPATH_D3D9:
5682 #ifdef SUPPORTD3D
5683                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5684                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5685                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5686                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5687                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5688                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5689                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5690                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5691                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5692                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5693                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5694
5695                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5696                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
5697                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5698                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5699                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
5700                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5701 #endif
5702                 break;
5703         case RENDERPATH_D3D10:
5704                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5705                 break;
5706         case RENDERPATH_D3D11:
5707                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5708                 break;
5709         case RENDERPATH_GL20:
5710         case RENDERPATH_GLES2:
5711                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5712                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5713                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5714                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5715                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5716                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5717                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5718                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5719                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5720                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5721                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
5722
5723                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
5724                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
5725                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
5726                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
5727                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
5728                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
5729                 break;
5730         case RENDERPATH_GL13:
5731         case RENDERPATH_GL11:
5732                 break;
5733         case RENDERPATH_SOFT:
5734                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5735                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5736                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
5737                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5738                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5739                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5740                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5741                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5742                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5743                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5744                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5745
5746                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5747                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5748                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5749                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5750                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5751                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5752                 break;
5753         }
5754 }
5755
5756 #define SKINFRAME_HASH 1024
5757
5758 typedef struct
5759 {
5760         int loadsequence; // incremented each level change
5761         memexpandablearray_t array;
5762         skinframe_t *hash[SKINFRAME_HASH];
5763 }
5764 r_skinframe_t;
5765 r_skinframe_t r_skinframe;
5766
5767 void R_SkinFrame_PrepareForPurge(void)
5768 {
5769         r_skinframe.loadsequence++;
5770         // wrap it without hitting zero
5771         if (r_skinframe.loadsequence >= 200)
5772                 r_skinframe.loadsequence = 1;
5773 }
5774
5775 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5776 {
5777         if (!skinframe)
5778                 return;
5779         // mark the skinframe as used for the purging code
5780         skinframe->loadsequence = r_skinframe.loadsequence;
5781 }
5782
5783 void R_SkinFrame_Purge(void)
5784 {
5785         int i;
5786         skinframe_t *s;
5787         for (i = 0;i < SKINFRAME_HASH;i++)
5788         {
5789                 for (s = r_skinframe.hash[i];s;s = s->next)
5790                 {
5791                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5792                         {
5793                                 if (s->merged == s->base)
5794                                         s->merged = NULL;
5795                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5796                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5797                                 R_PurgeTexture(s->merged);s->merged = NULL;
5798                                 R_PurgeTexture(s->base  );s->base   = NULL;
5799                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5800                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5801                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5802                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5803                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5804                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5805                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5806                                 s->loadsequence = 0;
5807                         }
5808                 }
5809         }
5810 }
5811
5812 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5813         skinframe_t *item;
5814         char basename[MAX_QPATH];
5815
5816         Image_StripImageExtension(name, basename, sizeof(basename));
5817
5818         if( last == NULL ) {
5819                 int hashindex;
5820                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5821                 item = r_skinframe.hash[hashindex];
5822         } else {
5823                 item = last->next;
5824         }
5825
5826         // linearly search through the hash bucket
5827         for( ; item ; item = item->next ) {
5828                 if( !strcmp( item->basename, basename ) ) {
5829                         return item;
5830                 }
5831         }
5832         return NULL;
5833 }
5834
5835 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5836 {
5837         skinframe_t *item;
5838         int hashindex;
5839         char basename[MAX_QPATH];
5840
5841         Image_StripImageExtension(name, basename, sizeof(basename));
5842
5843         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5844         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5845                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5846                         break;
5847
5848         if (!item) {
5849                 rtexture_t *dyntexture;
5850                 // check whether its a dynamic texture
5851                 dyntexture = CL_GetDynTexture( basename );
5852                 if (!add && !dyntexture)
5853                         return NULL;
5854                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5855                 memset(item, 0, sizeof(*item));
5856                 strlcpy(item->basename, basename, sizeof(item->basename));
5857                 item->base = dyntexture; // either NULL or dyntexture handle
5858                 item->textureflags = textureflags;
5859                 item->comparewidth = comparewidth;
5860                 item->compareheight = compareheight;
5861                 item->comparecrc = comparecrc;
5862                 item->next = r_skinframe.hash[hashindex];
5863                 r_skinframe.hash[hashindex] = item;
5864         }
5865         else if( item->base == NULL )
5866         {
5867                 rtexture_t *dyntexture;
5868                 // check whether its a dynamic texture
5869                 // 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]
5870                 dyntexture = CL_GetDynTexture( basename );
5871                 item->base = dyntexture; // either NULL or dyntexture handle
5872         }
5873
5874         R_SkinFrame_MarkUsed(item);
5875         return item;
5876 }
5877
5878 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5879         { \
5880                 unsigned long long avgcolor[5], wsum; \
5881                 int pix, comp, w; \
5882                 avgcolor[0] = 0; \
5883                 avgcolor[1] = 0; \
5884                 avgcolor[2] = 0; \
5885                 avgcolor[3] = 0; \
5886                 avgcolor[4] = 0; \
5887                 wsum = 0; \
5888                 for(pix = 0; pix < cnt; ++pix) \
5889                 { \
5890                         w = 0; \
5891                         for(comp = 0; comp < 3; ++comp) \
5892                                 w += getpixel; \
5893                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5894                         { \
5895                                 ++wsum; \
5896                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5897                                 w = getpixel; \
5898                                 for(comp = 0; comp < 3; ++comp) \
5899                                         avgcolor[comp] += getpixel * w; \
5900                                 avgcolor[3] += w; \
5901                         } \
5902                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5903                         avgcolor[4] += getpixel; \
5904                 } \
5905                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5906                         avgcolor[3] = 1; \
5907                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5908                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5909                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5910                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5911         }
5912
5913 extern cvar_t gl_picmip;
5914 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5915 {
5916         int j;
5917         unsigned char *pixels;
5918         unsigned char *bumppixels;
5919         unsigned char *basepixels = NULL;
5920         int basepixels_width = 0;
5921         int basepixels_height = 0;
5922         skinframe_t *skinframe;
5923         rtexture_t *ddsbase = NULL;
5924         qboolean ddshasalpha = false;
5925         float ddsavgcolor[4];
5926         char basename[MAX_QPATH];
5927         int miplevel = R_PicmipForFlags(textureflags);
5928         int savemiplevel = miplevel;
5929         int mymiplevel;
5930
5931         if (cls.state == ca_dedicated)
5932                 return NULL;
5933
5934         // return an existing skinframe if already loaded
5935         // if loading of the first image fails, don't make a new skinframe as it
5936         // would cause all future lookups of this to be missing
5937         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5938         if (skinframe && skinframe->base)
5939                 return skinframe;
5940
5941         Image_StripImageExtension(name, basename, sizeof(basename));
5942
5943         // check for DDS texture file first
5944         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5945         {
5946                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
5947                 if (basepixels == NULL)
5948                         return NULL;
5949         }
5950
5951         // FIXME handle miplevel
5952
5953         if (developer_loading.integer)
5954                 Con_Printf("loading skin \"%s\"\n", name);
5955
5956         // we've got some pixels to store, so really allocate this new texture now
5957         if (!skinframe)
5958                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5959         skinframe->stain = NULL;
5960         skinframe->merged = NULL;
5961         skinframe->base = NULL;
5962         skinframe->pants = NULL;
5963         skinframe->shirt = NULL;
5964         skinframe->nmap = NULL;
5965         skinframe->gloss = NULL;
5966         skinframe->glow = NULL;
5967         skinframe->fog = NULL;
5968         skinframe->reflect = NULL;
5969         skinframe->hasalpha = false;
5970
5971         if (ddsbase)
5972         {
5973                 skinframe->base = ddsbase;
5974                 skinframe->hasalpha = ddshasalpha;
5975                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5976                 if (r_loadfog && skinframe->hasalpha)
5977                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5978                 //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]);
5979         }
5980         else
5981         {
5982                 basepixels_width = image_width;
5983                 basepixels_height = image_height;
5984                 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);
5985                 if (textureflags & TEXF_ALPHA)
5986                 {
5987                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5988                         {
5989                                 if (basepixels[j] < 255)
5990                                 {
5991                                         skinframe->hasalpha = true;
5992                                         break;
5993                                 }
5994                         }
5995                         if (r_loadfog && skinframe->hasalpha)
5996                         {
5997                                 // has transparent pixels
5998                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5999                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6000                                 {
6001                                         pixels[j+0] = 255;
6002                                         pixels[j+1] = 255;
6003                                         pixels[j+2] = 255;
6004                                         pixels[j+3] = basepixels[j+3];
6005                                 }
6006                                 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);
6007                                 Mem_Free(pixels);
6008                         }
6009                 }
6010                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6011                 //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]);
6012                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6013                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6014                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6015                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6016         }
6017
6018         if (r_loaddds)
6019         {
6020                 mymiplevel = savemiplevel;
6021                 if (r_loadnormalmap)
6022                         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);
6023                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6024                 if (r_loadgloss)
6025                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6026                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6027                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6028                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6029         }
6030
6031         // _norm is the name used by tenebrae and has been adopted as standard
6032         if (r_loadnormalmap && skinframe->nmap == NULL)
6033         {
6034                 mymiplevel = savemiplevel;
6035                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6036                 {
6037                         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);
6038                         Mem_Free(pixels);
6039                         pixels = NULL;
6040                 }
6041                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6042                 {
6043                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6044                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6045                         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);
6046                         Mem_Free(pixels);
6047                         Mem_Free(bumppixels);
6048                 }
6049                 else if (r_shadow_bumpscale_basetexture.value > 0)
6050                 {
6051                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6052                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6053                         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);
6054                         Mem_Free(pixels);
6055                 }
6056                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6057                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6058         }
6059
6060         // _luma is supported only for tenebrae compatibility
6061         // _glow is the preferred name
6062         mymiplevel = savemiplevel;
6063         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))))
6064         {
6065                 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);
6066                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6067                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6068                 Mem_Free(pixels);pixels = NULL;
6069         }
6070
6071         mymiplevel = savemiplevel;
6072         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6073         {
6074                 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);
6075                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6076                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6077                 Mem_Free(pixels);
6078                 pixels = NULL;
6079         }
6080
6081         mymiplevel = savemiplevel;
6082         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6083         {
6084                 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);
6085                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6086                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6087                 Mem_Free(pixels);
6088                 pixels = NULL;
6089         }
6090
6091         mymiplevel = savemiplevel;
6092         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6093         {
6094                 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);
6095                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6096                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6097                 Mem_Free(pixels);
6098                 pixels = NULL;
6099         }
6100
6101         mymiplevel = savemiplevel;
6102         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6103         {
6104                 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);
6105                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6106                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6107                 Mem_Free(pixels);
6108                 pixels = NULL;
6109         }
6110
6111         if (basepixels)
6112                 Mem_Free(basepixels);
6113
6114         return skinframe;
6115 }
6116
6117 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6118 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6119 {
6120         int i;
6121         unsigned char *temp1, *temp2;
6122         skinframe_t *skinframe;
6123
6124         if (cls.state == ca_dedicated)
6125                 return NULL;
6126
6127         // if already loaded just return it, otherwise make a new skinframe
6128         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6129         if (skinframe && skinframe->base)
6130                 return skinframe;
6131
6132         skinframe->stain = NULL;
6133         skinframe->merged = NULL;
6134         skinframe->base = NULL;
6135         skinframe->pants = NULL;
6136         skinframe->shirt = NULL;
6137         skinframe->nmap = NULL;
6138         skinframe->gloss = NULL;
6139         skinframe->glow = NULL;
6140         skinframe->fog = NULL;
6141         skinframe->reflect = NULL;
6142         skinframe->hasalpha = false;
6143
6144         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6145         if (!skindata)
6146                 return NULL;
6147
6148         if (developer_loading.integer)
6149                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6150
6151         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6152         {
6153                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6154                 temp2 = temp1 + width * height * 4;
6155                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6156                 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);
6157                 Mem_Free(temp1);
6158         }
6159         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6160         if (textureflags & TEXF_ALPHA)
6161         {
6162                 for (i = 3;i < width * height * 4;i += 4)
6163                 {
6164                         if (skindata[i] < 255)
6165                         {
6166                                 skinframe->hasalpha = true;
6167                                 break;
6168                         }
6169                 }
6170                 if (r_loadfog && skinframe->hasalpha)
6171                 {
6172                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6173                         memcpy(fogpixels, skindata, width * height * 4);
6174                         for (i = 0;i < width * height * 4;i += 4)
6175                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6176                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6177                         Mem_Free(fogpixels);
6178                 }
6179         }
6180
6181         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6182         //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]);
6183
6184         return skinframe;
6185 }
6186
6187 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6188 {
6189         int i;
6190         int featuresmask;
6191         skinframe_t *skinframe;
6192
6193         if (cls.state == ca_dedicated)
6194                 return NULL;
6195
6196         // if already loaded just return it, otherwise make a new skinframe
6197         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6198         if (skinframe && skinframe->base)
6199                 return skinframe;
6200
6201         skinframe->stain = NULL;
6202         skinframe->merged = NULL;
6203         skinframe->base = NULL;
6204         skinframe->pants = NULL;
6205         skinframe->shirt = NULL;
6206         skinframe->nmap = NULL;
6207         skinframe->gloss = NULL;
6208         skinframe->glow = NULL;
6209         skinframe->fog = NULL;
6210         skinframe->reflect = NULL;
6211         skinframe->hasalpha = false;
6212
6213         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6214         if (!skindata)
6215                 return NULL;
6216
6217         if (developer_loading.integer)
6218                 Con_Printf("loading quake skin \"%s\"\n", name);
6219
6220         // 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)
6221         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6222         memcpy(skinframe->qpixels, skindata, width*height);
6223         skinframe->qwidth = width;
6224         skinframe->qheight = height;
6225
6226         featuresmask = 0;
6227         for (i = 0;i < width * height;i++)
6228                 featuresmask |= palette_featureflags[skindata[i]];
6229
6230         skinframe->hasalpha = false;
6231         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6232         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6233         skinframe->qgeneratemerged = true;
6234         skinframe->qgeneratebase = skinframe->qhascolormapping;
6235         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6236
6237         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6238         //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]);
6239
6240         return skinframe;
6241 }
6242
6243 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6244 {
6245         int width;
6246         int height;
6247         unsigned char *skindata;
6248
6249         if (!skinframe->qpixels)
6250                 return;
6251
6252         if (!skinframe->qhascolormapping)
6253                 colormapped = false;
6254
6255         if (colormapped)
6256         {
6257                 if (!skinframe->qgeneratebase)
6258                         return;
6259         }
6260         else
6261         {
6262                 if (!skinframe->qgeneratemerged)
6263                         return;
6264         }
6265
6266         width = skinframe->qwidth;
6267         height = skinframe->qheight;
6268         skindata = skinframe->qpixels;
6269
6270         if (skinframe->qgeneratenmap)
6271         {
6272                 unsigned char *temp1, *temp2;
6273                 skinframe->qgeneratenmap = false;
6274                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6275                 temp2 = temp1 + width * height * 4;
6276                 // use either a custom palette or the quake palette
6277                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6278                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6279                 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);
6280                 Mem_Free(temp1);
6281         }
6282
6283         if (skinframe->qgenerateglow)
6284         {
6285                 skinframe->qgenerateglow = false;
6286                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6287         }
6288
6289         if (colormapped)
6290         {
6291                 skinframe->qgeneratebase = false;
6292                 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);
6293                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6294                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6295         }
6296         else
6297         {
6298                 skinframe->qgeneratemerged = false;
6299                 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);
6300         }
6301
6302         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6303         {
6304                 Mem_Free(skinframe->qpixels);
6305                 skinframe->qpixels = NULL;
6306         }
6307 }
6308
6309 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)
6310 {
6311         int i;
6312         skinframe_t *skinframe;
6313
6314         if (cls.state == ca_dedicated)
6315                 return NULL;
6316
6317         // if already loaded just return it, otherwise make a new skinframe
6318         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6319         if (skinframe && skinframe->base)
6320                 return skinframe;
6321
6322         skinframe->stain = NULL;
6323         skinframe->merged = NULL;
6324         skinframe->base = NULL;
6325         skinframe->pants = NULL;
6326         skinframe->shirt = NULL;
6327         skinframe->nmap = NULL;
6328         skinframe->gloss = NULL;
6329         skinframe->glow = NULL;
6330         skinframe->fog = NULL;
6331         skinframe->reflect = NULL;
6332         skinframe->hasalpha = false;
6333
6334         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6335         if (!skindata)
6336                 return NULL;
6337
6338         if (developer_loading.integer)
6339                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6340
6341         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6342         if (textureflags & TEXF_ALPHA)
6343         {
6344                 for (i = 0;i < width * height;i++)
6345                 {
6346                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6347                         {
6348                                 skinframe->hasalpha = true;
6349                                 break;
6350                         }
6351                 }
6352                 if (r_loadfog && skinframe->hasalpha)
6353                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6354         }
6355
6356         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6357         //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]);
6358
6359         return skinframe;
6360 }
6361
6362 skinframe_t *R_SkinFrame_LoadMissing(void)
6363 {
6364         skinframe_t *skinframe;
6365
6366         if (cls.state == ca_dedicated)
6367                 return NULL;
6368
6369         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6370         skinframe->stain = NULL;
6371         skinframe->merged = NULL;
6372         skinframe->base = NULL;
6373         skinframe->pants = NULL;
6374         skinframe->shirt = NULL;
6375         skinframe->nmap = NULL;
6376         skinframe->gloss = NULL;
6377         skinframe->glow = NULL;
6378         skinframe->fog = NULL;
6379         skinframe->reflect = NULL;
6380         skinframe->hasalpha = false;
6381
6382         skinframe->avgcolor[0] = rand() / RAND_MAX;
6383         skinframe->avgcolor[1] = rand() / RAND_MAX;
6384         skinframe->avgcolor[2] = rand() / RAND_MAX;
6385         skinframe->avgcolor[3] = 1;
6386
6387         return skinframe;
6388 }
6389
6390 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6391 typedef struct suffixinfo_s
6392 {
6393         const char *suffix;
6394         qboolean flipx, flipy, flipdiagonal;
6395 }
6396 suffixinfo_t;
6397 static suffixinfo_t suffix[3][6] =
6398 {
6399         {
6400                 {"px",   false, false, false},
6401                 {"nx",   false, false, false},
6402                 {"py",   false, false, false},
6403                 {"ny",   false, false, false},
6404                 {"pz",   false, false, false},
6405                 {"nz",   false, false, false}
6406         },
6407         {
6408                 {"posx", false, false, false},
6409                 {"negx", false, false, false},
6410                 {"posy", false, false, false},
6411                 {"negy", false, false, false},
6412                 {"posz", false, false, false},
6413                 {"negz", false, false, false}
6414         },
6415         {
6416                 {"rt",    true, false,  true},
6417                 {"lf",   false,  true,  true},
6418                 {"ft",    true,  true, false},
6419                 {"bk",   false, false, false},
6420                 {"up",    true, false,  true},
6421                 {"dn",    true, false,  true}
6422         }
6423 };
6424
6425 static int componentorder[4] = {0, 1, 2, 3};
6426
6427 rtexture_t *R_LoadCubemap(const char *basename)
6428 {
6429         int i, j, cubemapsize;
6430         unsigned char *cubemappixels, *image_buffer;
6431         rtexture_t *cubemaptexture;
6432         char name[256];
6433         // must start 0 so the first loadimagepixels has no requested width/height
6434         cubemapsize = 0;
6435         cubemappixels = NULL;
6436         cubemaptexture = NULL;
6437         // keep trying different suffix groups (posx, px, rt) until one loads
6438         for (j = 0;j < 3 && !cubemappixels;j++)
6439         {
6440                 // load the 6 images in the suffix group
6441                 for (i = 0;i < 6;i++)
6442                 {
6443                         // generate an image name based on the base and and suffix
6444                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6445                         // load it
6446                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6447                         {
6448                                 // an image loaded, make sure width and height are equal
6449                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6450                                 {
6451                                         // if this is the first image to load successfully, allocate the cubemap memory
6452                                         if (!cubemappixels && image_width >= 1)
6453                                         {
6454                                                 cubemapsize = image_width;
6455                                                 // note this clears to black, so unavailable sides are black
6456                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6457                                         }
6458                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6459                                         if (cubemappixels)
6460                                                 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);
6461                                 }
6462                                 else
6463                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6464                                 // free the image
6465                                 Mem_Free(image_buffer);
6466                         }
6467                 }
6468         }
6469         // if a cubemap loaded, upload it
6470         if (cubemappixels)
6471         {
6472                 if (developer_loading.integer)
6473                         Con_Printf("loading cubemap \"%s\"\n", basename);
6474
6475                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6476                 Mem_Free(cubemappixels);
6477         }
6478         else
6479         {
6480                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6481                 if (developer_loading.integer)
6482                 {
6483                         Con_Printf("(tried tried images ");
6484                         for (j = 0;j < 3;j++)
6485                                 for (i = 0;i < 6;i++)
6486                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6487                         Con_Print(" and was unable to find any of them).\n");
6488                 }
6489         }
6490         return cubemaptexture;
6491 }
6492
6493 rtexture_t *R_GetCubemap(const char *basename)
6494 {
6495         int i;
6496         for (i = 0;i < r_texture_numcubemaps;i++)
6497                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6498                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6499         if (i >= MAX_CUBEMAPS)
6500                 return r_texture_whitecube;
6501         r_texture_numcubemaps++;
6502         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6503         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6504         return r_texture_cubemaps[i].texture;
6505 }
6506
6507 void R_FreeCubemaps(void)
6508 {
6509         int i;
6510         for (i = 0;i < r_texture_numcubemaps;i++)
6511         {
6512                 if (developer_loading.integer)
6513                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6514                 if (r_texture_cubemaps[i].texture)
6515                         R_FreeTexture(r_texture_cubemaps[i].texture);
6516         }
6517         r_texture_numcubemaps = 0;
6518 }
6519
6520 void R_Main_FreeViewCache(void)
6521 {
6522         if (r_refdef.viewcache.entityvisible)
6523                 Mem_Free(r_refdef.viewcache.entityvisible);
6524         if (r_refdef.viewcache.world_pvsbits)
6525                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6526         if (r_refdef.viewcache.world_leafvisible)
6527                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6528         if (r_refdef.viewcache.world_surfacevisible)
6529                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6530         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6531 }
6532
6533 void R_Main_ResizeViewCache(void)
6534 {
6535         int numentities = r_refdef.scene.numentities;
6536         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6537         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6538         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6539         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6540         if (r_refdef.viewcache.maxentities < numentities)
6541         {
6542                 r_refdef.viewcache.maxentities = numentities;
6543                 if (r_refdef.viewcache.entityvisible)
6544                         Mem_Free(r_refdef.viewcache.entityvisible);
6545                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6546         }
6547         if (r_refdef.viewcache.world_numclusters != numclusters)
6548         {
6549                 r_refdef.viewcache.world_numclusters = numclusters;
6550                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6551                 if (r_refdef.viewcache.world_pvsbits)
6552                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6553                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6554         }
6555         if (r_refdef.viewcache.world_numleafs != numleafs)
6556         {
6557                 r_refdef.viewcache.world_numleafs = numleafs;
6558                 if (r_refdef.viewcache.world_leafvisible)
6559                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6560                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6561         }
6562         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6563         {
6564                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6565                 if (r_refdef.viewcache.world_surfacevisible)
6566                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6567                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6568         }
6569 }
6570
6571 extern rtexture_t *loadingscreentexture;
6572 void gl_main_start(void)
6573 {
6574         loadingscreentexture = NULL;
6575         r_texture_blanknormalmap = NULL;
6576         r_texture_white = NULL;
6577         r_texture_grey128 = NULL;
6578         r_texture_black = NULL;
6579         r_texture_whitecube = NULL;
6580         r_texture_normalizationcube = NULL;
6581         r_texture_fogattenuation = NULL;
6582         r_texture_fogheighttexture = NULL;
6583         r_texture_gammaramps = NULL;
6584         r_texture_numcubemaps = 0;
6585
6586         r_loaddds = r_texture_dds_load.integer != 0;
6587         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6588
6589         switch(vid.renderpath)
6590         {
6591         case RENDERPATH_GL20:
6592         case RENDERPATH_D3D9:
6593         case RENDERPATH_D3D10:
6594         case RENDERPATH_D3D11:
6595         case RENDERPATH_SOFT:
6596                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6597                 Cvar_SetValueQuick(&gl_combine, 1);
6598                 Cvar_SetValueQuick(&r_glsl, 1);
6599                 r_loadnormalmap = true;
6600                 r_loadgloss = true;
6601                 r_loadfog = false;
6602                 break;
6603         case RENDERPATH_GL13:
6604                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6605                 Cvar_SetValueQuick(&gl_combine, 1);
6606                 Cvar_SetValueQuick(&r_glsl, 0);
6607                 r_loadnormalmap = false;
6608                 r_loadgloss = false;
6609                 r_loadfog = true;
6610                 break;
6611         case RENDERPATH_GL11:
6612                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6613                 Cvar_SetValueQuick(&gl_combine, 0);
6614                 Cvar_SetValueQuick(&r_glsl, 0);
6615                 r_loadnormalmap = false;
6616                 r_loadgloss = false;
6617                 r_loadfog = true;
6618                 break;
6619         case RENDERPATH_GLES2:
6620                 Cvar_SetValueQuick(&r_textureunits, 1);
6621                 Cvar_SetValueQuick(&gl_combine, 1);
6622                 Cvar_SetValueQuick(&r_glsl, 1);
6623                 r_loadnormalmap = true;
6624                 r_loadgloss = false;
6625                 r_loadfog = false;
6626                 break;
6627         }
6628
6629         R_AnimCache_Free();
6630         R_FrameData_Reset();
6631
6632         r_numqueries = 0;
6633         r_maxqueries = 0;
6634         memset(r_queries, 0, sizeof(r_queries));
6635
6636         r_qwskincache = NULL;
6637         r_qwskincache_size = 0;
6638
6639         // set up r_skinframe loading system for textures
6640         memset(&r_skinframe, 0, sizeof(r_skinframe));
6641         r_skinframe.loadsequence = 1;
6642         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6643
6644         r_main_texturepool = R_AllocTexturePool();
6645         R_BuildBlankTextures();
6646         R_BuildNoTexture();
6647         if (vid.support.arb_texture_cube_map)
6648         {
6649                 R_BuildWhiteCube();
6650                 R_BuildNormalizationCube();
6651         }
6652         r_texture_fogattenuation = NULL;
6653         r_texture_fogheighttexture = NULL;
6654         r_texture_gammaramps = NULL;
6655         //r_texture_fogintensity = NULL;
6656         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6657         memset(&r_waterstate, 0, sizeof(r_waterstate));
6658         r_glsl_permutation = NULL;
6659         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6660         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6661         glslshaderstring = NULL;
6662 #ifdef SUPPORTD3D
6663         r_hlsl_permutation = NULL;
6664         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6665         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6666 #endif
6667         hlslshaderstring = NULL;
6668         memset(&r_svbsp, 0, sizeof (r_svbsp));
6669
6670         r_refdef.fogmasktable_density = 0;
6671 }
6672
6673 void gl_main_shutdown(void)
6674 {
6675         R_AnimCache_Free();
6676         R_FrameData_Reset();
6677
6678         R_Main_FreeViewCache();
6679
6680         switch(vid.renderpath)
6681         {
6682         case RENDERPATH_GL11:
6683         case RENDERPATH_GL13:
6684         case RENDERPATH_GL20:
6685         case RENDERPATH_GLES2:
6686                 if (r_maxqueries)
6687                         qglDeleteQueriesARB(r_maxqueries, r_queries);
6688                 break;
6689         case RENDERPATH_D3D9:
6690                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6691                 break;
6692         case RENDERPATH_D3D10:
6693                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6694                 break;
6695         case RENDERPATH_D3D11:
6696                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6697                 break;
6698         case RENDERPATH_SOFT:
6699                 break;
6700         }
6701
6702         r_numqueries = 0;
6703         r_maxqueries = 0;
6704         memset(r_queries, 0, sizeof(r_queries));
6705
6706         r_qwskincache = NULL;
6707         r_qwskincache_size = 0;
6708
6709         // clear out the r_skinframe state
6710         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6711         memset(&r_skinframe, 0, sizeof(r_skinframe));
6712
6713         if (r_svbsp.nodes)
6714                 Mem_Free(r_svbsp.nodes);
6715         memset(&r_svbsp, 0, sizeof (r_svbsp));
6716         R_FreeTexturePool(&r_main_texturepool);
6717         loadingscreentexture = NULL;
6718         r_texture_blanknormalmap = NULL;
6719         r_texture_white = NULL;
6720         r_texture_grey128 = NULL;
6721         r_texture_black = NULL;
6722         r_texture_whitecube = NULL;
6723         r_texture_normalizationcube = NULL;
6724         r_texture_fogattenuation = NULL;
6725         r_texture_fogheighttexture = NULL;
6726         r_texture_gammaramps = NULL;
6727         r_texture_numcubemaps = 0;
6728         //r_texture_fogintensity = NULL;
6729         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6730         memset(&r_waterstate, 0, sizeof(r_waterstate));
6731         R_GLSL_Restart_f();
6732
6733         r_glsl_permutation = NULL;
6734         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6735         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6736         glslshaderstring = NULL;
6737 #ifdef SUPPORTD3D
6738         r_hlsl_permutation = NULL;
6739         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6740         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6741 #endif
6742         hlslshaderstring = NULL;
6743 }
6744
6745 extern void CL_ParseEntityLump(char *entitystring);
6746 void gl_main_newmap(void)
6747 {
6748         // FIXME: move this code to client
6749         char *entities, entname[MAX_QPATH];
6750         if (r_qwskincache)
6751                 Mem_Free(r_qwskincache);
6752         r_qwskincache = NULL;
6753         r_qwskincache_size = 0;
6754         if (cl.worldmodel)
6755         {
6756                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6757                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6758                 {
6759                         CL_ParseEntityLump(entities);
6760                         Mem_Free(entities);
6761                         return;
6762                 }
6763                 if (cl.worldmodel->brush.entities)
6764                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6765         }
6766         R_Main_FreeViewCache();
6767
6768         R_FrameData_Reset();
6769 }
6770
6771 void GL_Main_Init(void)
6772 {
6773         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6774
6775         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6776         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6777         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6778         if (gamemode == GAME_NEHAHRA)
6779         {
6780                 Cvar_RegisterVariable (&gl_fogenable);
6781                 Cvar_RegisterVariable (&gl_fogdensity);
6782                 Cvar_RegisterVariable (&gl_fogred);
6783                 Cvar_RegisterVariable (&gl_foggreen);
6784                 Cvar_RegisterVariable (&gl_fogblue);
6785                 Cvar_RegisterVariable (&gl_fogstart);
6786                 Cvar_RegisterVariable (&gl_fogend);
6787                 Cvar_RegisterVariable (&gl_skyclip);
6788         }
6789         Cvar_RegisterVariable(&r_motionblur);
6790         Cvar_RegisterVariable(&r_motionblur_maxblur);
6791         Cvar_RegisterVariable(&r_motionblur_bmin);
6792         Cvar_RegisterVariable(&r_motionblur_vmin);
6793         Cvar_RegisterVariable(&r_motionblur_vmax);
6794         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6795         Cvar_RegisterVariable(&r_motionblur_randomize);
6796         Cvar_RegisterVariable(&r_damageblur);
6797         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6798         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6799         Cvar_RegisterVariable(&r_equalize_entities_by);
6800         Cvar_RegisterVariable(&r_equalize_entities_to);
6801         Cvar_RegisterVariable(&r_depthfirst);
6802         Cvar_RegisterVariable(&r_useinfinitefarclip);
6803         Cvar_RegisterVariable(&r_farclip_base);
6804         Cvar_RegisterVariable(&r_farclip_world);
6805         Cvar_RegisterVariable(&r_nearclip);
6806         Cvar_RegisterVariable(&r_showbboxes);
6807         Cvar_RegisterVariable(&r_showsurfaces);
6808         Cvar_RegisterVariable(&r_showtris);
6809         Cvar_RegisterVariable(&r_shownormals);
6810         Cvar_RegisterVariable(&r_showlighting);
6811         Cvar_RegisterVariable(&r_showshadowvolumes);
6812         Cvar_RegisterVariable(&r_showcollisionbrushes);
6813         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6814         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6815         Cvar_RegisterVariable(&r_showdisabledepthtest);
6816         Cvar_RegisterVariable(&r_drawportals);
6817         Cvar_RegisterVariable(&r_drawentities);
6818         Cvar_RegisterVariable(&r_draw2d);
6819         Cvar_RegisterVariable(&r_drawworld);
6820         Cvar_RegisterVariable(&r_cullentities_trace);
6821         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6822         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6823         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6824         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6825         Cvar_RegisterVariable(&r_drawviewmodel);
6826         Cvar_RegisterVariable(&r_drawexteriormodel);
6827         Cvar_RegisterVariable(&r_speeds);
6828         Cvar_RegisterVariable(&r_fullbrights);
6829         Cvar_RegisterVariable(&r_wateralpha);
6830         Cvar_RegisterVariable(&r_dynamic);
6831         Cvar_RegisterVariable(&r_fakelight);
6832         Cvar_RegisterVariable(&r_fakelight_intensity);
6833         Cvar_RegisterVariable(&r_fullbright);
6834         Cvar_RegisterVariable(&r_shadows);
6835         Cvar_RegisterVariable(&r_shadows_darken);
6836         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6837         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6838         Cvar_RegisterVariable(&r_shadows_throwdistance);
6839         Cvar_RegisterVariable(&r_shadows_throwdirection);
6840         Cvar_RegisterVariable(&r_shadows_focus);
6841         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6842         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6843         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6844         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6845         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6846         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6847         Cvar_RegisterVariable(&r_fog_exp2);
6848         Cvar_RegisterVariable(&r_drawfog);
6849         Cvar_RegisterVariable(&r_transparentdepthmasking);
6850         Cvar_RegisterVariable(&r_texture_dds_load);
6851         Cvar_RegisterVariable(&r_texture_dds_save);
6852         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6853         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6854         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6855         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6856         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6857         Cvar_RegisterVariable(&r_textureunits);
6858         Cvar_RegisterVariable(&gl_combine);
6859         Cvar_RegisterVariable(&r_glsl);
6860         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6861         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6862         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6863         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6864         Cvar_RegisterVariable(&r_glsl_postprocess);
6865         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6866         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6867         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6868         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6869         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6870         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6871         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6872         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6873
6874         Cvar_RegisterVariable(&r_water);
6875         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6876         Cvar_RegisterVariable(&r_water_clippingplanebias);
6877         Cvar_RegisterVariable(&r_water_refractdistort);
6878         Cvar_RegisterVariable(&r_water_reflectdistort);
6879         Cvar_RegisterVariable(&r_water_scissormode);
6880         Cvar_RegisterVariable(&r_lerpsprites);
6881         Cvar_RegisterVariable(&r_lerpmodels);
6882         Cvar_RegisterVariable(&r_lerplightstyles);
6883         Cvar_RegisterVariable(&r_waterscroll);
6884         Cvar_RegisterVariable(&r_bloom);
6885         Cvar_RegisterVariable(&r_bloom_colorscale);
6886         Cvar_RegisterVariable(&r_bloom_brighten);
6887         Cvar_RegisterVariable(&r_bloom_blur);
6888         Cvar_RegisterVariable(&r_bloom_resolution);
6889         Cvar_RegisterVariable(&r_bloom_colorexponent);
6890         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6891         Cvar_RegisterVariable(&r_hdr);
6892         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6893         Cvar_RegisterVariable(&r_hdr_glowintensity);
6894         Cvar_RegisterVariable(&r_hdr_range);
6895         Cvar_RegisterVariable(&r_hdr_irisadaptation);
6896         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6897         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6898         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6899         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6900         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6901         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6902         Cvar_RegisterVariable(&developer_texturelogging);
6903         Cvar_RegisterVariable(&gl_lightmaps);
6904         Cvar_RegisterVariable(&r_test);
6905         Cvar_RegisterVariable(&r_glsl_saturation);
6906         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6907         Cvar_RegisterVariable(&r_framedatasize);
6908         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6909                 Cvar_SetValue("r_fullbrights", 0);
6910         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6911
6912         Cvar_RegisterVariable(&r_track_sprites);
6913         Cvar_RegisterVariable(&r_track_sprites_flags);
6914         Cvar_RegisterVariable(&r_track_sprites_scalew);
6915         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6916         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6917         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6918         Cvar_RegisterVariable(&r_overheadsprites_scalex);
6919         Cvar_RegisterVariable(&r_overheadsprites_scaley);
6920 }
6921
6922 extern void R_Textures_Init(void);
6923 extern void GL_Draw_Init(void);
6924 extern void GL_Main_Init(void);
6925 extern void R_Shadow_Init(void);
6926 extern void R_Sky_Init(void);
6927 extern void GL_Surf_Init(void);
6928 extern void R_Particles_Init(void);
6929 extern void R_Explosion_Init(void);
6930 extern void gl_backend_init(void);
6931 extern void Sbar_Init(void);
6932 extern void R_LightningBeams_Init(void);
6933 extern void Mod_RenderInit(void);
6934 extern void Font_Init(void);
6935
6936 void Render_Init(void)
6937 {
6938         gl_backend_init();
6939         R_Textures_Init();
6940         GL_Main_Init();
6941         Font_Init();
6942         GL_Draw_Init();
6943         R_Shadow_Init();
6944         R_Sky_Init();
6945         GL_Surf_Init();
6946         Sbar_Init();
6947         R_Particles_Init();
6948         R_Explosion_Init();
6949         R_LightningBeams_Init();
6950         Mod_RenderInit();
6951 }
6952
6953 /*
6954 ===============
6955 GL_Init
6956 ===============
6957 */
6958 extern char *ENGINE_EXTENSIONS;
6959 void GL_Init (void)
6960 {
6961         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6962         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6963         gl_version = (const char *)qglGetString(GL_VERSION);
6964         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6965
6966         if (!gl_extensions)
6967                 gl_extensions = "";
6968         if (!gl_platformextensions)
6969                 gl_platformextensions = "";
6970
6971         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6972         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6973         Con_Printf("GL_VERSION: %s\n", gl_version);
6974         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6975         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6976
6977         VID_CheckExtensions();
6978
6979         // LordHavoc: report supported extensions
6980         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6981
6982         // clear to black (loading plaque will be seen over this)
6983         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6984 }
6985
6986 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6987 {
6988         int i;
6989         mplane_t *p;
6990         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6991         {
6992                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6993                 if (i == 4)
6994                         continue;
6995                 p = r_refdef.view.frustum + i;
6996                 switch(p->signbits)
6997                 {
6998                 default:
6999                 case 0:
7000                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7001                                 return true;
7002                         break;
7003                 case 1:
7004                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7005                                 return true;
7006                         break;
7007                 case 2:
7008                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7009                                 return true;
7010                         break;
7011                 case 3:
7012                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7013                                 return true;
7014                         break;
7015                 case 4:
7016                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7017                                 return true;
7018                         break;
7019                 case 5:
7020                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7021                                 return true;
7022                         break;
7023                 case 6:
7024                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7025                                 return true;
7026                         break;
7027                 case 7:
7028                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7029                                 return true;
7030                         break;
7031                 }
7032         }
7033         return false;
7034 }
7035
7036 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7037 {
7038         int i;
7039         const mplane_t *p;
7040         for (i = 0;i < numplanes;i++)
7041         {
7042                 p = planes + i;
7043                 switch(p->signbits)
7044                 {
7045                 default:
7046                 case 0:
7047                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7048                                 return true;
7049                         break;
7050                 case 1:
7051                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7052                                 return true;
7053                         break;
7054                 case 2:
7055                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7056                                 return true;
7057                         break;
7058                 case 3:
7059                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7060                                 return true;
7061                         break;
7062                 case 4:
7063                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7064                                 return true;
7065                         break;
7066                 case 5:
7067                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7068                                 return true;
7069                         break;
7070                 case 6:
7071                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7072                                 return true;
7073                         break;
7074                 case 7:
7075                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7076                                 return true;
7077                         break;
7078                 }
7079         }
7080         return false;
7081 }
7082
7083 //==================================================================================
7084
7085 // LordHavoc: this stores temporary data used within the same frame
7086
7087 typedef struct r_framedata_mem_s
7088 {
7089         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7090         size_t size; // how much usable space
7091         size_t current; // how much space in use
7092         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7093         size_t wantedsize; // how much space was allocated
7094         unsigned char *data; // start of real data (16byte aligned)
7095 }
7096 r_framedata_mem_t;
7097
7098 static r_framedata_mem_t *r_framedata_mem;
7099
7100 void R_FrameData_Reset(void)
7101 {
7102         while (r_framedata_mem)
7103         {
7104                 r_framedata_mem_t *next = r_framedata_mem->purge;
7105                 Mem_Free(r_framedata_mem);
7106                 r_framedata_mem = next;
7107         }
7108 }
7109
7110 void R_FrameData_Resize(void)
7111 {
7112         size_t wantedsize;
7113         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7114         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7115         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7116         {
7117                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7118                 newmem->wantedsize = wantedsize;
7119                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7120                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7121                 newmem->current = 0;
7122                 newmem->mark = 0;
7123                 newmem->purge = r_framedata_mem;
7124                 r_framedata_mem = newmem;
7125         }
7126 }
7127
7128 void R_FrameData_NewFrame(void)
7129 {
7130         R_FrameData_Resize();
7131         if (!r_framedata_mem)
7132                 return;
7133         // if we ran out of space on the last frame, free the old memory now
7134         while (r_framedata_mem->purge)
7135         {
7136                 // repeatedly remove the second item in the list, leaving only head
7137                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7138                 Mem_Free(r_framedata_mem->purge);
7139                 r_framedata_mem->purge = next;
7140         }
7141         // reset the current mem pointer
7142         r_framedata_mem->current = 0;
7143         r_framedata_mem->mark = 0;
7144 }
7145
7146 void *R_FrameData_Alloc(size_t size)
7147 {
7148         void *data;
7149
7150         // align to 16 byte boundary - the data pointer is already aligned, so we
7151         // only need to ensure the size of every allocation is also aligned
7152         size = (size + 15) & ~15;
7153
7154         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7155         {
7156                 // emergency - we ran out of space, allocate more memory
7157                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7158                 R_FrameData_Resize();
7159         }
7160
7161         data = r_framedata_mem->data + r_framedata_mem->current;
7162         r_framedata_mem->current += size;
7163
7164         // count the usage for stats
7165         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7166         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7167
7168         return (void *)data;
7169 }
7170
7171 void *R_FrameData_Store(size_t size, void *data)
7172 {
7173         void *d = R_FrameData_Alloc(size);
7174         if (d && data)
7175                 memcpy(d, data, size);
7176         return d;
7177 }
7178
7179 void R_FrameData_SetMark(void)
7180 {
7181         if (!r_framedata_mem)
7182                 return;
7183         r_framedata_mem->mark = r_framedata_mem->current;
7184 }
7185
7186 void R_FrameData_ReturnToMark(void)
7187 {
7188         if (!r_framedata_mem)
7189                 return;
7190         r_framedata_mem->current = r_framedata_mem->mark;
7191 }
7192
7193 //==================================================================================
7194
7195 // LordHavoc: animcache originally written by Echon, rewritten since then
7196
7197 /**
7198  * Animation cache prevents re-generating mesh data for an animated model
7199  * multiple times in one frame for lighting, shadowing, reflections, etc.
7200  */
7201
7202 void R_AnimCache_Free(void)
7203 {
7204 }
7205
7206 void R_AnimCache_ClearCache(void)
7207 {
7208         int i;
7209         entity_render_t *ent;
7210
7211         for (i = 0;i < r_refdef.scene.numentities;i++)
7212         {
7213                 ent = r_refdef.scene.entities[i];
7214                 ent->animcache_vertex3f = NULL;
7215                 ent->animcache_normal3f = NULL;
7216                 ent->animcache_svector3f = NULL;
7217                 ent->animcache_tvector3f = NULL;
7218                 ent->animcache_vertexmesh = NULL;
7219                 ent->animcache_vertex3fbuffer = NULL;
7220                 ent->animcache_vertexmeshbuffer = NULL;
7221         }
7222 }
7223
7224 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7225 {
7226         int i;
7227
7228         // check if we need the meshbuffers
7229         if (!vid.useinterleavedarrays)
7230                 return;
7231
7232         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7233                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7234         // TODO: upload vertex3f buffer?
7235         if (ent->animcache_vertexmesh)
7236         {
7237                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7238                 for (i = 0;i < numvertices;i++)
7239                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7240                 if (ent->animcache_svector3f)
7241                         for (i = 0;i < numvertices;i++)
7242                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7243                 if (ent->animcache_tvector3f)
7244                         for (i = 0;i < numvertices;i++)
7245                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7246                 if (ent->animcache_normal3f)
7247                         for (i = 0;i < numvertices;i++)
7248                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7249                 // TODO: upload vertexmeshbuffer?
7250         }
7251 }
7252
7253 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7254 {
7255         dp_model_t *model = ent->model;
7256         int numvertices;
7257         // see if it's already cached this frame
7258         if (ent->animcache_vertex3f)
7259         {
7260                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7261                 if (wantnormals || wanttangents)
7262                 {
7263                         if (ent->animcache_normal3f)
7264                                 wantnormals = false;
7265                         if (ent->animcache_svector3f)
7266                                 wanttangents = false;
7267                         if (wantnormals || wanttangents)
7268                         {
7269                                 numvertices = model->surfmesh.num_vertices;
7270                                 if (wantnormals)
7271                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7272                                 if (wanttangents)
7273                                 {
7274                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7275                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7276                                 }
7277                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7278                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7279                         }
7280                 }
7281         }
7282         else
7283         {
7284                 // see if this ent is worth caching
7285                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7286                         return false;
7287                 // get some memory for this entity and generate mesh data
7288                 numvertices = model->surfmesh.num_vertices;
7289                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7290                 if (wantnormals)
7291                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7292                 if (wanttangents)
7293                 {
7294                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7295                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7296                 }
7297                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7298                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7299         }
7300         return true;
7301 }
7302
7303 void R_AnimCache_CacheVisibleEntities(void)
7304 {
7305         int i;
7306         qboolean wantnormals = true;
7307         qboolean wanttangents = !r_showsurfaces.integer;
7308
7309         switch(vid.renderpath)
7310         {
7311         case RENDERPATH_GL20:
7312         case RENDERPATH_D3D9:
7313         case RENDERPATH_D3D10:
7314         case RENDERPATH_D3D11:
7315         case RENDERPATH_GLES2:
7316                 break;
7317         case RENDERPATH_GL13:
7318         case RENDERPATH_GL11:
7319                 wanttangents = false;
7320                 break;
7321         case RENDERPATH_SOFT:
7322                 break;
7323         }
7324
7325         if (r_shownormals.integer)
7326                 wanttangents = wantnormals = true;
7327
7328         // TODO: thread this
7329         // NOTE: R_PrepareRTLights() also caches entities
7330
7331         for (i = 0;i < r_refdef.scene.numentities;i++)
7332                 if (r_refdef.viewcache.entityvisible[i])
7333                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7334 }
7335
7336 //==================================================================================
7337
7338 static void R_View_UpdateEntityLighting (void)
7339 {
7340         int i;
7341         entity_render_t *ent;
7342         vec3_t tempdiffusenormal, avg;
7343         vec_t f, fa, fd, fdd;
7344         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7345
7346         for (i = 0;i < r_refdef.scene.numentities;i++)
7347         {
7348                 ent = r_refdef.scene.entities[i];
7349
7350                 // skip unseen models
7351                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7352                         continue;
7353
7354                 // skip bsp models
7355                 if (ent->model && ent->model->brush.num_leafs)
7356                 {
7357                         // TODO: use modellight for r_ambient settings on world?
7358                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7359                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7360                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7361                         continue;
7362                 }
7363
7364                 // fetch the lighting from the worldmodel data
7365                 VectorClear(ent->modellight_ambient);
7366                 VectorClear(ent->modellight_diffuse);
7367                 VectorClear(tempdiffusenormal);
7368                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7369                 {
7370                         vec3_t org;
7371                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7372
7373                         // complete lightning for lit sprites
7374                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7375                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7376                         {
7377                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7378                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7379                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7380                         }
7381                         else
7382                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7383
7384                         if(ent->flags & RENDER_EQUALIZE)
7385                         {
7386                                 // first fix up ambient lighting...
7387                                 if(r_equalize_entities_minambient.value > 0)
7388                                 {
7389                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7390                                         if(fd > 0)
7391                                         {
7392                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7393                                                 if(fa < r_equalize_entities_minambient.value * fd)
7394                                                 {
7395                                                         // solve:
7396                                                         //   fa'/fd' = minambient
7397                                                         //   fa'+0.25*fd' = fa+0.25*fd
7398                                                         //   ...
7399                                                         //   fa' = fd' * minambient
7400                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7401                                                         //   ...
7402                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7403                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7404                                                         //   ...
7405                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7406                                                         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
7407                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7408                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7409                                                 }
7410                                         }
7411                                 }
7412
7413                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7414                                 {
7415                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7416                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7417                                         f = fa + 0.25 * fd;
7418                                         if(f > 0)
7419                                         {
7420                                                 // adjust brightness and saturation to target
7421                                                 avg[0] = avg[1] = avg[2] = fa / f;
7422                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7423                                                 avg[0] = avg[1] = avg[2] = fd / f;
7424                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7425                                         }
7426                                 }
7427                         }
7428                 }
7429                 else // highly rare
7430                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7431
7432                 // move the light direction into modelspace coordinates for lighting code
7433                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7434                 if(VectorLength2(ent->modellight_lightdir) == 0)
7435                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7436                 VectorNormalize(ent->modellight_lightdir);
7437         }
7438 }
7439
7440 #define MAX_LINEOFSIGHTTRACES 64
7441
7442 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7443 {
7444         int i;
7445         vec3_t boxmins, boxmaxs;
7446         vec3_t start;
7447         vec3_t end;
7448         dp_model_t *model = r_refdef.scene.worldmodel;
7449
7450         if (!model || !model->brush.TraceLineOfSight)
7451                 return true;
7452
7453         // expand the box a little
7454         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7455         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7456         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7457         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7458         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7459         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7460
7461         // return true if eye is inside enlarged box
7462         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7463                 return true;
7464
7465         // try center
7466         VectorCopy(eye, start);
7467         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7468         if (model->brush.TraceLineOfSight(model, start, end))
7469                 return true;
7470
7471         // try various random positions
7472         for (i = 0;i < numsamples;i++)
7473         {
7474                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7475                 if (model->brush.TraceLineOfSight(model, start, end))
7476                         return true;
7477         }
7478
7479         return false;
7480 }
7481
7482
7483 static void R_View_UpdateEntityVisible (void)
7484 {
7485         int i;
7486         int renderimask;
7487         int samples;
7488         entity_render_t *ent;
7489
7490         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7491                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7492                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7493                 :                                                          RENDER_EXTERIORMODEL;
7494         if (!r_drawviewmodel.integer)
7495                 renderimask |= RENDER_VIEWMODEL;
7496         if (!r_drawexteriormodel.integer)
7497                 renderimask |= RENDER_EXTERIORMODEL;
7498         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7499         {
7500                 // worldmodel can check visibility
7501                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7502                 for (i = 0;i < r_refdef.scene.numentities;i++)
7503                 {
7504                         ent = r_refdef.scene.entities[i];
7505                         if (!(ent->flags & renderimask))
7506                         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)))
7507                         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))
7508                                 r_refdef.viewcache.entityvisible[i] = true;
7509                 }
7510                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7511                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7512                 {
7513                         for (i = 0;i < r_refdef.scene.numentities;i++)
7514                         {
7515                                 ent = r_refdef.scene.entities[i];
7516                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7517                                 {
7518                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7519                                         if (samples < 0)
7520                                                 continue; // temp entities do pvs only
7521                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7522                                                 ent->last_trace_visibility = realtime;
7523                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7524                                                 r_refdef.viewcache.entityvisible[i] = 0;
7525                                 }
7526                         }
7527                 }
7528         }
7529         else
7530         {
7531                 // no worldmodel or it can't check visibility
7532                 for (i = 0;i < r_refdef.scene.numentities;i++)
7533                 {
7534                         ent = r_refdef.scene.entities[i];
7535                         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));
7536                 }
7537         }
7538 }
7539
7540 /// only used if skyrendermasked, and normally returns false
7541 int R_DrawBrushModelsSky (void)
7542 {
7543         int i, sky;
7544         entity_render_t *ent;
7545
7546         sky = false;
7547         for (i = 0;i < r_refdef.scene.numentities;i++)
7548         {
7549                 if (!r_refdef.viewcache.entityvisible[i])
7550                         continue;
7551                 ent = r_refdef.scene.entities[i];
7552                 if (!ent->model || !ent->model->DrawSky)
7553                         continue;
7554                 ent->model->DrawSky(ent);
7555                 sky = true;
7556         }
7557         return sky;
7558 }
7559
7560 static void R_DrawNoModel(entity_render_t *ent);
7561 static void R_DrawModels(void)
7562 {
7563         int i;
7564         entity_render_t *ent;
7565
7566         for (i = 0;i < r_refdef.scene.numentities;i++)
7567         {
7568                 if (!r_refdef.viewcache.entityvisible[i])
7569                         continue;
7570                 ent = r_refdef.scene.entities[i];
7571                 r_refdef.stats.entities++;
7572                 if (ent->model && ent->model->Draw != NULL)
7573                         ent->model->Draw(ent);
7574                 else
7575                         R_DrawNoModel(ent);
7576         }
7577 }
7578
7579 static void R_DrawModelsDepth(void)
7580 {
7581         int i;
7582         entity_render_t *ent;
7583
7584         for (i = 0;i < r_refdef.scene.numentities;i++)
7585         {
7586                 if (!r_refdef.viewcache.entityvisible[i])
7587                         continue;
7588                 ent = r_refdef.scene.entities[i];
7589                 if (ent->model && ent->model->DrawDepth != NULL)
7590                         ent->model->DrawDepth(ent);
7591         }
7592 }
7593
7594 static void R_DrawModelsDebug(void)
7595 {
7596         int i;
7597         entity_render_t *ent;
7598
7599         for (i = 0;i < r_refdef.scene.numentities;i++)
7600         {
7601                 if (!r_refdef.viewcache.entityvisible[i])
7602                         continue;
7603                 ent = r_refdef.scene.entities[i];
7604                 if (ent->model && ent->model->DrawDebug != NULL)
7605                         ent->model->DrawDebug(ent);
7606         }
7607 }
7608
7609 static void R_DrawModelsAddWaterPlanes(void)
7610 {
7611         int i;
7612         entity_render_t *ent;
7613
7614         for (i = 0;i < r_refdef.scene.numentities;i++)
7615         {
7616                 if (!r_refdef.viewcache.entityvisible[i])
7617                         continue;
7618                 ent = r_refdef.scene.entities[i];
7619                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7620                         ent->model->DrawAddWaterPlanes(ent);
7621         }
7622 }
7623
7624 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7625 {
7626         if (r_hdr_irisadaptation.integer)
7627         {
7628                 vec3_t ambient;
7629                 vec3_t diffuse;
7630                 vec3_t diffusenormal;
7631                 vec_t brightness;
7632                 vec_t goal;
7633                 vec_t adjust;
7634                 vec_t current;
7635                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7636                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7637                 brightness = max(0.0000001f, brightness);
7638                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7639                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7640                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7641                 current = r_hdr_irisadaptation_value.value;
7642                 if (current < goal)
7643                         current = min(current + adjust, goal);
7644                 else if (current > goal)
7645                         current = max(current - adjust, goal);
7646                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7647                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7648         }
7649         else if (r_hdr_irisadaptation_value.value != 1.0f)
7650                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7651 }
7652
7653 static void R_View_SetFrustum(const int *scissor)
7654 {
7655         int i;
7656         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7657         vec3_t forward, left, up, origin, v;
7658
7659         if(scissor)
7660         {
7661                 // flipped x coordinates (because x points left here)
7662                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7663                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7664
7665                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7666                 switch(vid.renderpath)
7667                 {
7668                         case RENDERPATH_D3D9:
7669                         case RENDERPATH_D3D10:
7670                         case RENDERPATH_D3D11:
7671                         case RENDERPATH_SOFT:
7672                                 // non-flipped y coordinates
7673                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7674                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7675                                 break;
7676                         case RENDERPATH_GL11:
7677                         case RENDERPATH_GL13:
7678                         case RENDERPATH_GL20:
7679                         case RENDERPATH_GLES2:
7680                                 // non-flipped y coordinates
7681                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7682                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7683                                 break;
7684                 }
7685         }
7686
7687         // we can't trust r_refdef.view.forward and friends in reflected scenes
7688         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7689
7690 #if 0
7691         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7692         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7693         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7694         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7695         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7696         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7697         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7698         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7699         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7700         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7701         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7702         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7703 #endif
7704
7705 #if 0
7706         zNear = r_refdef.nearclip;
7707         nudge = 1.0 - 1.0 / (1<<23);
7708         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7709         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7710         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7711         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7712         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7713         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7714         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7715         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7716 #endif
7717
7718
7719
7720 #if 0
7721         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7722         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7723         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7724         r_refdef.view.frustum[0].dist = m[15] - m[12];
7725
7726         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7727         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7728         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7729         r_refdef.view.frustum[1].dist = m[15] + m[12];
7730
7731         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7732         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7733         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7734         r_refdef.view.frustum[2].dist = m[15] - m[13];
7735
7736         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7737         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7738         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7739         r_refdef.view.frustum[3].dist = m[15] + m[13];
7740
7741         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7742         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7743         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7744         r_refdef.view.frustum[4].dist = m[15] - m[14];
7745
7746         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7747         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7748         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7749         r_refdef.view.frustum[5].dist = m[15] + m[14];
7750 #endif
7751
7752         if (r_refdef.view.useperspective)
7753         {
7754                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7755                 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]);
7756                 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]);
7757                 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]);
7758                 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]);
7759
7760                 // then the normals from the corners relative to origin
7761                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7762                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7763                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7764                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7765
7766                 // in a NORMAL view, forward cross left == up
7767                 // in a REFLECTED view, forward cross left == down
7768                 // so our cross products above need to be adjusted for a left handed coordinate system
7769                 CrossProduct(forward, left, v);
7770                 if(DotProduct(v, up) < 0)
7771                 {
7772                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7773                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7774                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7775                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7776                 }
7777
7778                 // Leaving those out was a mistake, those were in the old code, and they
7779                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7780                 // I couldn't reproduce it after adding those normalizations. --blub
7781                 VectorNormalize(r_refdef.view.frustum[0].normal);
7782                 VectorNormalize(r_refdef.view.frustum[1].normal);
7783                 VectorNormalize(r_refdef.view.frustum[2].normal);
7784                 VectorNormalize(r_refdef.view.frustum[3].normal);
7785
7786                 // make the corners absolute
7787                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7788                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7789                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7790                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7791
7792                 // one more normal
7793                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7794
7795                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7796                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7797                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7798                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7799                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7800         }
7801         else
7802         {
7803                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7804                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7805                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7806                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7807                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7808                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7809                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7810                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7811                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7812                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7813         }
7814         r_refdef.view.numfrustumplanes = 5;
7815
7816         if (r_refdef.view.useclipplane)
7817         {
7818                 r_refdef.view.numfrustumplanes = 6;
7819                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7820         }
7821
7822         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7823                 PlaneClassify(r_refdef.view.frustum + i);
7824
7825         // LordHavoc: note to all quake engine coders, Quake had a special case
7826         // for 90 degrees which assumed a square view (wrong), so I removed it,
7827         // Quake2 has it disabled as well.
7828
7829         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7830         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7831         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7832         //PlaneClassify(&frustum[0]);
7833
7834         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7835         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7836         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7837         //PlaneClassify(&frustum[1]);
7838
7839         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7840         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7841         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7842         //PlaneClassify(&frustum[2]);
7843
7844         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7845         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7846         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7847         //PlaneClassify(&frustum[3]);
7848
7849         // nearclip plane
7850         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7851         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7852         //PlaneClassify(&frustum[4]);
7853 }
7854
7855 void R_View_UpdateWithScissor(const int *myscissor)
7856 {
7857         R_Main_ResizeViewCache();
7858         R_View_SetFrustum(myscissor);
7859         R_View_WorldVisibility(r_refdef.view.useclipplane);
7860         R_View_UpdateEntityVisible();
7861         R_View_UpdateEntityLighting();
7862 }
7863
7864 void R_View_Update(void)
7865 {
7866         R_Main_ResizeViewCache();
7867         R_View_SetFrustum(NULL);
7868         R_View_WorldVisibility(r_refdef.view.useclipplane);
7869         R_View_UpdateEntityVisible();
7870         R_View_UpdateEntityLighting();
7871 }
7872
7873 void R_SetupView(qboolean allowwaterclippingplane)
7874 {
7875         const float *customclipplane = NULL;
7876         float plane[4];
7877         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7878         {
7879                 // LordHavoc: couldn't figure out how to make this approach the
7880                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7881                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7882                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7883                         dist = r_refdef.view.clipplane.dist;
7884                 plane[0] = r_refdef.view.clipplane.normal[0];
7885                 plane[1] = r_refdef.view.clipplane.normal[1];
7886                 plane[2] = r_refdef.view.clipplane.normal[2];
7887                 plane[3] = dist;
7888                 customclipplane = plane;
7889         }
7890
7891         if (!r_refdef.view.useperspective)
7892                 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);
7893         else if (vid.stencil && r_useinfinitefarclip.integer)
7894                 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);
7895         else
7896                 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);
7897         R_SetViewport(&r_refdef.view.viewport);
7898 }
7899
7900 void R_EntityMatrix(const matrix4x4_t *matrix)
7901 {
7902         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7903         {
7904                 gl_modelmatrixchanged = false;
7905                 gl_modelmatrix = *matrix;
7906                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7907                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7908                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7909                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7910                 CHECKGLERROR
7911                 switch(vid.renderpath)
7912                 {
7913                 case RENDERPATH_D3D9:
7914 #ifdef SUPPORTD3D
7915                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
7916                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
7917 #endif
7918                         break;
7919                 case RENDERPATH_D3D10:
7920                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
7921                         break;
7922                 case RENDERPATH_D3D11:
7923                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
7924                         break;
7925                 case RENDERPATH_GL13:
7926                 case RENDERPATH_GL11:
7927                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7928                         break;
7929                 case RENDERPATH_SOFT:
7930                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
7931                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
7932                         break;
7933                 case RENDERPATH_GL20:
7934                 case RENDERPATH_GLES2:
7935                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7936                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7937                         break;
7938                 }
7939         }
7940 }
7941
7942 void R_ResetViewRendering2D(void)
7943 {
7944         r_viewport_t viewport;
7945         DrawQ_Finish();
7946
7947         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7948         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);
7949         R_SetViewport(&viewport);
7950         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7951         GL_Color(1, 1, 1, 1);
7952         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7953         GL_BlendFunc(GL_ONE, GL_ZERO);
7954         GL_ScissorTest(false);
7955         GL_DepthMask(false);
7956         GL_DepthRange(0, 1);
7957         GL_DepthTest(false);
7958         GL_DepthFunc(GL_LEQUAL);
7959         R_EntityMatrix(&identitymatrix);
7960         R_Mesh_ResetTextureState();
7961         GL_PolygonOffset(0, 0);
7962         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7963         switch(vid.renderpath)
7964         {
7965         case RENDERPATH_GL11:
7966         case RENDERPATH_GL13:
7967         case RENDERPATH_GL20:
7968         case RENDERPATH_GLES2:
7969                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7970                 break;
7971         case RENDERPATH_D3D9:
7972         case RENDERPATH_D3D10:
7973         case RENDERPATH_D3D11:
7974         case RENDERPATH_SOFT:
7975                 break;
7976         }
7977         GL_CullFace(GL_NONE);
7978 }
7979
7980 void R_ResetViewRendering3D(void)
7981 {
7982         DrawQ_Finish();
7983
7984         R_SetupView(true);
7985         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7986         GL_Color(1, 1, 1, 1);
7987         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7988         GL_BlendFunc(GL_ONE, GL_ZERO);
7989         GL_ScissorTest(true);
7990         GL_DepthMask(true);
7991         GL_DepthRange(0, 1);
7992         GL_DepthTest(true);
7993         GL_DepthFunc(GL_LEQUAL);
7994         R_EntityMatrix(&identitymatrix);
7995         R_Mesh_ResetTextureState();
7996         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7997         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7998         switch(vid.renderpath)
7999         {
8000         case RENDERPATH_GL11:
8001         case RENDERPATH_GL13:
8002         case RENDERPATH_GL20:
8003         case RENDERPATH_GLES2:
8004                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8005                 break;
8006         case RENDERPATH_D3D9:
8007         case RENDERPATH_D3D10:
8008         case RENDERPATH_D3D11:
8009         case RENDERPATH_SOFT:
8010                 break;
8011         }
8012         GL_CullFace(r_refdef.view.cullface_back);
8013 }
8014
8015 /*
8016 ================
8017 R_RenderView_UpdateViewVectors
8018 ================
8019 */
8020 static void R_RenderView_UpdateViewVectors(void)
8021 {
8022         // break apart the view matrix into vectors for various purposes
8023         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8024         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8025         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8026         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8027         // make an inverted copy of the view matrix for tracking sprites
8028         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8029 }
8030
8031 void R_RenderScene(void);
8032 void R_RenderWaterPlanes(void);
8033
8034 static void R_Water_StartFrame(void)
8035 {
8036         int i;
8037         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8038         r_waterstate_waterplane_t *p;
8039
8040         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8041                 return;
8042
8043         switch(vid.renderpath)
8044         {
8045         case RENDERPATH_GL20:
8046         case RENDERPATH_D3D9:
8047         case RENDERPATH_D3D10:
8048         case RENDERPATH_D3D11:
8049         case RENDERPATH_SOFT:
8050         case RENDERPATH_GLES2:
8051                 break;
8052         case RENDERPATH_GL13:
8053         case RENDERPATH_GL11:
8054                 return;
8055         }
8056
8057         // set waterwidth and waterheight to the water resolution that will be
8058         // used (often less than the screen resolution for faster rendering)
8059         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8060         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8061
8062         // calculate desired texture sizes
8063         // can't use water if the card does not support the texture size
8064         if (!r_water.integer || r_showsurfaces.integer)
8065                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8066         else if (vid.support.arb_texture_non_power_of_two)
8067         {
8068                 texturewidth = waterwidth;
8069                 textureheight = waterheight;
8070                 camerawidth = waterwidth;
8071                 cameraheight = waterheight;
8072         }
8073         else
8074         {
8075                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8076                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8077                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8078                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8079         }
8080
8081         // allocate textures as needed
8082         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8083         {
8084                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8085                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8086                 {
8087                         if (p->texture_refraction)
8088                                 R_FreeTexture(p->texture_refraction);
8089                         p->texture_refraction = NULL;
8090                         if (p->texture_reflection)
8091                                 R_FreeTexture(p->texture_reflection);
8092                         p->texture_reflection = NULL;
8093                         if (p->texture_camera)
8094                                 R_FreeTexture(p->texture_camera);
8095                         p->texture_camera = NULL;
8096                 }
8097                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8098                 r_waterstate.texturewidth = texturewidth;
8099                 r_waterstate.textureheight = textureheight;
8100                 r_waterstate.camerawidth = camerawidth;
8101                 r_waterstate.cameraheight = cameraheight;
8102         }
8103
8104         if (r_waterstate.texturewidth)
8105         {
8106                 r_waterstate.enabled = true;
8107
8108                 // when doing a reduced render (HDR) we want to use a smaller area
8109                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8110                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8111
8112                 // set up variables that will be used in shader setup
8113                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8114                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8115                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8116                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8117         }
8118
8119         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8120         r_waterstate.numwaterplanes = 0;
8121 }
8122
8123 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8124 {
8125         int triangleindex, planeindex;
8126         const int *e;
8127         vec3_t vert[3];
8128         vec3_t normal;
8129         vec3_t center;
8130         mplane_t plane;
8131         r_waterstate_waterplane_t *p;
8132         texture_t *t = R_GetCurrentTexture(surface->texture);
8133
8134         // just use the first triangle with a valid normal for any decisions
8135         VectorClear(normal);
8136         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8137         {
8138                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8139                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8140                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8141                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8142                 if (VectorLength2(normal) >= 0.001)
8143                         break;
8144         }
8145
8146         VectorCopy(normal, plane.normal);
8147         VectorNormalize(plane.normal);
8148         plane.dist = DotProduct(vert[0], plane.normal);
8149         PlaneClassify(&plane);
8150         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8151         {
8152                 // skip backfaces (except if nocullface is set)
8153                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8154                         return;
8155                 VectorNegate(plane.normal, plane.normal);
8156                 plane.dist *= -1;
8157                 PlaneClassify(&plane);
8158         }
8159
8160
8161         // find a matching plane if there is one
8162         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8163                 if(p->camera_entity == t->camera_entity)
8164                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8165                                 break;
8166         if (planeindex >= r_waterstate.maxwaterplanes)
8167                 return; // nothing we can do, out of planes
8168
8169         // if this triangle does not fit any known plane rendered this frame, add one
8170         if (planeindex >= r_waterstate.numwaterplanes)
8171         {
8172                 // store the new plane
8173                 r_waterstate.numwaterplanes++;
8174                 p->plane = plane;
8175                 // clear materialflags and pvs
8176                 p->materialflags = 0;
8177                 p->pvsvalid = false;
8178                 p->camera_entity = t->camera_entity;
8179                 VectorCopy(surface->mins, p->mins);
8180                 VectorCopy(surface->maxs, p->maxs);
8181         }
8182         else
8183         {
8184                 // merge mins/maxs
8185                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8186                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8187                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8188                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8189                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8190                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8191         }
8192         // merge this surface's materialflags into the waterplane
8193         p->materialflags |= t->currentmaterialflags;
8194         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8195         {
8196                 // merge this surface's PVS into the waterplane
8197                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8198                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8199                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8200                 {
8201                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8202                         p->pvsvalid = true;
8203                 }
8204         }
8205 }
8206
8207 static void R_Water_ProcessPlanes(void)
8208 {
8209         int myscissor[4];
8210         r_refdef_view_t originalview;
8211         r_refdef_view_t myview;
8212         int planeindex;
8213         r_waterstate_waterplane_t *p;
8214         vec3_t visorigin;
8215
8216         originalview = r_refdef.view;
8217
8218         // make sure enough textures are allocated
8219         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8220         {
8221                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8222                 {
8223                         if (!p->texture_refraction)
8224                                 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);
8225                         if (!p->texture_refraction)
8226                                 goto error;
8227                 }
8228                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8229                 {
8230                         if (!p->texture_camera)
8231                                 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);
8232                         if (!p->texture_camera)
8233                                 goto error;
8234                 }
8235
8236                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8237                 {
8238                         if (!p->texture_reflection)
8239                                 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);
8240                         if (!p->texture_reflection)
8241                                 goto error;
8242                 }
8243         }
8244
8245         // render views
8246         r_refdef.view = originalview;
8247         r_refdef.view.showdebug = false;
8248         r_refdef.view.width = r_waterstate.waterwidth;
8249         r_refdef.view.height = r_waterstate.waterheight;
8250         r_refdef.view.useclipplane = true;
8251         myview = r_refdef.view;
8252         r_waterstate.renderingscene = true;
8253         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8254         {
8255                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8256                 {
8257                         r_refdef.view = myview;
8258                         if(r_water_scissormode.integer)
8259                         {
8260                                 R_SetupView(true);
8261                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8262                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8263                         }
8264
8265                         // render reflected scene and copy into texture
8266                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8267                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8268                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8269                         r_refdef.view.clipplane = p->plane;
8270
8271                         // reverse the cullface settings for this render
8272                         r_refdef.view.cullface_front = GL_FRONT;
8273                         r_refdef.view.cullface_back = GL_BACK;
8274                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8275                         {
8276                                 r_refdef.view.usecustompvs = true;
8277                                 if (p->pvsvalid)
8278                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8279                                 else
8280                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8281                         }
8282
8283                         R_ResetViewRendering3D();
8284                         R_ClearScreen(r_refdef.fogenabled);
8285                         if(r_water_scissormode.integer & 2)
8286                                 R_View_UpdateWithScissor(myscissor);
8287                         else
8288                                 R_View_Update();
8289                         if(r_water_scissormode.integer & 1)
8290                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8291                         R_RenderScene();
8292
8293                         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);
8294                 }
8295
8296                 // render the normal view scene and copy into texture
8297                 // (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)
8298                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8299                 {
8300                         r_refdef.view = myview;
8301                         if(r_water_scissormode.integer)
8302                         {
8303                                 R_SetupView(true);
8304                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8305                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8306                         }
8307
8308                         r_waterstate.renderingrefraction = true;
8309
8310                         r_refdef.view.clipplane = p->plane;
8311                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8312                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8313
8314                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8315                         {
8316                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8317                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8318                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8319                                 R_RenderView_UpdateViewVectors();
8320                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8321                                 {
8322                                         r_refdef.view.usecustompvs = true;
8323                                         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);
8324                                 }
8325                         }
8326
8327                         PlaneClassify(&r_refdef.view.clipplane);
8328
8329                         R_ResetViewRendering3D();
8330                         R_ClearScreen(r_refdef.fogenabled);
8331                         if(r_water_scissormode.integer & 2)
8332                                 R_View_UpdateWithScissor(myscissor);
8333                         else
8334                                 R_View_Update();
8335                         if(r_water_scissormode.integer & 1)
8336                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8337                         R_RenderScene();
8338
8339                         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);
8340                         r_waterstate.renderingrefraction = false;
8341                 }
8342                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8343                 {
8344                         r_refdef.view = myview;
8345
8346                         r_refdef.view.clipplane = p->plane;
8347                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8348                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8349
8350                         r_refdef.view.width = r_waterstate.camerawidth;
8351                         r_refdef.view.height = r_waterstate.cameraheight;
8352                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8353                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8354
8355                         if(p->camera_entity)
8356                         {
8357                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8358                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8359                         }
8360
8361                         // note: all of the view is used for displaying... so
8362                         // there is no use in scissoring
8363
8364                         // reverse the cullface settings for this render
8365                         r_refdef.view.cullface_front = GL_FRONT;
8366                         r_refdef.view.cullface_back = GL_BACK;
8367                         // also reverse the view matrix
8368                         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
8369                         R_RenderView_UpdateViewVectors();
8370                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8371                         {
8372                                 r_refdef.view.usecustompvs = true;
8373                                 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);
8374                         }
8375                         
8376                         // camera needs no clipplane
8377                         r_refdef.view.useclipplane = false;
8378
8379                         PlaneClassify(&r_refdef.view.clipplane);
8380
8381                         R_ResetViewRendering3D();
8382                         R_ClearScreen(r_refdef.fogenabled);
8383                         R_View_Update();
8384                         R_RenderScene();
8385
8386                         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);
8387                         r_waterstate.renderingrefraction = false;
8388                 }
8389
8390         }
8391         r_waterstate.renderingscene = false;
8392         r_refdef.view = originalview;
8393         R_ResetViewRendering3D();
8394         R_ClearScreen(r_refdef.fogenabled);
8395         R_View_Update();
8396         return;
8397 error:
8398         r_refdef.view = originalview;
8399         r_waterstate.renderingscene = false;
8400         Cvar_SetValueQuick(&r_water, 0);
8401         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8402         return;
8403 }
8404
8405 void R_Bloom_StartFrame(void)
8406 {
8407         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8408
8409         switch(vid.renderpath)
8410         {
8411         case RENDERPATH_GL20:
8412         case RENDERPATH_D3D9:
8413         case RENDERPATH_D3D10:
8414         case RENDERPATH_D3D11:
8415         case RENDERPATH_SOFT:
8416         case RENDERPATH_GLES2:
8417                 break;
8418         case RENDERPATH_GL13:
8419         case RENDERPATH_GL11:
8420                 return;
8421         }
8422
8423         // set bloomwidth and bloomheight to the bloom resolution that will be
8424         // used (often less than the screen resolution for faster rendering)
8425         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8426         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8427         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8428         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8429         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8430
8431         // calculate desired texture sizes
8432         if (vid.support.arb_texture_non_power_of_two)
8433         {
8434                 screentexturewidth = r_refdef.view.width;
8435                 screentextureheight = r_refdef.view.height;
8436                 bloomtexturewidth = r_bloomstate.bloomwidth;
8437                 bloomtextureheight = r_bloomstate.bloomheight;
8438         }
8439         else
8440         {
8441                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8442                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8443                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8444                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8445         }
8446
8447         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))
8448         {
8449                 Cvar_SetValueQuick(&r_hdr, 0);
8450                 Cvar_SetValueQuick(&r_bloom, 0);
8451                 Cvar_SetValueQuick(&r_motionblur, 0);
8452                 Cvar_SetValueQuick(&r_damageblur, 0);
8453         }
8454
8455         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)))
8456                 screentexturewidth = screentextureheight = 0;
8457         if (!r_hdr.integer && !r_bloom.integer)
8458                 bloomtexturewidth = bloomtextureheight = 0;
8459
8460         // allocate textures as needed
8461         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8462         {
8463                 if (r_bloomstate.texture_screen)
8464                         R_FreeTexture(r_bloomstate.texture_screen);
8465                 r_bloomstate.texture_screen = NULL;
8466                 r_bloomstate.screentexturewidth = screentexturewidth;
8467                 r_bloomstate.screentextureheight = screentextureheight;
8468                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8469                         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);
8470         }
8471         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8472         {
8473                 if (r_bloomstate.texture_bloom)
8474                         R_FreeTexture(r_bloomstate.texture_bloom);
8475                 r_bloomstate.texture_bloom = NULL;
8476                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8477                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8478                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8479                         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);
8480         }
8481
8482         // when doing a reduced render (HDR) we want to use a smaller area
8483         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8484         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8485         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8486         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8487         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8488
8489         // set up a texcoord array for the full resolution screen image
8490         // (we have to keep this around to copy back during final render)
8491         r_bloomstate.screentexcoord2f[0] = 0;
8492         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8493         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8494         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8495         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8496         r_bloomstate.screentexcoord2f[5] = 0;
8497         r_bloomstate.screentexcoord2f[6] = 0;
8498         r_bloomstate.screentexcoord2f[7] = 0;
8499
8500         // set up a texcoord array for the reduced resolution bloom image
8501         // (which will be additive blended over the screen image)
8502         r_bloomstate.bloomtexcoord2f[0] = 0;
8503         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8504         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8505         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8506         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8507         r_bloomstate.bloomtexcoord2f[5] = 0;
8508         r_bloomstate.bloomtexcoord2f[6] = 0;
8509         r_bloomstate.bloomtexcoord2f[7] = 0;
8510
8511         switch(vid.renderpath)
8512         {
8513         case RENDERPATH_GL11:
8514         case RENDERPATH_GL13:
8515         case RENDERPATH_GL20:
8516         case RENDERPATH_SOFT:
8517         case RENDERPATH_GLES2:
8518                 break;
8519         case RENDERPATH_D3D9:
8520         case RENDERPATH_D3D10:
8521         case RENDERPATH_D3D11:
8522                 {
8523                         int i;
8524                         for (i = 0;i < 4;i++)
8525                         {
8526                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8527                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8528                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8529                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8530                         }
8531                 }
8532                 break;
8533         }
8534
8535         if (r_hdr.integer || r_bloom.integer)
8536         {
8537                 r_bloomstate.enabled = true;
8538                 r_bloomstate.hdr = r_hdr.integer != 0;
8539         }
8540
8541         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);
8542 }
8543
8544 void R_Bloom_CopyBloomTexture(float colorscale)
8545 {
8546         r_refdef.stats.bloom++;
8547
8548         // scale down screen texture to the bloom texture size
8549         CHECKGLERROR
8550         R_SetViewport(&r_bloomstate.viewport);
8551         GL_BlendFunc(GL_ONE, GL_ZERO);
8552         GL_Color(colorscale, colorscale, colorscale, 1);
8553         // 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...
8554         switch(vid.renderpath)
8555         {
8556         case RENDERPATH_GL11:
8557         case RENDERPATH_GL13:
8558         case RENDERPATH_GL20:
8559         case RENDERPATH_SOFT:
8560         case RENDERPATH_GLES2:
8561                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8562                 break;
8563         case RENDERPATH_D3D9:
8564         case RENDERPATH_D3D10:
8565         case RENDERPATH_D3D11:
8566                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8567                 break;
8568         }
8569         // TODO: do boxfilter scale-down in shader?
8570         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8571         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8572         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8573
8574         // we now have a bloom image in the framebuffer
8575         // copy it into the bloom image texture for later processing
8576         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);
8577         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8578 }
8579
8580 void R_Bloom_CopyHDRTexture(void)
8581 {
8582         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);
8583         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8584 }
8585
8586 void R_Bloom_MakeTexture(void)
8587 {
8588         int x, range, dir;
8589         float xoffset, yoffset, r, brighten;
8590
8591         r_refdef.stats.bloom++;
8592
8593         R_ResetViewRendering2D();
8594
8595         // we have a bloom image in the framebuffer
8596         CHECKGLERROR
8597         R_SetViewport(&r_bloomstate.viewport);
8598
8599         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8600         {
8601                 x *= 2;
8602                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8603                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8604                 GL_Color(r,r,r,1);
8605                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8606                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8607                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8608                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8609
8610                 // copy the vertically blurred bloom view to a texture
8611                 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);
8612                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8613         }
8614
8615         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8616         brighten = r_bloom_brighten.value;
8617         if (r_hdr.integer)
8618                 brighten *= r_hdr_range.value;
8619         brighten = sqrt(brighten);
8620         if(range >= 1)
8621                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8622         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8623
8624         for (dir = 0;dir < 2;dir++)
8625         {
8626                 // blend on at multiple vertical offsets to achieve a vertical blur
8627                 // TODO: do offset blends using GLSL
8628                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8629                 GL_BlendFunc(GL_ONE, GL_ZERO);
8630                 for (x = -range;x <= range;x++)
8631                 {
8632                         if (!dir){xoffset = 0;yoffset = x;}
8633                         else {xoffset = x;yoffset = 0;}
8634                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8635                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8636                         // compute a texcoord array with the specified x and y offset
8637                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8638                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8639                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8640                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8641                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8642                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8643                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8644                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8645                         // this r value looks like a 'dot' particle, fading sharply to
8646                         // black at the edges
8647                         // (probably not realistic but looks good enough)
8648                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8649                         //r = brighten/(range*2+1);
8650                         r = brighten / (range * 2 + 1);
8651                         if(range >= 1)
8652                                 r *= (1 - x*x/(float)(range*range));
8653                         GL_Color(r, r, r, 1);
8654                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8655                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8656                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8657                         GL_BlendFunc(GL_ONE, GL_ONE);
8658                 }
8659
8660                 // copy the vertically blurred bloom view to a texture
8661                 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);
8662                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8663         }
8664 }
8665
8666 void R_HDR_RenderBloomTexture(void)
8667 {
8668         int oldwidth, oldheight;
8669         float oldcolorscale;
8670         qboolean oldwaterstate;
8671
8672         oldwaterstate = r_waterstate.enabled;
8673         oldcolorscale = r_refdef.view.colorscale;
8674         oldwidth = r_refdef.view.width;
8675         oldheight = r_refdef.view.height;
8676         r_refdef.view.width = r_bloomstate.bloomwidth;
8677         r_refdef.view.height = r_bloomstate.bloomheight;
8678
8679         if(r_hdr.integer < 2)
8680                 r_waterstate.enabled = false;
8681
8682         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8683         // TODO: add exposure compensation features
8684         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8685
8686         r_refdef.view.showdebug = false;
8687         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8688
8689         R_ResetViewRendering3D();
8690
8691         R_ClearScreen(r_refdef.fogenabled);
8692         if (r_timereport_active)
8693                 R_TimeReport("HDRclear");
8694
8695         R_View_Update();
8696         if (r_timereport_active)
8697                 R_TimeReport("visibility");
8698
8699         // only do secondary renders with HDR if r_hdr is 2 or higher
8700         r_waterstate.numwaterplanes = 0;
8701         if (r_waterstate.enabled)
8702                 R_RenderWaterPlanes();
8703
8704         r_refdef.view.showdebug = true;
8705         R_RenderScene();
8706         r_waterstate.numwaterplanes = 0;
8707
8708         R_ResetViewRendering2D();
8709
8710         R_Bloom_CopyHDRTexture();
8711         R_Bloom_MakeTexture();
8712
8713         // restore the view settings
8714         r_waterstate.enabled = oldwaterstate;
8715         r_refdef.view.width = oldwidth;
8716         r_refdef.view.height = oldheight;
8717         r_refdef.view.colorscale = oldcolorscale;
8718
8719         R_ResetViewRendering3D();
8720
8721         R_ClearScreen(r_refdef.fogenabled);
8722         if (r_timereport_active)
8723                 R_TimeReport("viewclear");
8724 }
8725
8726 static void R_BlendView(void)
8727 {
8728         unsigned int permutation;
8729         float uservecs[4][4];
8730
8731         switch (vid.renderpath)
8732         {
8733         case RENDERPATH_GL20:
8734         case RENDERPATH_D3D9:
8735         case RENDERPATH_D3D10:
8736         case RENDERPATH_D3D11:
8737         case RENDERPATH_SOFT:
8738         case RENDERPATH_GLES2:
8739                 permutation =
8740                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8741                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8742                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8743                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8744                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8745
8746                 if (r_bloomstate.texture_screen)
8747                 {
8748                         // make sure the buffer is available
8749                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8750
8751                         R_ResetViewRendering2D();
8752
8753                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8754                         {
8755                                 // declare variables
8756                                 float speed;
8757                                 static float avgspeed;
8758
8759                                 speed = VectorLength(cl.movement_velocity);
8760
8761                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8762                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8763
8764                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8765                                 speed = bound(0, speed, 1);
8766                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8767
8768                                 // calculate values into a standard alpha
8769                                 cl.motionbluralpha = 1 - exp(-
8770                                                 (
8771                                                  (r_motionblur.value * speed / 80)
8772                                                  +
8773                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8774                                                 )
8775                                                 /
8776                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8777                                            );
8778
8779                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8780                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8781                                 // apply the blur
8782                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8783                                 {
8784                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8785                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8786                                         switch(vid.renderpath)
8787                                         {
8788                                         case RENDERPATH_GL11:
8789                                         case RENDERPATH_GL13:
8790                                         case RENDERPATH_GL20:
8791                                         case RENDERPATH_SOFT:
8792                                         case RENDERPATH_GLES2:
8793                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8794                                                 break;
8795                                         case RENDERPATH_D3D9:
8796                                         case RENDERPATH_D3D10:
8797                                         case RENDERPATH_D3D11:
8798                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8799                                                 break;
8800                                         }
8801                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8802                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8803                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8804                                 }
8805                         }
8806
8807                         // copy view into the screen texture
8808                         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);
8809                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8810                 }
8811                 else if (!r_bloomstate.texture_bloom)
8812                 {
8813                         // we may still have to do view tint...
8814                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8815                         {
8816                                 // apply a color tint to the whole view
8817                                 R_ResetViewRendering2D();
8818                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8819                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8820                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8821                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8822                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8823                         }
8824                         break; // no screen processing, no bloom, skip it
8825                 }
8826
8827                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8828                 {
8829                         // render simple bloom effect
8830                         // copy the screen and shrink it and darken it for the bloom process
8831                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8832                         // make the bloom texture
8833                         R_Bloom_MakeTexture();
8834                 }
8835
8836 #if _MSC_VER >= 1400
8837 #define sscanf sscanf_s
8838 #endif
8839                 memset(uservecs, 0, sizeof(uservecs));
8840                 if (r_glsl_postprocess_uservec1_enable.integer)
8841                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8842                 if (r_glsl_postprocess_uservec2_enable.integer)
8843                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8844                 if (r_glsl_postprocess_uservec3_enable.integer)
8845                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8846                 if (r_glsl_postprocess_uservec4_enable.integer)
8847                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8848
8849                 R_ResetViewRendering2D();
8850                 GL_Color(1, 1, 1, 1);
8851                 GL_BlendFunc(GL_ONE, GL_ZERO);
8852
8853                 switch(vid.renderpath)
8854                 {
8855                 case RENDERPATH_GL20:
8856                 case RENDERPATH_GLES2:
8857                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8858                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8859                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
8860                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
8861                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
8862                         if (r_glsl_permutation->loc_ViewTintColor           >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8863                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8864                         if (r_glsl_permutation->loc_UserVec1                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8865                         if (r_glsl_permutation->loc_UserVec2                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8866                         if (r_glsl_permutation->loc_UserVec3                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8867                         if (r_glsl_permutation->loc_UserVec4                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8868                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8869                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8870                         if (r_glsl_permutation->loc_BloomColorSubtract      >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8871                         break;
8872                 case RENDERPATH_D3D9:
8873 #ifdef SUPPORTD3D
8874                         // 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...
8875                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8876                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8877                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8878                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8879                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8880                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8881                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8882                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8883                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8884                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8885                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8886                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
8887                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8888                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8889 #endif
8890                         break;
8891                 case RENDERPATH_D3D10:
8892                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8893                         break;
8894                 case RENDERPATH_D3D11:
8895                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8896                         break;
8897                 case RENDERPATH_SOFT:
8898                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8899                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8900                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8901                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8902                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8903                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8904                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8905                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8906                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8907                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8908                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8909                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
8910                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8911                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8912                         break;
8913                 default:
8914                         break;
8915                 }
8916                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8917                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8918                 break;
8919         case RENDERPATH_GL13:
8920         case RENDERPATH_GL11:
8921                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8922                 {
8923                         // apply a color tint to the whole view
8924                         R_ResetViewRendering2D();
8925                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8926                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8927                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8928                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8929                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8930                 }
8931                 break;
8932         }
8933 }
8934
8935 matrix4x4_t r_waterscrollmatrix;
8936
8937 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8938 {
8939         if (r_refdef.fog_density)
8940         {
8941                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8942                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8943                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8944
8945                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8946                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8947                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8948                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8949
8950                 {
8951                         vec3_t fogvec;
8952                         VectorCopy(r_refdef.fogcolor, fogvec);
8953                         //   color.rgb *= ContrastBoost * SceneBrightness;
8954                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8955                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8956                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8957                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8958                 }
8959         }
8960 }
8961
8962 void R_UpdateVariables(void)
8963 {
8964         R_Textures_Frame();
8965
8966         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8967
8968         r_refdef.farclip = r_farclip_base.value;
8969         if (r_refdef.scene.worldmodel)
8970                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8971         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8972
8973         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8974                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8975         r_refdef.polygonfactor = 0;
8976         r_refdef.polygonoffset = 0;
8977         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8978         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8979
8980         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8981         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8982         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
8983         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8984         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8985         if (FAKELIGHT_ENABLED)
8986         {
8987                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8988         }
8989         if (r_showsurfaces.integer)
8990         {
8991                 r_refdef.scene.rtworld = false;
8992                 r_refdef.scene.rtworldshadows = false;
8993                 r_refdef.scene.rtdlight = false;
8994                 r_refdef.scene.rtdlightshadows = false;
8995                 r_refdef.lightmapintensity = 0;
8996         }
8997
8998         if (gamemode == GAME_NEHAHRA)
8999         {
9000                 if (gl_fogenable.integer)
9001                 {
9002                         r_refdef.oldgl_fogenable = true;
9003                         r_refdef.fog_density = gl_fogdensity.value;
9004                         r_refdef.fog_red = gl_fogred.value;
9005                         r_refdef.fog_green = gl_foggreen.value;
9006                         r_refdef.fog_blue = gl_fogblue.value;
9007                         r_refdef.fog_alpha = 1;
9008                         r_refdef.fog_start = 0;
9009                         r_refdef.fog_end = gl_skyclip.value;
9010                         r_refdef.fog_height = 1<<30;
9011                         r_refdef.fog_fadedepth = 128;
9012                 }
9013                 else if (r_refdef.oldgl_fogenable)
9014                 {
9015                         r_refdef.oldgl_fogenable = false;
9016                         r_refdef.fog_density = 0;
9017                         r_refdef.fog_red = 0;
9018                         r_refdef.fog_green = 0;
9019                         r_refdef.fog_blue = 0;
9020                         r_refdef.fog_alpha = 0;
9021                         r_refdef.fog_start = 0;
9022                         r_refdef.fog_end = 0;
9023                         r_refdef.fog_height = 1<<30;
9024                         r_refdef.fog_fadedepth = 128;
9025                 }
9026         }
9027
9028         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9029         r_refdef.fog_start = max(0, r_refdef.fog_start);
9030         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9031
9032         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9033
9034         if (r_refdef.fog_density && r_drawfog.integer)
9035         {
9036                 r_refdef.fogenabled = true;
9037                 // this is the point where the fog reaches 0.9986 alpha, which we
9038                 // consider a good enough cutoff point for the texture
9039                 // (0.9986 * 256 == 255.6)
9040                 if (r_fog_exp2.integer)
9041                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9042                 else
9043                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9044                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9045                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9046                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9047                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9048                         R_BuildFogHeightTexture();
9049                 // fog color was already set
9050                 // update the fog texture
9051                 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)
9052                         R_BuildFogTexture();
9053                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9054                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9055         }
9056         else
9057                 r_refdef.fogenabled = false;
9058
9059         switch(vid.renderpath)
9060         {
9061         case RENDERPATH_GL20:
9062         case RENDERPATH_D3D9:
9063         case RENDERPATH_D3D10:
9064         case RENDERPATH_D3D11:
9065         case RENDERPATH_SOFT:
9066         case RENDERPATH_GLES2:
9067                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9068                 {
9069                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9070                         {
9071                                 // build GLSL gamma texture
9072 #define RAMPWIDTH 256
9073                                 unsigned short ramp[RAMPWIDTH * 3];
9074                                 unsigned char rampbgr[RAMPWIDTH][4];
9075                                 int i;
9076
9077                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9078
9079                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9080                                 for(i = 0; i < RAMPWIDTH; ++i)
9081                                 {
9082                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9083                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9084                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9085                                         rampbgr[i][3] = 0;
9086                                 }
9087                                 if (r_texture_gammaramps)
9088                                 {
9089                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
9090                                 }
9091                                 else
9092                                 {
9093                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9094                                 }
9095                         }
9096                 }
9097                 else
9098                 {
9099                         // remove GLSL gamma texture
9100                 }
9101                 break;
9102         case RENDERPATH_GL13:
9103         case RENDERPATH_GL11:
9104                 break;
9105         }
9106 }
9107
9108 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9109 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9110 /*
9111 ================
9112 R_SelectScene
9113 ================
9114 */
9115 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9116         if( scenetype != r_currentscenetype ) {
9117                 // store the old scenetype
9118                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9119                 r_currentscenetype = scenetype;
9120                 // move in the new scene
9121                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9122         }
9123 }
9124
9125 /*
9126 ================
9127 R_GetScenePointer
9128 ================
9129 */
9130 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9131 {
9132         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9133         if( scenetype == r_currentscenetype ) {
9134                 return &r_refdef.scene;
9135         } else {
9136                 return &r_scenes_store[ scenetype ];
9137         }
9138 }
9139
9140 /*
9141 ================
9142 R_RenderView
9143 ================
9144 */
9145 int dpsoftrast_test;
9146 void R_RenderView(void)
9147 {
9148         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9149
9150         dpsoftrast_test = r_test.integer;
9151
9152         if (r_timereport_active)
9153                 R_TimeReport("start");
9154         r_textureframe++; // used only by R_GetCurrentTexture
9155         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9156
9157         if(R_CompileShader_CheckStaticParms())
9158                 R_GLSL_Restart_f();
9159
9160         if (!r_drawentities.integer)
9161                 r_refdef.scene.numentities = 0;
9162
9163         R_AnimCache_ClearCache();
9164         R_FrameData_NewFrame();
9165
9166         /* adjust for stereo display */
9167         if(R_Stereo_Active())
9168         {
9169                 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);
9170                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9171         }
9172
9173         if (r_refdef.view.isoverlay)
9174         {
9175                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9176                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9177                 R_TimeReport("depthclear");
9178
9179                 r_refdef.view.showdebug = false;
9180
9181                 r_waterstate.enabled = false;
9182                 r_waterstate.numwaterplanes = 0;
9183
9184                 R_RenderScene();
9185
9186                 r_refdef.view.matrix = originalmatrix;
9187
9188                 CHECKGLERROR
9189                 return;
9190         }
9191
9192         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9193         {
9194                 r_refdef.view.matrix = originalmatrix;
9195                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9196         }
9197
9198         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9199
9200         R_RenderView_UpdateViewVectors();
9201
9202         R_Shadow_UpdateWorldLightSelection();
9203
9204         R_Bloom_StartFrame();
9205         R_Water_StartFrame();
9206
9207         CHECKGLERROR
9208         if (r_timereport_active)
9209                 R_TimeReport("viewsetup");
9210
9211         R_ResetViewRendering3D();
9212
9213         if (r_refdef.view.clear || r_refdef.fogenabled)
9214         {
9215                 R_ClearScreen(r_refdef.fogenabled);
9216                 if (r_timereport_active)
9217                         R_TimeReport("viewclear");
9218         }
9219         r_refdef.view.clear = true;
9220
9221         // this produces a bloom texture to be used in R_BlendView() later
9222         if (r_hdr.integer && r_bloomstate.bloomwidth)
9223         {
9224                 R_HDR_RenderBloomTexture();
9225                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9226                 r_textureframe++; // used only by R_GetCurrentTexture
9227         }
9228
9229         r_refdef.view.showdebug = true;
9230
9231         R_View_Update();
9232         if (r_timereport_active)
9233                 R_TimeReport("visibility");
9234
9235         r_waterstate.numwaterplanes = 0;
9236         if (r_waterstate.enabled)
9237                 R_RenderWaterPlanes();
9238
9239         R_RenderScene();
9240         r_waterstate.numwaterplanes = 0;
9241
9242         R_BlendView();
9243         if (r_timereport_active)
9244                 R_TimeReport("blendview");
9245
9246         GL_Scissor(0, 0, vid.width, vid.height);
9247         GL_ScissorTest(false);
9248
9249         r_refdef.view.matrix = originalmatrix;
9250
9251         CHECKGLERROR
9252 }
9253
9254 void R_RenderWaterPlanes(void)
9255 {
9256         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9257         {
9258                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9259                 if (r_timereport_active)
9260                         R_TimeReport("waterworld");
9261         }
9262
9263         // don't let sound skip if going slow
9264         if (r_refdef.scene.extraupdate)
9265                 S_ExtraUpdate ();
9266
9267         R_DrawModelsAddWaterPlanes();
9268         if (r_timereport_active)
9269                 R_TimeReport("watermodels");
9270
9271         if (r_waterstate.numwaterplanes)
9272         {
9273                 R_Water_ProcessPlanes();
9274                 if (r_timereport_active)
9275                         R_TimeReport("waterscenes");
9276         }
9277 }
9278
9279 extern void R_DrawLightningBeams (void);
9280 extern void VM_CL_AddPolygonsToMeshQueue (void);
9281 extern void R_DrawPortals (void);
9282 extern cvar_t cl_locs_show;
9283 static void R_DrawLocs(void);
9284 static void R_DrawEntityBBoxes(void);
9285 static void R_DrawModelDecals(void);
9286 extern void R_DrawModelShadows(void);
9287 extern void R_DrawModelShadowMaps(void);
9288 extern cvar_t cl_decals_newsystem;
9289 extern qboolean r_shadow_usingdeferredprepass;
9290 void R_RenderScene(void)
9291 {
9292         qboolean shadowmapping = false;
9293
9294         if (r_timereport_active)
9295                 R_TimeReport("beginscene");
9296
9297         r_refdef.stats.renders++;
9298
9299         R_UpdateFogColor();
9300
9301         // don't let sound skip if going slow
9302         if (r_refdef.scene.extraupdate)
9303                 S_ExtraUpdate ();
9304
9305         R_MeshQueue_BeginScene();
9306
9307         R_SkyStartFrame();
9308
9309         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);
9310
9311         if (r_timereport_active)
9312                 R_TimeReport("skystartframe");
9313
9314         if (cl.csqc_vidvars.drawworld)
9315         {
9316                 // don't let sound skip if going slow
9317                 if (r_refdef.scene.extraupdate)
9318                         S_ExtraUpdate ();
9319
9320                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9321                 {
9322                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9323                         if (r_timereport_active)
9324                                 R_TimeReport("worldsky");
9325                 }
9326
9327                 if (R_DrawBrushModelsSky() && r_timereport_active)
9328                         R_TimeReport("bmodelsky");
9329
9330                 if (skyrendermasked && skyrenderlater)
9331                 {
9332                         // we have to force off the water clipping plane while rendering sky
9333                         R_SetupView(false);
9334                         R_Sky();
9335                         R_SetupView(true);
9336                         if (r_timereport_active)
9337                                 R_TimeReport("sky");
9338                 }
9339         }
9340
9341         R_AnimCache_CacheVisibleEntities();
9342         if (r_timereport_active)
9343                 R_TimeReport("animation");
9344
9345         R_Shadow_PrepareLights();
9346         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9347                 R_Shadow_PrepareModelShadows();
9348         if (r_timereport_active)
9349                 R_TimeReport("preparelights");
9350
9351         if (R_Shadow_ShadowMappingEnabled())
9352                 shadowmapping = true;
9353
9354         if (r_shadow_usingdeferredprepass)
9355                 R_Shadow_DrawPrepass();
9356
9357         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9358         {
9359                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9360                 if (r_timereport_active)
9361                         R_TimeReport("worlddepth");
9362         }
9363         if (r_depthfirst.integer >= 2)
9364         {
9365                 R_DrawModelsDepth();
9366                 if (r_timereport_active)
9367                         R_TimeReport("modeldepth");
9368         }
9369
9370         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9371         {
9372                 R_DrawModelShadowMaps();
9373                 R_ResetViewRendering3D();
9374                 // don't let sound skip if going slow
9375                 if (r_refdef.scene.extraupdate)
9376                         S_ExtraUpdate ();
9377         }
9378
9379         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9380         {
9381                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9382                 if (r_timereport_active)
9383                         R_TimeReport("world");
9384         }
9385
9386         // don't let sound skip if going slow
9387         if (r_refdef.scene.extraupdate)
9388                 S_ExtraUpdate ();
9389
9390         R_DrawModels();
9391         if (r_timereport_active)
9392                 R_TimeReport("models");
9393
9394         // don't let sound skip if going slow
9395         if (r_refdef.scene.extraupdate)
9396                 S_ExtraUpdate ();
9397
9398         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9399         {
9400                 R_DrawModelShadows();
9401                 R_ResetViewRendering3D();
9402                 // don't let sound skip if going slow
9403                 if (r_refdef.scene.extraupdate)
9404                         S_ExtraUpdate ();
9405         }
9406
9407         if (!r_shadow_usingdeferredprepass)
9408         {
9409                 R_Shadow_DrawLights();
9410                 if (r_timereport_active)
9411                         R_TimeReport("rtlights");
9412         }
9413
9414         // don't let sound skip if going slow
9415         if (r_refdef.scene.extraupdate)
9416                 S_ExtraUpdate ();
9417
9418         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9419         {
9420                 R_DrawModelShadows();
9421                 R_ResetViewRendering3D();
9422                 // don't let sound skip if going slow
9423                 if (r_refdef.scene.extraupdate)
9424                         S_ExtraUpdate ();
9425         }
9426
9427         if (cl.csqc_vidvars.drawworld)
9428         {
9429                 if (cl_decals_newsystem.integer)
9430                 {
9431                         R_DrawModelDecals();
9432                         if (r_timereport_active)
9433                                 R_TimeReport("modeldecals");
9434                 }
9435                 else
9436                 {
9437                         R_DrawDecals();
9438                         if (r_timereport_active)
9439                                 R_TimeReport("decals");
9440                 }
9441
9442                 R_DrawParticles();
9443                 if (r_timereport_active)
9444                         R_TimeReport("particles");
9445
9446                 R_DrawExplosions();
9447                 if (r_timereport_active)
9448                         R_TimeReport("explosions");
9449
9450                 R_DrawLightningBeams();
9451                 if (r_timereport_active)
9452                         R_TimeReport("lightning");
9453         }
9454
9455         VM_CL_AddPolygonsToMeshQueue();
9456
9457         if (r_refdef.view.showdebug)
9458         {
9459                 if (cl_locs_show.integer)
9460                 {
9461                         R_DrawLocs();
9462                         if (r_timereport_active)
9463                                 R_TimeReport("showlocs");
9464                 }
9465
9466                 if (r_drawportals.integer)
9467                 {
9468                         R_DrawPortals();
9469                         if (r_timereport_active)
9470                                 R_TimeReport("portals");
9471                 }
9472
9473                 if (r_showbboxes.value > 0)
9474                 {
9475                         R_DrawEntityBBoxes();
9476                         if (r_timereport_active)
9477                                 R_TimeReport("bboxes");
9478                 }
9479         }
9480
9481         R_MeshQueue_RenderTransparent();
9482         if (r_timereport_active)
9483                 R_TimeReport("drawtrans");
9484
9485         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))
9486         {
9487                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9488                 if (r_timereport_active)
9489                         R_TimeReport("worlddebug");
9490                 R_DrawModelsDebug();
9491                 if (r_timereport_active)
9492                         R_TimeReport("modeldebug");
9493         }
9494
9495         if (cl.csqc_vidvars.drawworld)
9496         {
9497                 R_Shadow_DrawCoronas();
9498                 if (r_timereport_active)
9499                         R_TimeReport("coronas");
9500         }
9501
9502 #if 0
9503         {
9504                 GL_DepthTest(false);
9505                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9506                 GL_Color(1, 1, 1, 1);
9507                 qglBegin(GL_POLYGON);
9508                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9509                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9510                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9511                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9512                 qglEnd();
9513                 qglBegin(GL_POLYGON);
9514                 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]);
9515                 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]);
9516                 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]);
9517                 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]);
9518                 qglEnd();
9519                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9520         }
9521 #endif
9522
9523         // don't let sound skip if going slow
9524         if (r_refdef.scene.extraupdate)
9525                 S_ExtraUpdate ();
9526
9527         R_ResetViewRendering2D();
9528 }
9529
9530 static const unsigned short bboxelements[36] =
9531 {
9532         5, 1, 3, 5, 3, 7,
9533         6, 2, 0, 6, 0, 4,
9534         7, 3, 2, 7, 2, 6,
9535         4, 0, 1, 4, 1, 5,
9536         4, 5, 7, 4, 7, 6,
9537         1, 0, 2, 1, 2, 3,
9538 };
9539
9540 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9541 {
9542         int i;
9543         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9544
9545         RSurf_ActiveWorldEntity();
9546
9547         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9548         GL_DepthMask(false);
9549         GL_DepthRange(0, 1);
9550         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9551 //      R_Mesh_ResetTextureState();
9552
9553         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9554         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9555         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9556         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9557         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9558         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9559         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9560         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9561         R_FillColors(color4f, 8, cr, cg, cb, ca);
9562         if (r_refdef.fogenabled)
9563         {
9564                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9565                 {
9566                         f1 = RSurf_FogVertex(v);
9567                         f2 = 1 - f1;
9568                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9569                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9570                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9571                 }
9572         }
9573         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9574         R_Mesh_ResetTextureState();
9575         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9576         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9577 }
9578
9579 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9580 {
9581         int i;
9582         float color[4];
9583         prvm_edict_t *edict;
9584         prvm_prog_t *prog_save = prog;
9585
9586         // this function draws bounding boxes of server entities
9587         if (!sv.active)
9588                 return;
9589
9590         GL_CullFace(GL_NONE);
9591         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9592
9593         prog = 0;
9594         SV_VM_Begin();
9595         for (i = 0;i < numsurfaces;i++)
9596         {
9597                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9598                 switch ((int)edict->fields.server->solid)
9599                 {
9600                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9601                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9602                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9603                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9604                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9605                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9606                 }
9607                 color[3] *= r_showbboxes.value;
9608                 color[3] = bound(0, color[3], 1);
9609                 GL_DepthTest(!r_showdisabledepthtest.integer);
9610                 GL_CullFace(r_refdef.view.cullface_front);
9611                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9612         }
9613         SV_VM_End();
9614         prog = prog_save;
9615 }
9616
9617 static void R_DrawEntityBBoxes(void)
9618 {
9619         int i;
9620         prvm_edict_t *edict;
9621         vec3_t center;
9622         prvm_prog_t *prog_save = prog;
9623
9624         // this function draws bounding boxes of server entities
9625         if (!sv.active)
9626                 return;
9627
9628         prog = 0;
9629         SV_VM_Begin();
9630         for (i = 0;i < prog->num_edicts;i++)
9631         {
9632                 edict = PRVM_EDICT_NUM(i);
9633                 if (edict->priv.server->free)
9634                         continue;
9635                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9636                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9637                         continue;
9638                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9639                         continue;
9640                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9641                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9642         }
9643         SV_VM_End();
9644         prog = prog_save;
9645 }
9646
9647 static const int nomodelelement3i[24] =
9648 {
9649         5, 2, 0,
9650         5, 1, 2,
9651         5, 0, 3,
9652         5, 3, 1,
9653         0, 2, 4,
9654         2, 1, 4,
9655         3, 0, 4,
9656         1, 3, 4
9657 };
9658
9659 static const unsigned short nomodelelement3s[24] =
9660 {
9661         5, 2, 0,
9662         5, 1, 2,
9663         5, 0, 3,
9664         5, 3, 1,
9665         0, 2, 4,
9666         2, 1, 4,
9667         3, 0, 4,
9668         1, 3, 4
9669 };
9670
9671 static const float nomodelvertex3f[6*3] =
9672 {
9673         -16,   0,   0,
9674          16,   0,   0,
9675           0, -16,   0,
9676           0,  16,   0,
9677           0,   0, -16,
9678           0,   0,  16
9679 };
9680
9681 static const float nomodelcolor4f[6*4] =
9682 {
9683         0.0f, 0.0f, 0.5f, 1.0f,
9684         0.0f, 0.0f, 0.5f, 1.0f,
9685         0.0f, 0.5f, 0.0f, 1.0f,
9686         0.0f, 0.5f, 0.0f, 1.0f,
9687         0.5f, 0.0f, 0.0f, 1.0f,
9688         0.5f, 0.0f, 0.0f, 1.0f
9689 };
9690
9691 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9692 {
9693         int i;
9694         float f1, f2, *c;
9695         float color4f[6*4];
9696
9697         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);
9698
9699         // this is only called once per entity so numsurfaces is always 1, and
9700         // surfacelist is always {0}, so this code does not handle batches
9701
9702         if (rsurface.ent_flags & RENDER_ADDITIVE)
9703         {
9704                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9705                 GL_DepthMask(false);
9706         }
9707         else if (rsurface.colormod[3] < 1)
9708         {
9709                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9710                 GL_DepthMask(false);
9711         }
9712         else
9713         {
9714                 GL_BlendFunc(GL_ONE, GL_ZERO);
9715                 GL_DepthMask(true);
9716         }
9717         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9718         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9719         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9720         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9721         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9722         for (i = 0, c = color4f;i < 6;i++, c += 4)
9723         {
9724                 c[0] *= rsurface.colormod[0];
9725                 c[1] *= rsurface.colormod[1];
9726                 c[2] *= rsurface.colormod[2];
9727                 c[3] *= rsurface.colormod[3];
9728         }
9729         if (r_refdef.fogenabled)
9730         {
9731                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9732                 {
9733                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9734                         f2 = 1 - f1;
9735                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9736                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9737                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9738                 }
9739         }
9740 //      R_Mesh_ResetTextureState();
9741         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9742         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9743         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9744 }
9745
9746 void R_DrawNoModel(entity_render_t *ent)
9747 {
9748         vec3_t org;
9749         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9750         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9751                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9752         else
9753                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9754 }
9755
9756 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9757 {
9758         vec3_t right1, right2, diff, normal;
9759
9760         VectorSubtract (org2, org1, normal);
9761
9762         // calculate 'right' vector for start
9763         VectorSubtract (r_refdef.view.origin, org1, diff);
9764         CrossProduct (normal, diff, right1);
9765         VectorNormalize (right1);
9766
9767         // calculate 'right' vector for end
9768         VectorSubtract (r_refdef.view.origin, org2, diff);
9769         CrossProduct (normal, diff, right2);
9770         VectorNormalize (right2);
9771
9772         vert[ 0] = org1[0] + width * right1[0];
9773         vert[ 1] = org1[1] + width * right1[1];
9774         vert[ 2] = org1[2] + width * right1[2];
9775         vert[ 3] = org1[0] - width * right1[0];
9776         vert[ 4] = org1[1] - width * right1[1];
9777         vert[ 5] = org1[2] - width * right1[2];
9778         vert[ 6] = org2[0] - width * right2[0];
9779         vert[ 7] = org2[1] - width * right2[1];
9780         vert[ 8] = org2[2] - width * right2[2];
9781         vert[ 9] = org2[0] + width * right2[0];
9782         vert[10] = org2[1] + width * right2[1];
9783         vert[11] = org2[2] + width * right2[2];
9784 }
9785
9786 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)
9787 {
9788         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9789         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9790         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9791         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9792         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9793         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9794         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9795         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9796         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9797         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9798         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9799         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9800 }
9801
9802 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9803 {
9804         int i;
9805         float *vertex3f;
9806         float v[3];
9807         VectorSet(v, x, y, z);
9808         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9809                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9810                         break;
9811         if (i == mesh->numvertices)
9812         {
9813                 if (mesh->numvertices < mesh->maxvertices)
9814                 {
9815                         VectorCopy(v, vertex3f);
9816                         mesh->numvertices++;
9817                 }
9818                 return mesh->numvertices;
9819         }
9820         else
9821                 return i;
9822 }
9823
9824 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9825 {
9826         int i;
9827         int *e, element[3];
9828         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9829         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9830         e = mesh->element3i + mesh->numtriangles * 3;
9831         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9832         {
9833                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9834                 if (mesh->numtriangles < mesh->maxtriangles)
9835                 {
9836                         *e++ = element[0];
9837                         *e++ = element[1];
9838                         *e++ = element[2];
9839                         mesh->numtriangles++;
9840                 }
9841                 element[1] = element[2];
9842         }
9843 }
9844
9845 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9846 {
9847         int i;
9848         int *e, element[3];
9849         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9850         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9851         e = mesh->element3i + mesh->numtriangles * 3;
9852         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9853         {
9854                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9855                 if (mesh->numtriangles < mesh->maxtriangles)
9856                 {
9857                         *e++ = element[0];
9858                         *e++ = element[1];
9859                         *e++ = element[2];
9860                         mesh->numtriangles++;
9861                 }
9862                 element[1] = element[2];
9863         }
9864 }
9865
9866 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9867 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9868 {
9869         int planenum, planenum2;
9870         int w;
9871         int tempnumpoints;
9872         mplane_t *plane, *plane2;
9873         double maxdist;
9874         double temppoints[2][256*3];
9875         // figure out how large a bounding box we need to properly compute this brush
9876         maxdist = 0;
9877         for (w = 0;w < numplanes;w++)
9878                 maxdist = max(maxdist, fabs(planes[w].dist));
9879         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9880         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9881         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9882         {
9883                 w = 0;
9884                 tempnumpoints = 4;
9885                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9886                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9887                 {
9888                         if (planenum2 == planenum)
9889                                 continue;
9890                         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);
9891                         w = !w;
9892                 }
9893                 if (tempnumpoints < 3)
9894                         continue;
9895                 // generate elements forming a triangle fan for this polygon
9896                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9897         }
9898 }
9899
9900 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)
9901 {
9902         texturelayer_t *layer;
9903         layer = t->currentlayers + t->currentnumlayers++;
9904         layer->type = type;
9905         layer->depthmask = depthmask;
9906         layer->blendfunc1 = blendfunc1;
9907         layer->blendfunc2 = blendfunc2;
9908         layer->texture = texture;
9909         layer->texmatrix = *matrix;
9910         layer->color[0] = r;
9911         layer->color[1] = g;
9912         layer->color[2] = b;
9913         layer->color[3] = a;
9914 }
9915
9916 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9917 {
9918         if(parms[0] == 0 && parms[1] == 0)
9919                 return false;
9920         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9921                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9922                         return false;
9923         return true;
9924 }
9925
9926 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9927 {
9928         double index, f;
9929         index = parms[2] + r_refdef.scene.time * parms[3];
9930         index -= floor(index);
9931         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9932         {
9933         default:
9934         case Q3WAVEFUNC_NONE:
9935         case Q3WAVEFUNC_NOISE:
9936         case Q3WAVEFUNC_COUNT:
9937                 f = 0;
9938                 break;
9939         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9940         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9941         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9942         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9943         case Q3WAVEFUNC_TRIANGLE:
9944                 index *= 4;
9945                 f = index - floor(index);
9946                 if (index < 1)
9947                         f = f;
9948                 else if (index < 2)
9949                         f = 1 - f;
9950                 else if (index < 3)
9951                         f = -f;
9952                 else
9953                         f = -(1 - f);
9954                 break;
9955         }
9956         f = parms[0] + parms[1] * f;
9957         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9958                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9959         return (float) f;
9960 }
9961
9962 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9963 {
9964         int w, h, idx;
9965         float f;
9966         float tcmat[12];
9967         matrix4x4_t matrix, temp;
9968         switch(tcmod->tcmod)
9969         {
9970                 case Q3TCMOD_COUNT:
9971                 case Q3TCMOD_NONE:
9972                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9973                                 matrix = r_waterscrollmatrix;
9974                         else
9975                                 matrix = identitymatrix;
9976                         break;
9977                 case Q3TCMOD_ENTITYTRANSLATE:
9978                         // this is used in Q3 to allow the gamecode to control texcoord
9979                         // scrolling on the entity, which is not supported in darkplaces yet.
9980                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9981                         break;
9982                 case Q3TCMOD_ROTATE:
9983                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9984                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9985                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9986                         break;
9987                 case Q3TCMOD_SCALE:
9988                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9989                         break;
9990                 case Q3TCMOD_SCROLL:
9991                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9992                         break;
9993                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9994                         w = (int) tcmod->parms[0];
9995                         h = (int) tcmod->parms[1];
9996                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9997                         f = f - floor(f);
9998                         idx = (int) floor(f * w * h);
9999                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10000                         break;
10001                 case Q3TCMOD_STRETCH:
10002                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10003                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10004                         break;
10005                 case Q3TCMOD_TRANSFORM:
10006                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10007                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10008                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10009                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10010                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10011                         break;
10012                 case Q3TCMOD_TURBULENT:
10013                         // this is handled in the RSurf_PrepareVertices function
10014                         matrix = identitymatrix;
10015                         break;
10016         }
10017         temp = *texmatrix;
10018         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10019 }
10020
10021 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10022 {
10023         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10024         char name[MAX_QPATH];
10025         skinframe_t *skinframe;
10026         unsigned char pixels[296*194];
10027         strlcpy(cache->name, skinname, sizeof(cache->name));
10028         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10029         if (developer_loading.integer)
10030                 Con_Printf("loading %s\n", name);
10031         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10032         if (!skinframe || !skinframe->base)
10033         {
10034                 unsigned char *f;
10035                 fs_offset_t filesize;
10036                 skinframe = NULL;
10037                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10038                 if (f)
10039                 {
10040                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10041                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10042                         Mem_Free(f);
10043                 }
10044         }
10045         cache->skinframe = skinframe;
10046 }
10047
10048 texture_t *R_GetCurrentTexture(texture_t *t)
10049 {
10050         int i;
10051         const entity_render_t *ent = rsurface.entity;
10052         dp_model_t *model = ent->model;
10053         q3shaderinfo_layer_tcmod_t *tcmod;
10054
10055         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10056                 return t->currentframe;
10057         t->update_lastrenderframe = r_textureframe;
10058         t->update_lastrenderentity = (void *)ent;
10059
10060         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10061                 t->camera_entity = ent->entitynumber;
10062         else
10063                 t->camera_entity = 0;
10064
10065         // switch to an alternate material if this is a q1bsp animated material
10066         {
10067                 texture_t *texture = t;
10068                 int s = rsurface.ent_skinnum;
10069                 if ((unsigned int)s >= (unsigned int)model->numskins)
10070                         s = 0;
10071                 if (model->skinscenes)
10072                 {
10073                         if (model->skinscenes[s].framecount > 1)
10074                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10075                         else
10076                                 s = model->skinscenes[s].firstframe;
10077                 }
10078                 if (s > 0)
10079                         t = t + s * model->num_surfaces;
10080                 if (t->animated)
10081                 {
10082                         // use an alternate animation if the entity's frame is not 0,
10083                         // and only if the texture has an alternate animation
10084                         if (rsurface.ent_alttextures && t->anim_total[1])
10085                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10086                         else
10087                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10088                 }
10089                 texture->currentframe = t;
10090         }
10091
10092         // update currentskinframe to be a qw skin or animation frame
10093         if (rsurface.ent_qwskin >= 0)
10094         {
10095                 i = rsurface.ent_qwskin;
10096                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10097                 {
10098                         r_qwskincache_size = cl.maxclients;
10099                         if (r_qwskincache)
10100                                 Mem_Free(r_qwskincache);
10101                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10102                 }
10103                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10104                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10105                 t->currentskinframe = r_qwskincache[i].skinframe;
10106                 if (t->currentskinframe == NULL)
10107                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10108         }
10109         else if (t->numskinframes >= 2)
10110                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10111         if (t->backgroundnumskinframes >= 2)
10112                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10113
10114         t->currentmaterialflags = t->basematerialflags;
10115         t->currentalpha = rsurface.colormod[3];
10116         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10117                 t->currentalpha *= r_wateralpha.value;
10118         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10119                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10120         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10121                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10122         if (!(rsurface.ent_flags & RENDER_LIGHT))
10123                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10124         else if (FAKELIGHT_ENABLED)
10125         {
10126                         // no modellight if using fakelight for the map
10127         }
10128         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10129         {
10130                 // pick a model lighting mode
10131                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10132                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10133                 else
10134                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10135         }
10136         if (rsurface.ent_flags & RENDER_ADDITIVE)
10137                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10138         else if (t->currentalpha < 1)
10139                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10140         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10141                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10142         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10143                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10144         if (t->backgroundnumskinframes)
10145                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10146         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10147         {
10148                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10149                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10150         }
10151         else
10152                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10153         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10154                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10155
10156         // there is no tcmod
10157         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10158         {
10159                 t->currenttexmatrix = r_waterscrollmatrix;
10160                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10161         }
10162         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10163         {
10164                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10165                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10166         }
10167
10168         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10169                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10170         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10171                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10172
10173         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10174         if (t->currentskinframe->qpixels)
10175                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10176         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10177         if (!t->basetexture)
10178                 t->basetexture = r_texture_notexture;
10179         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10180         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10181         t->nmaptexture = t->currentskinframe->nmap;
10182         if (!t->nmaptexture)
10183                 t->nmaptexture = r_texture_blanknormalmap;
10184         t->glosstexture = r_texture_black;
10185         t->glowtexture = t->currentskinframe->glow;
10186         t->fogtexture = t->currentskinframe->fog;
10187         t->reflectmasktexture = t->currentskinframe->reflect;
10188         if (t->backgroundnumskinframes)
10189         {
10190                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10191                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10192                 t->backgroundglosstexture = r_texture_black;
10193                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10194                 if (!t->backgroundnmaptexture)
10195                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10196         }
10197         else
10198         {
10199                 t->backgroundbasetexture = r_texture_white;
10200                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10201                 t->backgroundglosstexture = r_texture_black;
10202                 t->backgroundglowtexture = NULL;
10203         }
10204         t->specularpower = r_shadow_glossexponent.value;
10205         // TODO: store reference values for these in the texture?
10206         t->specularscale = 0;
10207         if (r_shadow_gloss.integer > 0)
10208         {
10209                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10210                 {
10211                         if (r_shadow_glossintensity.value > 0)
10212                         {
10213                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10214                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10215                                 t->specularscale = r_shadow_glossintensity.value;
10216                         }
10217                 }
10218                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10219                 {
10220                         t->glosstexture = r_texture_white;
10221                         t->backgroundglosstexture = r_texture_white;
10222                         t->specularscale = r_shadow_gloss2intensity.value;
10223                         t->specularpower = r_shadow_gloss2exponent.value;
10224                 }
10225         }
10226         t->specularscale *= t->specularscalemod;
10227         t->specularpower *= t->specularpowermod;
10228
10229         // lightmaps mode looks bad with dlights using actual texturing, so turn
10230         // off the colormap and glossmap, but leave the normalmap on as it still
10231         // accurately represents the shading involved
10232         if (gl_lightmaps.integer)
10233         {
10234                 t->basetexture = r_texture_grey128;
10235                 t->pantstexture = r_texture_black;
10236                 t->shirttexture = r_texture_black;
10237                 t->nmaptexture = r_texture_blanknormalmap;
10238                 t->glosstexture = r_texture_black;
10239                 t->glowtexture = NULL;
10240                 t->fogtexture = NULL;
10241                 t->reflectmasktexture = NULL;
10242                 t->backgroundbasetexture = NULL;
10243                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10244                 t->backgroundglosstexture = r_texture_black;
10245                 t->backgroundglowtexture = NULL;
10246                 t->specularscale = 0;
10247                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10248         }
10249
10250         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10251         VectorClear(t->dlightcolor);
10252         t->currentnumlayers = 0;
10253         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10254         {
10255                 int blendfunc1, blendfunc2;
10256                 qboolean depthmask;
10257                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10258                 {
10259                         blendfunc1 = GL_SRC_ALPHA;
10260                         blendfunc2 = GL_ONE;
10261                 }
10262                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10263                 {
10264                         blendfunc1 = GL_SRC_ALPHA;
10265                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10266                 }
10267                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10268                 {
10269                         blendfunc1 = t->customblendfunc[0];
10270                         blendfunc2 = t->customblendfunc[1];
10271                 }
10272                 else
10273                 {
10274                         blendfunc1 = GL_ONE;
10275                         blendfunc2 = GL_ZERO;
10276                 }
10277                 // don't colormod evilblend textures
10278                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10279                         VectorSet(t->lightmapcolor, 1, 1, 1);
10280                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10281                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10282                 {
10283                         // fullbright is not affected by r_refdef.lightmapintensity
10284                         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]);
10285                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10286                                 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]);
10287                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10288                                 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]);
10289                 }
10290                 else
10291                 {
10292                         vec3_t ambientcolor;
10293                         float colorscale;
10294                         // set the color tint used for lights affecting this surface
10295                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10296                         colorscale = 2;
10297                         // q3bsp has no lightmap updates, so the lightstylevalue that
10298                         // would normally be baked into the lightmap must be
10299                         // applied to the color
10300                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10301                         if (model->type == mod_brushq3)
10302                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10303                         colorscale *= r_refdef.lightmapintensity;
10304                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10305                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10306                         // basic lit geometry
10307                         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]);
10308                         // add pants/shirt if needed
10309                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10310                                 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]);
10311                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10312                                 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]);
10313                         // now add ambient passes if needed
10314                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10315                         {
10316                                 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]);
10317                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10318                                         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]);
10319                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10320                                         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]);
10321                         }
10322                 }
10323                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10324                         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]);
10325                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10326                 {
10327                         // if this is opaque use alpha blend which will darken the earlier
10328                         // passes cheaply.
10329                         //
10330                         // if this is an alpha blended material, all the earlier passes
10331                         // were darkened by fog already, so we only need to add the fog
10332                         // color ontop through the fog mask texture
10333                         //
10334                         // if this is an additive blended material, all the earlier passes
10335                         // were darkened by fog already, and we should not add fog color
10336                         // (because the background was not darkened, there is no fog color
10337                         // that was lost behind it).
10338                         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]);
10339                 }
10340         }
10341
10342         return t->currentframe;
10343 }
10344
10345 rsurfacestate_t rsurface;
10346
10347 void RSurf_ActiveWorldEntity(void)
10348 {
10349         dp_model_t *model = r_refdef.scene.worldmodel;
10350         //if (rsurface.entity == r_refdef.scene.worldentity)
10351         //      return;
10352         rsurface.entity = r_refdef.scene.worldentity;
10353         rsurface.skeleton = NULL;
10354         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10355         rsurface.ent_skinnum = 0;
10356         rsurface.ent_qwskin = -1;
10357         rsurface.ent_shadertime = 0;
10358         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10359         rsurface.matrix = identitymatrix;
10360         rsurface.inversematrix = identitymatrix;
10361         rsurface.matrixscale = 1;
10362         rsurface.inversematrixscale = 1;
10363         R_EntityMatrix(&identitymatrix);
10364         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10365         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10366         rsurface.fograngerecip = r_refdef.fograngerecip;
10367         rsurface.fogheightfade = r_refdef.fogheightfade;
10368         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10369         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10370         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10371         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10372         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10373         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10374         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10375         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10376         rsurface.colormod[3] = 1;
10377         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);
10378         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10379         rsurface.frameblend[0].lerp = 1;
10380         rsurface.ent_alttextures = false;
10381         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10382         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10383         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10384         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10385         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10386         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10387         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10388         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10389         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10390         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10391         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10392         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10393         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10394         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10395         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10396         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10397         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10398         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10399         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10400         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10401         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10402         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10403         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10404         rsurface.modelelement3i = model->surfmesh.data_element3i;
10405         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10406         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10407         rsurface.modelelement3s = model->surfmesh.data_element3s;
10408         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10409         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10410         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10411         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10412         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10413         rsurface.modelsurfaces = model->data_surfaces;
10414         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10415         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10416         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10417         rsurface.modelgeneratedvertex = false;
10418         rsurface.batchgeneratedvertex = false;
10419         rsurface.batchfirstvertex = 0;
10420         rsurface.batchnumvertices = 0;
10421         rsurface.batchfirsttriangle = 0;
10422         rsurface.batchnumtriangles = 0;
10423         rsurface.batchvertex3f  = NULL;
10424         rsurface.batchvertex3f_vertexbuffer = NULL;
10425         rsurface.batchvertex3f_bufferoffset = 0;
10426         rsurface.batchsvector3f = NULL;
10427         rsurface.batchsvector3f_vertexbuffer = NULL;
10428         rsurface.batchsvector3f_bufferoffset = 0;
10429         rsurface.batchtvector3f = NULL;
10430         rsurface.batchtvector3f_vertexbuffer = NULL;
10431         rsurface.batchtvector3f_bufferoffset = 0;
10432         rsurface.batchnormal3f  = NULL;
10433         rsurface.batchnormal3f_vertexbuffer = NULL;
10434         rsurface.batchnormal3f_bufferoffset = 0;
10435         rsurface.batchlightmapcolor4f = NULL;
10436         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10437         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10438         rsurface.batchtexcoordtexture2f = NULL;
10439         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10440         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10441         rsurface.batchtexcoordlightmap2f = NULL;
10442         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10443         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10444         rsurface.batchvertexmesh = NULL;
10445         rsurface.batchvertexmeshbuffer = NULL;
10446         rsurface.batchvertex3fbuffer = NULL;
10447         rsurface.batchelement3i = NULL;
10448         rsurface.batchelement3i_indexbuffer = NULL;
10449         rsurface.batchelement3i_bufferoffset = 0;
10450         rsurface.batchelement3s = NULL;
10451         rsurface.batchelement3s_indexbuffer = NULL;
10452         rsurface.batchelement3s_bufferoffset = 0;
10453         rsurface.passcolor4f = NULL;
10454         rsurface.passcolor4f_vertexbuffer = NULL;
10455         rsurface.passcolor4f_bufferoffset = 0;
10456 }
10457
10458 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10459 {
10460         dp_model_t *model = ent->model;
10461         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10462         //      return;
10463         rsurface.entity = (entity_render_t *)ent;
10464         rsurface.skeleton = ent->skeleton;
10465         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10466         rsurface.ent_skinnum = ent->skinnum;
10467         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;
10468         rsurface.ent_shadertime = ent->shadertime;
10469         rsurface.ent_flags = ent->flags;
10470         rsurface.matrix = ent->matrix;
10471         rsurface.inversematrix = ent->inversematrix;
10472         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10473         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10474         R_EntityMatrix(&rsurface.matrix);
10475         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10476         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10477         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10478         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10479         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10480         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10481         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10482         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10483         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10484         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10485         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10486         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10487         rsurface.colormod[3] = ent->alpha;
10488         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10489         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10490         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10491         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10492         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10493         if (ent->model->brush.submodel && !prepass)
10494         {
10495                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10496                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10497         }
10498         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10499         {
10500                 if (ent->animcache_vertex3f)
10501                 {
10502                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10503                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10504                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10505                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10506                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10507                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10508                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10509                 }
10510                 else if (wanttangents)
10511                 {
10512                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10513                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10514                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10515                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10516                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10517                         rsurface.modelvertexmesh = NULL;
10518                         rsurface.modelvertexmeshbuffer = NULL;
10519                         rsurface.modelvertex3fbuffer = NULL;
10520                 }
10521                 else if (wantnormals)
10522                 {
10523                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10524                         rsurface.modelsvector3f = NULL;
10525                         rsurface.modeltvector3f = NULL;
10526                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10527                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10528                         rsurface.modelvertexmesh = NULL;
10529                         rsurface.modelvertexmeshbuffer = NULL;
10530                         rsurface.modelvertex3fbuffer = NULL;
10531                 }
10532                 else
10533                 {
10534                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10535                         rsurface.modelsvector3f = NULL;
10536                         rsurface.modeltvector3f = NULL;
10537                         rsurface.modelnormal3f = NULL;
10538                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10539                         rsurface.modelvertexmesh = NULL;
10540                         rsurface.modelvertexmeshbuffer = NULL;
10541                         rsurface.modelvertex3fbuffer = NULL;
10542                 }
10543                 rsurface.modelvertex3f_vertexbuffer = 0;
10544                 rsurface.modelvertex3f_bufferoffset = 0;
10545                 rsurface.modelsvector3f_vertexbuffer = 0;
10546                 rsurface.modelsvector3f_bufferoffset = 0;
10547                 rsurface.modeltvector3f_vertexbuffer = 0;
10548                 rsurface.modeltvector3f_bufferoffset = 0;
10549                 rsurface.modelnormal3f_vertexbuffer = 0;
10550                 rsurface.modelnormal3f_bufferoffset = 0;
10551                 rsurface.modelgeneratedvertex = true;
10552         }
10553         else
10554         {
10555                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10556                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10557                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10558                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10559                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10560                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10561                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10562                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10563                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10564                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10565                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10566                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10567                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10568                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10569                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10570                 rsurface.modelgeneratedvertex = false;
10571         }
10572         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10573         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10574         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10575         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10576         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10577         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10578         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10579         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10580         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10581         rsurface.modelelement3i = model->surfmesh.data_element3i;
10582         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10583         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10584         rsurface.modelelement3s = model->surfmesh.data_element3s;
10585         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10586         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10587         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10588         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10589         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10590         rsurface.modelsurfaces = model->data_surfaces;
10591         rsurface.batchgeneratedvertex = false;
10592         rsurface.batchfirstvertex = 0;
10593         rsurface.batchnumvertices = 0;
10594         rsurface.batchfirsttriangle = 0;
10595         rsurface.batchnumtriangles = 0;
10596         rsurface.batchvertex3f  = NULL;
10597         rsurface.batchvertex3f_vertexbuffer = NULL;
10598         rsurface.batchvertex3f_bufferoffset = 0;
10599         rsurface.batchsvector3f = NULL;
10600         rsurface.batchsvector3f_vertexbuffer = NULL;
10601         rsurface.batchsvector3f_bufferoffset = 0;
10602         rsurface.batchtvector3f = NULL;
10603         rsurface.batchtvector3f_vertexbuffer = NULL;
10604         rsurface.batchtvector3f_bufferoffset = 0;
10605         rsurface.batchnormal3f  = NULL;
10606         rsurface.batchnormal3f_vertexbuffer = NULL;
10607         rsurface.batchnormal3f_bufferoffset = 0;
10608         rsurface.batchlightmapcolor4f = NULL;
10609         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10610         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10611         rsurface.batchtexcoordtexture2f = NULL;
10612         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10613         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10614         rsurface.batchtexcoordlightmap2f = NULL;
10615         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10616         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10617         rsurface.batchvertexmesh = NULL;
10618         rsurface.batchvertexmeshbuffer = NULL;
10619         rsurface.batchvertex3fbuffer = NULL;
10620         rsurface.batchelement3i = NULL;
10621         rsurface.batchelement3i_indexbuffer = NULL;
10622         rsurface.batchelement3i_bufferoffset = 0;
10623         rsurface.batchelement3s = NULL;
10624         rsurface.batchelement3s_indexbuffer = NULL;
10625         rsurface.batchelement3s_bufferoffset = 0;
10626         rsurface.passcolor4f = NULL;
10627         rsurface.passcolor4f_vertexbuffer = NULL;
10628         rsurface.passcolor4f_bufferoffset = 0;
10629 }
10630
10631 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)
10632 {
10633         rsurface.entity = r_refdef.scene.worldentity;
10634         rsurface.skeleton = NULL;
10635         rsurface.ent_skinnum = 0;
10636         rsurface.ent_qwskin = -1;
10637         rsurface.ent_shadertime = shadertime;
10638         rsurface.ent_flags = entflags;
10639         rsurface.modelnumvertices = numvertices;
10640         rsurface.modelnumtriangles = numtriangles;
10641         rsurface.matrix = *matrix;
10642         rsurface.inversematrix = *inversematrix;
10643         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10644         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10645         R_EntityMatrix(&rsurface.matrix);
10646         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10647         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10648         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10649         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10650         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10651         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10652         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10653         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10654         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10655         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10656         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10657         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10658         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);
10659         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10660         rsurface.frameblend[0].lerp = 1;
10661         rsurface.ent_alttextures = false;
10662         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10663         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10664         if (wanttangents)
10665         {
10666                 rsurface.modelvertex3f = (float *)vertex3f;
10667                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10668                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10669                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10670         }
10671         else if (wantnormals)
10672         {
10673                 rsurface.modelvertex3f = (float *)vertex3f;
10674                 rsurface.modelsvector3f = NULL;
10675                 rsurface.modeltvector3f = NULL;
10676                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10677         }
10678         else
10679         {
10680                 rsurface.modelvertex3f = (float *)vertex3f;
10681                 rsurface.modelsvector3f = NULL;
10682                 rsurface.modeltvector3f = NULL;
10683                 rsurface.modelnormal3f = NULL;
10684         }
10685         rsurface.modelvertexmesh = NULL;
10686         rsurface.modelvertexmeshbuffer = NULL;
10687         rsurface.modelvertex3fbuffer = NULL;
10688         rsurface.modelvertex3f_vertexbuffer = 0;
10689         rsurface.modelvertex3f_bufferoffset = 0;
10690         rsurface.modelsvector3f_vertexbuffer = 0;
10691         rsurface.modelsvector3f_bufferoffset = 0;
10692         rsurface.modeltvector3f_vertexbuffer = 0;
10693         rsurface.modeltvector3f_bufferoffset = 0;
10694         rsurface.modelnormal3f_vertexbuffer = 0;
10695         rsurface.modelnormal3f_bufferoffset = 0;
10696         rsurface.modelgeneratedvertex = true;
10697         rsurface.modellightmapcolor4f  = (float *)color4f;
10698         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10699         rsurface.modellightmapcolor4f_bufferoffset = 0;
10700         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
10701         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10702         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10703         rsurface.modeltexcoordlightmap2f  = NULL;
10704         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10705         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10706         rsurface.modelelement3i = (int *)element3i;
10707         rsurface.modelelement3i_indexbuffer = NULL;
10708         rsurface.modelelement3i_bufferoffset = 0;
10709         rsurface.modelelement3s = (unsigned short *)element3s;
10710         rsurface.modelelement3s_indexbuffer = NULL;
10711         rsurface.modelelement3s_bufferoffset = 0;
10712         rsurface.modellightmapoffsets = NULL;
10713         rsurface.modelsurfaces = NULL;
10714         rsurface.batchgeneratedvertex = false;
10715         rsurface.batchfirstvertex = 0;
10716         rsurface.batchnumvertices = 0;
10717         rsurface.batchfirsttriangle = 0;
10718         rsurface.batchnumtriangles = 0;
10719         rsurface.batchvertex3f  = NULL;
10720         rsurface.batchvertex3f_vertexbuffer = NULL;
10721         rsurface.batchvertex3f_bufferoffset = 0;
10722         rsurface.batchsvector3f = NULL;
10723         rsurface.batchsvector3f_vertexbuffer = NULL;
10724         rsurface.batchsvector3f_bufferoffset = 0;
10725         rsurface.batchtvector3f = NULL;
10726         rsurface.batchtvector3f_vertexbuffer = NULL;
10727         rsurface.batchtvector3f_bufferoffset = 0;
10728         rsurface.batchnormal3f  = NULL;
10729         rsurface.batchnormal3f_vertexbuffer = NULL;
10730         rsurface.batchnormal3f_bufferoffset = 0;
10731         rsurface.batchlightmapcolor4f = NULL;
10732         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10733         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10734         rsurface.batchtexcoordtexture2f = NULL;
10735         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10736         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10737         rsurface.batchtexcoordlightmap2f = NULL;
10738         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10739         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10740         rsurface.batchvertexmesh = NULL;
10741         rsurface.batchvertexmeshbuffer = NULL;
10742         rsurface.batchvertex3fbuffer = NULL;
10743         rsurface.batchelement3i = NULL;
10744         rsurface.batchelement3i_indexbuffer = NULL;
10745         rsurface.batchelement3i_bufferoffset = 0;
10746         rsurface.batchelement3s = NULL;
10747         rsurface.batchelement3s_indexbuffer = NULL;
10748         rsurface.batchelement3s_bufferoffset = 0;
10749         rsurface.passcolor4f = NULL;
10750         rsurface.passcolor4f_vertexbuffer = NULL;
10751         rsurface.passcolor4f_bufferoffset = 0;
10752
10753         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10754         {
10755                 if ((wantnormals || wanttangents) && !normal3f)
10756                 {
10757                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10758                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10759                 }
10760                 if (wanttangents && !svector3f)
10761                 {
10762                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10763                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10764                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10765                 }
10766         }
10767 }
10768
10769 float RSurf_FogPoint(const float *v)
10770 {
10771         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10772         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10773         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10774         float FogHeightFade = r_refdef.fogheightfade;
10775         float fogfrac;
10776         unsigned int fogmasktableindex;
10777         if (r_refdef.fogplaneviewabove)
10778                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10779         else
10780                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10781         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10782         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10783 }
10784
10785 float RSurf_FogVertex(const float *v)
10786 {
10787         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10788         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10789         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10790         float FogHeightFade = rsurface.fogheightfade;
10791         float fogfrac;
10792         unsigned int fogmasktableindex;
10793         if (r_refdef.fogplaneviewabove)
10794                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10795         else
10796                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10797         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10798         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10799 }
10800
10801 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10802 {
10803         int i;
10804         for (i = 0;i < numelements;i++)
10805                 outelement3i[i] = inelement3i[i] + adjust;
10806 }
10807
10808 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10809 extern cvar_t gl_vbo;
10810 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10811 {
10812         int deformindex;
10813         int firsttriangle;
10814         int numtriangles;
10815         int firstvertex;
10816         int endvertex;
10817         int numvertices;
10818         int surfacefirsttriangle;
10819         int surfacenumtriangles;
10820         int surfacefirstvertex;
10821         int surfaceendvertex;
10822         int surfacenumvertices;
10823         int batchnumvertices;
10824         int batchnumtriangles;
10825         int needsupdate;
10826         int i, j;
10827         qboolean gaps;
10828         qboolean dynamicvertex;
10829         float amplitude;
10830         float animpos;
10831         float scale;
10832         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10833         float waveparms[4];
10834         q3shaderinfo_deform_t *deform;
10835         const msurface_t *surface, *firstsurface;
10836         r_vertexmesh_t *vertexmesh;
10837         if (!texturenumsurfaces)
10838                 return;
10839         // find vertex range of this surface batch
10840         gaps = false;
10841         firstsurface = texturesurfacelist[0];
10842         firsttriangle = firstsurface->num_firsttriangle;
10843         batchnumvertices = 0;
10844         batchnumtriangles = 0;
10845         firstvertex = endvertex = firstsurface->num_firstvertex;
10846         for (i = 0;i < texturenumsurfaces;i++)
10847         {
10848                 surface = texturesurfacelist[i];
10849                 if (surface != firstsurface + i)
10850                         gaps = true;
10851                 surfacefirstvertex = surface->num_firstvertex;
10852                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10853                 surfacenumvertices = surface->num_vertices;
10854                 surfacenumtriangles = surface->num_triangles;
10855                 if (firstvertex > surfacefirstvertex)
10856                         firstvertex = surfacefirstvertex;
10857                 if (endvertex < surfaceendvertex)
10858                         endvertex = surfaceendvertex;
10859                 batchnumvertices += surfacenumvertices;
10860                 batchnumtriangles += surfacenumtriangles;
10861         }
10862
10863         // we now know the vertex range used, and if there are any gaps in it
10864         rsurface.batchfirstvertex = firstvertex;
10865         rsurface.batchnumvertices = endvertex - firstvertex;
10866         rsurface.batchfirsttriangle = firsttriangle;
10867         rsurface.batchnumtriangles = batchnumtriangles;
10868
10869         // this variable holds flags for which properties have been updated that
10870         // may require regenerating vertexmesh array...
10871         needsupdate = 0;
10872
10873         // check if any dynamic vertex processing must occur
10874         dynamicvertex = false;
10875
10876         // if there is a chance of animated vertex colors, it's a dynamic batch
10877         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10878         {
10879                 dynamicvertex = true;
10880                 batchneed |= BATCHNEED_NOGAPS;
10881                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10882         }
10883
10884         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10885         {
10886                 switch (deform->deform)
10887                 {
10888                 default:
10889                 case Q3DEFORM_PROJECTIONSHADOW:
10890                 case Q3DEFORM_TEXT0:
10891                 case Q3DEFORM_TEXT1:
10892                 case Q3DEFORM_TEXT2:
10893                 case Q3DEFORM_TEXT3:
10894                 case Q3DEFORM_TEXT4:
10895                 case Q3DEFORM_TEXT5:
10896                 case Q3DEFORM_TEXT6:
10897                 case Q3DEFORM_TEXT7:
10898                 case Q3DEFORM_NONE:
10899                         break;
10900                 case Q3DEFORM_AUTOSPRITE:
10901                         dynamicvertex = true;
10902                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10903                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10904                         break;
10905                 case Q3DEFORM_AUTOSPRITE2:
10906                         dynamicvertex = true;
10907                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10908                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10909                         break;
10910                 case Q3DEFORM_NORMAL:
10911                         dynamicvertex = true;
10912                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10913                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10914                         break;
10915                 case Q3DEFORM_WAVE:
10916                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10917                                 break; // if wavefunc is a nop, ignore this transform
10918                         dynamicvertex = true;
10919                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10920                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10921                         break;
10922                 case Q3DEFORM_BULGE:
10923                         dynamicvertex = true;
10924                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10925                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10926                         break;
10927                 case Q3DEFORM_MOVE:
10928                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10929                                 break; // if wavefunc is a nop, ignore this transform
10930                         dynamicvertex = true;
10931                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10932                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
10933                         break;
10934                 }
10935         }
10936         switch(rsurface.texture->tcgen.tcgen)
10937         {
10938         default:
10939         case Q3TCGEN_TEXTURE:
10940                 break;
10941         case Q3TCGEN_LIGHTMAP:
10942                 dynamicvertex = true;
10943                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10944                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10945                 break;
10946         case Q3TCGEN_VECTOR:
10947                 dynamicvertex = true;
10948                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10949                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10950                 break;
10951         case Q3TCGEN_ENVIRONMENT:
10952                 dynamicvertex = true;
10953                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10954                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10955                 break;
10956         }
10957         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10958         {
10959                 dynamicvertex = true;
10960                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10961                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10962         }
10963
10964         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10965         {
10966                 dynamicvertex = true;
10967                 batchneed |= BATCHNEED_NOGAPS;
10968                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10969         }
10970
10971         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10972         {
10973                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10974                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
10975                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
10976                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
10977                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10978                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10979                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10980         }
10981
10982         // when the model data has no vertex buffer (dynamic mesh), we need to
10983         // eliminate gaps
10984         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
10985                 batchneed |= BATCHNEED_NOGAPS;
10986
10987         // if needsupdate, we have to do a dynamic vertex batch for sure
10988         if (needsupdate & batchneed)
10989                 dynamicvertex = true;
10990
10991         // see if we need to build vertexmesh from arrays
10992         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10993                 dynamicvertex = true;
10994
10995         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10996         // also some drivers strongly dislike firstvertex
10997         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10998                 dynamicvertex = true;
10999
11000         rsurface.batchvertex3f = rsurface.modelvertex3f;
11001         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11002         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11003         rsurface.batchsvector3f = rsurface.modelsvector3f;
11004         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11005         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11006         rsurface.batchtvector3f = rsurface.modeltvector3f;
11007         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11008         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11009         rsurface.batchnormal3f = rsurface.modelnormal3f;
11010         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11011         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11012         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11013         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11014         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11015         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11016         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11017         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11018         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11019         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11020         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11021         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11022         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11023         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11024         rsurface.batchelement3i = rsurface.modelelement3i;
11025         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11026         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11027         rsurface.batchelement3s = rsurface.modelelement3s;
11028         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11029         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11030
11031         // if any dynamic vertex processing has to occur in software, we copy the
11032         // entire surface list together before processing to rebase the vertices
11033         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11034         //
11035         // if any gaps exist and we do not have a static vertex buffer, we have to
11036         // copy the surface list together to avoid wasting upload bandwidth on the
11037         // vertices in the gaps.
11038         //
11039         // if gaps exist and we have a static vertex buffer, we still have to
11040         // combine the index buffer ranges into one dynamic index buffer.
11041         //
11042         // in all cases we end up with data that can be drawn in one call.
11043
11044         if (!dynamicvertex)
11045         {
11046                 // static vertex data, just set pointers...
11047                 rsurface.batchgeneratedvertex = false;
11048                 // if there are gaps, we want to build a combined index buffer,
11049                 // otherwise use the original static buffer with an appropriate offset
11050                 if (gaps)
11051                 {
11052                         // build a new triangle elements array for this batch
11053                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11054                         rsurface.batchfirsttriangle = 0;
11055                         numtriangles = 0;
11056                         for (i = 0;i < texturenumsurfaces;i++)
11057                         {
11058                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11059                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11060                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11061                                 numtriangles += surfacenumtriangles;
11062                         }
11063                         rsurface.batchelement3i_indexbuffer = NULL;
11064                         rsurface.batchelement3i_bufferoffset = 0;
11065                         rsurface.batchelement3s = NULL;
11066                         rsurface.batchelement3s_indexbuffer = NULL;
11067                         rsurface.batchelement3s_bufferoffset = 0;
11068                         if (endvertex <= 65536)
11069                         {
11070                                 // make a 16bit (unsigned short) index array if possible
11071                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11072                                 for (i = 0;i < numtriangles*3;i++)
11073                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11074                         }
11075                 }
11076                 return;
11077         }
11078
11079         // something needs software processing, do it for real...
11080         // we only directly handle separate array data in this case and then
11081         // generate interleaved data if needed...
11082         rsurface.batchgeneratedvertex = true;
11083
11084         // now copy the vertex data into a combined array and make an index array
11085         // (this is what Quake3 does all the time)
11086         //if (gaps || rsurface.batchfirstvertex)
11087         {
11088                 rsurface.batchvertex3fbuffer = NULL;
11089                 rsurface.batchvertexmesh = NULL;
11090                 rsurface.batchvertexmeshbuffer = NULL;
11091                 rsurface.batchvertex3f = NULL;
11092                 rsurface.batchvertex3f_vertexbuffer = NULL;
11093                 rsurface.batchvertex3f_bufferoffset = 0;
11094                 rsurface.batchsvector3f = NULL;
11095                 rsurface.batchsvector3f_vertexbuffer = NULL;
11096                 rsurface.batchsvector3f_bufferoffset = 0;
11097                 rsurface.batchtvector3f = NULL;
11098                 rsurface.batchtvector3f_vertexbuffer = NULL;
11099                 rsurface.batchtvector3f_bufferoffset = 0;
11100                 rsurface.batchnormal3f = NULL;
11101                 rsurface.batchnormal3f_vertexbuffer = NULL;
11102                 rsurface.batchnormal3f_bufferoffset = 0;
11103                 rsurface.batchlightmapcolor4f = NULL;
11104                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11105                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11106                 rsurface.batchtexcoordtexture2f = NULL;
11107                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11108                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11109                 rsurface.batchtexcoordlightmap2f = NULL;
11110                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11111                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11112                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11113                 rsurface.batchelement3i_indexbuffer = NULL;
11114                 rsurface.batchelement3i_bufferoffset = 0;
11115                 rsurface.batchelement3s = NULL;
11116                 rsurface.batchelement3s_indexbuffer = NULL;
11117                 rsurface.batchelement3s_bufferoffset = 0;
11118                 // we'll only be setting up certain arrays as needed
11119                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11120                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11121                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11122                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11123                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11124                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11125                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11126                 {
11127                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11128                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11129                 }
11130                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11131                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11132                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11133                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11134                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11135                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11136                 numvertices = 0;
11137                 numtriangles = 0;
11138                 for (i = 0;i < texturenumsurfaces;i++)
11139                 {
11140                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11141                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11142                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11143                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11144                         // copy only the data requested
11145                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11146                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11147                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11148                         {
11149                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11150                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11151                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11152                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11153                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11154                                 {
11155                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11156                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11157                                 }
11158                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11159                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11160                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11161                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11162                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11163                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11164                         }
11165                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11166                         numvertices += surfacenumvertices;
11167                         numtriangles += surfacenumtriangles;
11168                 }
11169
11170                 // generate a 16bit index array as well if possible
11171                 // (in general, dynamic batches fit)
11172                 if (numvertices <= 65536)
11173                 {
11174                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11175                         for (i = 0;i < numtriangles*3;i++)
11176                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11177                 }
11178
11179                 // since we've copied everything, the batch now starts at 0
11180                 rsurface.batchfirstvertex = 0;
11181                 rsurface.batchnumvertices = batchnumvertices;
11182                 rsurface.batchfirsttriangle = 0;
11183                 rsurface.batchnumtriangles = batchnumtriangles;
11184         }
11185
11186         // q1bsp surfaces rendered in vertex color mode have to have colors
11187         // calculated based on lightstyles
11188         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11189         {
11190                 // generate color arrays for the surfaces in this list
11191                 int c[4];
11192                 int scale;
11193                 int size3;
11194                 const int *offsets;
11195                 const unsigned char *lm;
11196                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11197                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11198                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11199                 numvertices = 0;
11200                 for (i = 0;i < texturenumsurfaces;i++)
11201                 {
11202                         surface = texturesurfacelist[i];
11203                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11204                         surfacenumvertices = surface->num_vertices;
11205                         if (surface->lightmapinfo->samples)
11206                         {
11207                                 for (j = 0;j < surfacenumvertices;j++)
11208                                 {
11209                                         lm = surface->lightmapinfo->samples + offsets[j];
11210                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11211                                         VectorScale(lm, scale, c);
11212                                         if (surface->lightmapinfo->styles[1] != 255)
11213                                         {
11214                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11215                                                 lm += size3;
11216                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11217                                                 VectorMA(c, scale, lm, c);
11218                                                 if (surface->lightmapinfo->styles[2] != 255)
11219                                                 {
11220                                                         lm += size3;
11221                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11222                                                         VectorMA(c, scale, lm, c);
11223                                                         if (surface->lightmapinfo->styles[3] != 255)
11224                                                         {
11225                                                                 lm += size3;
11226                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11227                                                                 VectorMA(c, scale, lm, c);
11228                                                         }
11229                                                 }
11230                                         }
11231                                         c[0] >>= 7;
11232                                         c[1] >>= 7;
11233                                         c[2] >>= 7;
11234                                         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);
11235                                         numvertices++;
11236                                 }
11237                         }
11238                         else
11239                         {
11240                                 for (j = 0;j < surfacenumvertices;j++)
11241                                 {
11242                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11243                                         numvertices++;
11244                                 }
11245                         }
11246                 }
11247         }
11248
11249         // if vertices are deformed (sprite flares and things in maps, possibly
11250         // water waves, bulges and other deformations), modify the copied vertices
11251         // in place
11252         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11253         {
11254                 switch (deform->deform)
11255                 {
11256                 default:
11257                 case Q3DEFORM_PROJECTIONSHADOW:
11258                 case Q3DEFORM_TEXT0:
11259                 case Q3DEFORM_TEXT1:
11260                 case Q3DEFORM_TEXT2:
11261                 case Q3DEFORM_TEXT3:
11262                 case Q3DEFORM_TEXT4:
11263                 case Q3DEFORM_TEXT5:
11264                 case Q3DEFORM_TEXT6:
11265                 case Q3DEFORM_TEXT7:
11266                 case Q3DEFORM_NONE:
11267                         break;
11268                 case Q3DEFORM_AUTOSPRITE:
11269                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11270                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11271                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11272                         VectorNormalize(newforward);
11273                         VectorNormalize(newright);
11274                         VectorNormalize(newup);
11275 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11276 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11277 //                      rsurface.batchvertex3f_bufferoffset = 0;
11278 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11279 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
11280 //                      rsurface.batchsvector3f_bufferoffset = 0;
11281 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11282 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
11283 //                      rsurface.batchtvector3f_bufferoffset = 0;
11284 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11285 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11286 //                      rsurface.batchnormal3f_bufferoffset = 0;
11287                         // a single autosprite surface can contain multiple sprites...
11288                         for (j = 0;j < batchnumvertices - 3;j += 4)
11289                         {
11290                                 VectorClear(center);
11291                                 for (i = 0;i < 4;i++)
11292                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11293                                 VectorScale(center, 0.25f, center);
11294                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11295                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11296                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11297                                 for (i = 0;i < 4;i++)
11298                                 {
11299                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11300                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11301                                 }
11302                         }
11303                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11304                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11305                         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);
11306                         break;
11307                 case Q3DEFORM_AUTOSPRITE2:
11308                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11309                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11310                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11311                         VectorNormalize(newforward);
11312                         VectorNormalize(newright);
11313                         VectorNormalize(newup);
11314 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11315 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11316 //                      rsurface.batchvertex3f_bufferoffset = 0;
11317                         {
11318                                 const float *v1, *v2;
11319                                 vec3_t start, end;
11320                                 float f, l;
11321                                 struct
11322                                 {
11323                                         float length2;
11324                                         const float *v1;
11325                                         const float *v2;
11326                                 }
11327                                 shortest[2];
11328                                 memset(shortest, 0, sizeof(shortest));
11329                                 // a single autosprite surface can contain multiple sprites...
11330                                 for (j = 0;j < batchnumvertices - 3;j += 4)
11331                                 {
11332                                         VectorClear(center);
11333                                         for (i = 0;i < 4;i++)
11334                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11335                                         VectorScale(center, 0.25f, center);
11336                                         // find the two shortest edges, then use them to define the
11337                                         // axis vectors for rotating around the central axis
11338                                         for (i = 0;i < 6;i++)
11339                                         {
11340                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11341                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11342                                                 l = VectorDistance2(v1, v2);
11343                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11344                                                 if (v1[2] != v2[2])
11345                                                         l += (1.0f / 1024.0f);
11346                                                 if (shortest[0].length2 > l || i == 0)
11347                                                 {
11348                                                         shortest[1] = shortest[0];
11349                                                         shortest[0].length2 = l;
11350                                                         shortest[0].v1 = v1;
11351                                                         shortest[0].v2 = v2;
11352                                                 }
11353                                                 else if (shortest[1].length2 > l || i == 1)
11354                                                 {
11355                                                         shortest[1].length2 = l;
11356                                                         shortest[1].v1 = v1;
11357                                                         shortest[1].v2 = v2;
11358                                                 }
11359                                         }
11360                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11361                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11362                                         // this calculates the right vector from the shortest edge
11363                                         // and the up vector from the edge midpoints
11364                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11365                                         VectorNormalize(right);
11366                                         VectorSubtract(end, start, up);
11367                                         VectorNormalize(up);
11368                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11369                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11370                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11371                                         VectorNegate(forward, forward);
11372                                         VectorReflect(forward, 0, up, forward);
11373                                         VectorNormalize(forward);
11374                                         CrossProduct(up, forward, newright);
11375                                         VectorNormalize(newright);
11376                                         // rotate the quad around the up axis vector, this is made
11377                                         // especially easy by the fact we know the quad is flat,
11378                                         // so we only have to subtract the center position and
11379                                         // measure distance along the right vector, and then
11380                                         // multiply that by the newright vector and add back the
11381                                         // center position
11382                                         // we also need to subtract the old position to undo the
11383                                         // displacement from the center, which we do with a
11384                                         // DotProduct, the subtraction/addition of center is also
11385                                         // optimized into DotProducts here
11386                                         l = DotProduct(right, center);
11387                                         for (i = 0;i < 4;i++)
11388                                         {
11389                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11390                                                 f = DotProduct(right, v1) - l;
11391                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11392                                         }
11393                                 }
11394                         }
11395                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11396                         {
11397 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11398 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
11399 //                              rsurface.batchnormal3f_bufferoffset = 0;
11400                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11401                         }
11402                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11403                         {
11404 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11405 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11406 //                              rsurface.batchsvector3f_bufferoffset = 0;
11407 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11408 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11409 //                              rsurface.batchtvector3f_bufferoffset = 0;
11410                                 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);
11411                         }
11412                         break;
11413                 case Q3DEFORM_NORMAL:
11414                         // deform the normals to make reflections wavey
11415                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11416                         rsurface.batchnormal3f_vertexbuffer = NULL;
11417                         rsurface.batchnormal3f_bufferoffset = 0;
11418                         for (j = 0;j < batchnumvertices;j++)
11419                         {
11420                                 float vertex[3];
11421                                 float *normal = rsurface.batchnormal3f + 3*j;
11422                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11423                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11424                                 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]);
11425                                 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]);
11426                                 VectorNormalize(normal);
11427                         }
11428                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11429                         {
11430 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11431 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11432 //                              rsurface.batchsvector3f_bufferoffset = 0;
11433 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11434 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11435 //                              rsurface.batchtvector3f_bufferoffset = 0;
11436                                 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);
11437                         }
11438                         break;
11439                 case Q3DEFORM_WAVE:
11440                         // deform vertex array to make wavey water and flags and such
11441                         waveparms[0] = deform->waveparms[0];
11442                         waveparms[1] = deform->waveparms[1];
11443                         waveparms[2] = deform->waveparms[2];
11444                         waveparms[3] = deform->waveparms[3];
11445                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11446                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11447                         // this is how a divisor of vertex influence on deformation
11448                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11449                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11450 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11451 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11452 //                      rsurface.batchvertex3f_bufferoffset = 0;
11453 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11454 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11455 //                      rsurface.batchnormal3f_bufferoffset = 0;
11456                         for (j = 0;j < batchnumvertices;j++)
11457                         {
11458                                 // if the wavefunc depends on time, evaluate it per-vertex
11459                                 if (waveparms[3])
11460                                 {
11461                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11462                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11463                                 }
11464                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11465                         }
11466                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11467                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11468                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11469                         {
11470 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11471 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11472 //                              rsurface.batchsvector3f_bufferoffset = 0;
11473 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11474 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11475 //                              rsurface.batchtvector3f_bufferoffset = 0;
11476                                 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);
11477                         }
11478                         break;
11479                 case Q3DEFORM_BULGE:
11480                         // deform vertex array to make the surface have moving bulges
11481 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11482 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11483 //                      rsurface.batchvertex3f_bufferoffset = 0;
11484 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11485 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11486 //                      rsurface.batchnormal3f_bufferoffset = 0;
11487                         for (j = 0;j < batchnumvertices;j++)
11488                         {
11489                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11490                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11491                         }
11492                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11493                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11494                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11495                         {
11496 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11497 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11498 //                              rsurface.batchsvector3f_bufferoffset = 0;
11499 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11500 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11501 //                              rsurface.batchtvector3f_bufferoffset = 0;
11502                                 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);
11503                         }
11504                         break;
11505                 case Q3DEFORM_MOVE:
11506                         // deform vertex array
11507                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11508                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11509                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11510                         VectorScale(deform->parms, scale, waveparms);
11511 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11512 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11513 //                      rsurface.batchvertex3f_bufferoffset = 0;
11514                         for (j = 0;j < batchnumvertices;j++)
11515                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11516                         break;
11517                 }
11518         }
11519
11520         // generate texcoords based on the chosen texcoord source
11521         switch(rsurface.texture->tcgen.tcgen)
11522         {
11523         default:
11524         case Q3TCGEN_TEXTURE:
11525                 break;
11526         case Q3TCGEN_LIGHTMAP:
11527 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11528 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11529 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11530                 if (rsurface.batchtexcoordlightmap2f)
11531                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11532                 break;
11533         case Q3TCGEN_VECTOR:
11534 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11535 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11536 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11537                 for (j = 0;j < batchnumvertices;j++)
11538                 {
11539                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11540                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11541                 }
11542                 break;
11543         case Q3TCGEN_ENVIRONMENT:
11544                 // make environment reflections using a spheremap
11545                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11546                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11547                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11548                 for (j = 0;j < batchnumvertices;j++)
11549                 {
11550                         // identical to Q3A's method, but executed in worldspace so
11551                         // carried models can be shiny too
11552
11553                         float viewer[3], d, reflected[3], worldreflected[3];
11554
11555                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11556                         // VectorNormalize(viewer);
11557
11558                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11559
11560                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11561                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11562                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11563                         // note: this is proportinal to viewer, so we can normalize later
11564
11565                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11566                         VectorNormalize(worldreflected);
11567
11568                         // note: this sphere map only uses world x and z!
11569                         // so positive and negative y will LOOK THE SAME.
11570                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11571                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11572                 }
11573                 break;
11574         }
11575         // the only tcmod that needs software vertex processing is turbulent, so
11576         // check for it here and apply the changes if needed
11577         // and we only support that as the first one
11578         // (handling a mixture of turbulent and other tcmods would be problematic
11579         //  without punting it entirely to a software path)
11580         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11581         {
11582                 amplitude = rsurface.texture->tcmods[0].parms[1];
11583                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11584 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11585 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11586 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11587                 for (j = 0;j < batchnumvertices;j++)
11588                 {
11589                         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);
11590                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11591                 }
11592         }
11593
11594         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11595         {
11596                 // convert the modified arrays to vertex structs
11597 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11598 //              rsurface.batchvertexmeshbuffer = NULL;
11599                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11600                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11601                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11602                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11603                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11604                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11605                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11606                 {
11607                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11608                         {
11609                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11610                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11611                         }
11612                 }
11613                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11614                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11615                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11616                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11617                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11618                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11619                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11620                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11621                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11622         }
11623 }
11624
11625 void RSurf_DrawBatch(void)
11626 {
11627         // sometimes a zero triangle surface (usually a degenerate patch) makes it
11628         // through the pipeline, killing it earlier in the pipeline would have
11629         // per-surface overhead rather than per-batch overhead, so it's best to
11630         // reject it here, before it hits glDraw.
11631         if (rsurface.batchnumtriangles == 0)
11632                 return;
11633 #if 0
11634         // batch debugging code
11635         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11636         {
11637                 int i;
11638                 int j;
11639                 int c;
11640                 const int *e;
11641                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11642                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11643                 {
11644                         c = e[i];
11645                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11646                         {
11647                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11648                                 {
11649                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11650                                                 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);
11651                                         break;
11652                                 }
11653                         }
11654                 }
11655         }
11656 #endif
11657         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);
11658 }
11659
11660 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11661 {
11662         // pick the closest matching water plane
11663         int planeindex, vertexindex, bestplaneindex = -1;
11664         float d, bestd;
11665         vec3_t vert;
11666         const float *v;
11667         r_waterstate_waterplane_t *p;
11668         qboolean prepared = false;
11669         bestd = 0;
11670         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11671         {
11672                 if(p->camera_entity != rsurface.texture->camera_entity)
11673                         continue;
11674                 d = 0;
11675                 if(!prepared)
11676                 {
11677                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11678                         prepared = true;
11679                         if(rsurface.batchnumvertices == 0)
11680                                 break;
11681                 }
11682                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11683                 {
11684                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11685                         d += fabs(PlaneDiff(vert, &p->plane));
11686                 }
11687                 if (bestd > d || bestplaneindex < 0)
11688                 {
11689                         bestd = d;
11690                         bestplaneindex = planeindex;
11691                 }
11692         }
11693         return bestplaneindex;
11694         // NOTE: this MAY return a totally unrelated water plane; we can ignore
11695         // this situation though, as it might be better to render single larger
11696         // batches with useless stuff (backface culled for example) than to
11697         // render multiple smaller batches
11698 }
11699
11700 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11701 {
11702         int i;
11703         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11704         rsurface.passcolor4f_vertexbuffer = 0;
11705         rsurface.passcolor4f_bufferoffset = 0;
11706         for (i = 0;i < rsurface.batchnumvertices;i++)
11707                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11708 }
11709
11710 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11711 {
11712         int i;
11713         float f;
11714         const float *v;
11715         const float *c;
11716         float *c2;
11717         if (rsurface.passcolor4f)
11718         {
11719                 // generate color arrays
11720                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11721                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11722                 rsurface.passcolor4f_vertexbuffer = 0;
11723                 rsurface.passcolor4f_bufferoffset = 0;
11724                 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)
11725                 {
11726                         f = RSurf_FogVertex(v);
11727                         c2[0] = c[0] * f;
11728                         c2[1] = c[1] * f;
11729                         c2[2] = c[2] * f;
11730                         c2[3] = c[3];
11731                 }
11732         }
11733         else
11734         {
11735                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11736                 rsurface.passcolor4f_vertexbuffer = 0;
11737                 rsurface.passcolor4f_bufferoffset = 0;
11738                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11739                 {
11740                         f = RSurf_FogVertex(v);
11741                         c2[0] = f;
11742                         c2[1] = f;
11743                         c2[2] = f;
11744                         c2[3] = 1;
11745                 }
11746         }
11747 }
11748
11749 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11750 {
11751         int i;
11752         float f;
11753         const float *v;
11754         const float *c;
11755         float *c2;
11756         if (!rsurface.passcolor4f)
11757                 return;
11758         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11759         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11760         rsurface.passcolor4f_vertexbuffer = 0;
11761         rsurface.passcolor4f_bufferoffset = 0;
11762         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
11763         {
11764                 f = RSurf_FogVertex(v);
11765                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11766                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11767                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11768                 c2[3] = c[3];
11769         }
11770 }
11771
11772 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11773 {
11774         int i;
11775         const float *c;
11776         float *c2;
11777         if (!rsurface.passcolor4f)
11778                 return;
11779         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11780         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11781         rsurface.passcolor4f_vertexbuffer = 0;
11782         rsurface.passcolor4f_bufferoffset = 0;
11783         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11784         {
11785                 c2[0] = c[0] * r;
11786                 c2[1] = c[1] * g;
11787                 c2[2] = c[2] * b;
11788                 c2[3] = c[3] * a;
11789         }
11790 }
11791
11792 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11793 {
11794         int i;
11795         const float *c;
11796         float *c2;
11797         if (!rsurface.passcolor4f)
11798                 return;
11799         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11800         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11801         rsurface.passcolor4f_vertexbuffer = 0;
11802         rsurface.passcolor4f_bufferoffset = 0;
11803         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11804         {
11805                 c2[0] = c[0] + r_refdef.scene.ambient;
11806                 c2[1] = c[1] + r_refdef.scene.ambient;
11807                 c2[2] = c[2] + r_refdef.scene.ambient;
11808                 c2[3] = c[3];
11809         }
11810 }
11811
11812 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11813 {
11814         // TODO: optimize
11815         rsurface.passcolor4f = NULL;
11816         rsurface.passcolor4f_vertexbuffer = 0;
11817         rsurface.passcolor4f_bufferoffset = 0;
11818         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11819         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11820         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11821         GL_Color(r, g, b, a);
11822         R_Mesh_TexBind(0, rsurface.lightmaptexture);
11823         RSurf_DrawBatch();
11824 }
11825
11826 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11827 {
11828         // TODO: optimize applyfog && applycolor case
11829         // just apply fog if necessary, and tint the fog color array if necessary
11830         rsurface.passcolor4f = NULL;
11831         rsurface.passcolor4f_vertexbuffer = 0;
11832         rsurface.passcolor4f_bufferoffset = 0;
11833         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11834         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11835         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11836         GL_Color(r, g, b, a);
11837         RSurf_DrawBatch();
11838 }
11839
11840 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11841 {
11842         // TODO: optimize
11843         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11844         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11845         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11846         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11847         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11848         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11849         GL_Color(r, g, b, a);
11850         RSurf_DrawBatch();
11851 }
11852
11853 static void RSurf_DrawBatch_GL11_ClampColor(void)
11854 {
11855         int i;
11856         const float *c1;
11857         float *c2;
11858         if (!rsurface.passcolor4f)
11859                 return;
11860         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11861         {
11862                 c2[0] = bound(0.0f, c1[0], 1.0f);
11863                 c2[1] = bound(0.0f, c1[1], 1.0f);
11864                 c2[2] = bound(0.0f, c1[2], 1.0f);
11865                 c2[3] = bound(0.0f, c1[3], 1.0f);
11866         }
11867 }
11868
11869 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11870 {
11871         int i;
11872         float f;
11873         const float *v;
11874         const float *n;
11875         float *c;
11876         //vec3_t eyedir;
11877
11878         // fake shading
11879         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11880         rsurface.passcolor4f_vertexbuffer = 0;
11881         rsurface.passcolor4f_bufferoffset = 0;
11882         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)
11883         {
11884                 f = -DotProduct(r_refdef.view.forward, n);
11885                 f = max(0, f);
11886                 f = f * 0.85 + 0.15; // work around so stuff won't get black
11887                 f *= r_refdef.lightmapintensity;
11888                 Vector4Set(c, f, f, f, 1);
11889         }
11890 }
11891
11892 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11893 {
11894         RSurf_DrawBatch_GL11_ApplyFakeLight();
11895         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11896         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11897         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11898         GL_Color(r, g, b, a);
11899         RSurf_DrawBatch();
11900 }
11901
11902 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11903 {
11904         int i;
11905         float f;
11906         float alpha;
11907         const float *v;
11908         const float *n;
11909         float *c;
11910         vec3_t ambientcolor;
11911         vec3_t diffusecolor;
11912         vec3_t lightdir;
11913         // TODO: optimize
11914         // model lighting
11915         VectorCopy(rsurface.modellight_lightdir, lightdir);
11916         f = 0.5f * r_refdef.lightmapintensity;
11917         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11918         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11919         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11920         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11921         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11922         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11923         alpha = *a;
11924         if (VectorLength2(diffusecolor) > 0)
11925         {
11926                 // q3-style directional shading
11927                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11928                 rsurface.passcolor4f_vertexbuffer = 0;
11929                 rsurface.passcolor4f_bufferoffset = 0;
11930                 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)
11931                 {
11932                         if ((f = DotProduct(n, lightdir)) > 0)
11933                                 VectorMA(ambientcolor, f, diffusecolor, c);
11934                         else
11935                                 VectorCopy(ambientcolor, c);
11936                         c[3] = alpha;
11937                 }
11938                 *r = 1;
11939                 *g = 1;
11940                 *b = 1;
11941                 *a = 1;
11942                 *applycolor = false;
11943         }
11944         else
11945         {
11946                 *r = ambientcolor[0];
11947                 *g = ambientcolor[1];
11948                 *b = ambientcolor[2];
11949                 rsurface.passcolor4f = NULL;
11950                 rsurface.passcolor4f_vertexbuffer = 0;
11951                 rsurface.passcolor4f_bufferoffset = 0;
11952         }
11953 }
11954
11955 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11956 {
11957         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11958         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11959         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11960         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11961         GL_Color(r, g, b, a);
11962         RSurf_DrawBatch();
11963 }
11964
11965 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11966 {
11967         int i;
11968         float f;
11969         const float *v;
11970         float *c;
11971         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11972         {
11973                 f = 1 - RSurf_FogVertex(v);
11974                 c[0] = r;
11975                 c[1] = g;
11976                 c[2] = b;
11977                 c[3] = f * a;
11978         }
11979 }
11980
11981 void RSurf_SetupDepthAndCulling(void)
11982 {
11983         // submodels are biased to avoid z-fighting with world surfaces that they
11984         // may be exactly overlapping (avoids z-fighting artifacts on certain
11985         // doors and things in Quake maps)
11986         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11987         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11988         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11989         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11990 }
11991
11992 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11993 {
11994         // transparent sky would be ridiculous
11995         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11996                 return;
11997         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11998         skyrenderlater = true;
11999         RSurf_SetupDepthAndCulling();
12000         GL_DepthMask(true);
12001         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12002         // skymasking on them, and Quake3 never did sky masking (unlike
12003         // software Quake and software Quake2), so disable the sky masking
12004         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12005         // and skymasking also looks very bad when noclipping outside the
12006         // level, so don't use it then either.
12007         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12008         {
12009                 R_Mesh_ResetTextureState();
12010                 if (skyrendermasked)
12011                 {
12012                         R_SetupShader_DepthOrShadow();
12013                         // depth-only (masking)
12014                         GL_ColorMask(0,0,0,0);
12015                         // just to make sure that braindead drivers don't draw
12016                         // anything despite that colormask...
12017                         GL_BlendFunc(GL_ZERO, GL_ONE);
12018                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12019                         if (rsurface.batchvertex3fbuffer)
12020                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12021                         else
12022                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12023                 }
12024                 else
12025                 {
12026                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12027                         // fog sky
12028                         GL_BlendFunc(GL_ONE, GL_ZERO);
12029                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12030                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12031                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12032                 }
12033                 RSurf_DrawBatch();
12034                 if (skyrendermasked)
12035                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12036         }
12037         R_Mesh_ResetTextureState();
12038         GL_Color(1, 1, 1, 1);
12039 }
12040
12041 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12042 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12043 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12044 {
12045         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12046                 return;
12047         if (prepass)
12048         {
12049                 // render screenspace normalmap to texture
12050                 GL_DepthMask(true);
12051                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12052                 RSurf_DrawBatch();
12053                 return;
12054         }
12055
12056         // bind lightmap texture
12057
12058         // water/refraction/reflection/camera surfaces have to be handled specially
12059         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12060         {
12061                 int start, end, startplaneindex;
12062                 for (start = 0;start < texturenumsurfaces;start = end)
12063                 {
12064                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12065                         if(startplaneindex < 0)
12066                         {
12067                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12068                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12069                                 end = start + 1;
12070                                 continue;
12071                         }
12072                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12073                                 ;
12074                         // now that we have a batch using the same planeindex, render it
12075                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12076                         {
12077                                 // render water or distortion background
12078                                 GL_DepthMask(true);
12079                                 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));
12080                                 RSurf_DrawBatch();
12081                                 // blend surface on top
12082                                 GL_DepthMask(false);
12083                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12084                                 RSurf_DrawBatch();
12085                         }
12086                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12087                         {
12088                                 // render surface with reflection texture as input
12089                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12090                                 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));
12091                                 RSurf_DrawBatch();
12092                         }
12093                 }
12094                 return;
12095         }
12096
12097         // render surface batch normally
12098         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12099         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12100         RSurf_DrawBatch();
12101 }
12102
12103 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12104 {
12105         // OpenGL 1.3 path - anything not completely ancient
12106         qboolean applycolor;
12107         qboolean applyfog;
12108         int layerindex;
12109         const texturelayer_t *layer;
12110         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);
12111         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12112
12113         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12114         {
12115                 vec4_t layercolor;
12116                 int layertexrgbscale;
12117                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12118                 {
12119                         if (layerindex == 0)
12120                                 GL_AlphaTest(true);
12121                         else
12122                         {
12123                                 GL_AlphaTest(false);
12124                                 GL_DepthFunc(GL_EQUAL);
12125                         }
12126                 }
12127                 GL_DepthMask(layer->depthmask && writedepth);
12128                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12129                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12130                 {
12131                         layertexrgbscale = 4;
12132                         VectorScale(layer->color, 0.25f, layercolor);
12133                 }
12134                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12135                 {
12136                         layertexrgbscale = 2;
12137                         VectorScale(layer->color, 0.5f, layercolor);
12138                 }
12139                 else
12140                 {
12141                         layertexrgbscale = 1;
12142                         VectorScale(layer->color, 1.0f, layercolor);
12143                 }
12144                 layercolor[3] = layer->color[3];
12145                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12146                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12147                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12148                 switch (layer->type)
12149                 {
12150                 case TEXTURELAYERTYPE_LITTEXTURE:
12151                         // single-pass lightmapped texture with 2x rgbscale
12152                         R_Mesh_TexBind(0, r_texture_white);
12153                         R_Mesh_TexMatrix(0, NULL);
12154                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12155                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12156                         R_Mesh_TexBind(1, layer->texture);
12157                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12158                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12159                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12160                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12161                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12162                         else if (FAKELIGHT_ENABLED)
12163                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12164                         else if (rsurface.uselightmaptexture)
12165                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12166                         else
12167                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12168                         break;
12169                 case TEXTURELAYERTYPE_TEXTURE:
12170                         // singletexture unlit texture with transparency support
12171                         R_Mesh_TexBind(0, layer->texture);
12172                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12173                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12174                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12175                         R_Mesh_TexBind(1, 0);
12176                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12177                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12178                         break;
12179                 case TEXTURELAYERTYPE_FOG:
12180                         // singletexture fogging
12181                         if (layer->texture)
12182                         {
12183                                 R_Mesh_TexBind(0, layer->texture);
12184                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12185                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12186                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12187                         }
12188                         else
12189                         {
12190                                 R_Mesh_TexBind(0, 0);
12191                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12192                         }
12193                         R_Mesh_TexBind(1, 0);
12194                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12195                         // generate a color array for the fog pass
12196                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12197                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12198                         RSurf_DrawBatch();
12199                         break;
12200                 default:
12201                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12202                 }
12203         }
12204         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12205         {
12206                 GL_DepthFunc(GL_LEQUAL);
12207                 GL_AlphaTest(false);
12208         }
12209 }
12210
12211 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12212 {
12213         // OpenGL 1.1 - crusty old voodoo path
12214         qboolean applyfog;
12215         int layerindex;
12216         const texturelayer_t *layer;
12217         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);
12218         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12219
12220         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12221         {
12222                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12223                 {
12224                         if (layerindex == 0)
12225                                 GL_AlphaTest(true);
12226                         else
12227                         {
12228                                 GL_AlphaTest(false);
12229                                 GL_DepthFunc(GL_EQUAL);
12230                         }
12231                 }
12232                 GL_DepthMask(layer->depthmask && writedepth);
12233                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12234                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12235                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12236                 switch (layer->type)
12237                 {
12238                 case TEXTURELAYERTYPE_LITTEXTURE:
12239                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12240                         {
12241                                 // two-pass lit texture with 2x rgbscale
12242                                 // first the lightmap pass
12243                                 R_Mesh_TexBind(0, r_texture_white);
12244                                 R_Mesh_TexMatrix(0, NULL);
12245                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12246                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12247                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12248                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12249                                 else if (FAKELIGHT_ENABLED)
12250                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12251                                 else if (rsurface.uselightmaptexture)
12252                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12253                                 else
12254                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12255                                 // then apply the texture to it
12256                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12257                                 R_Mesh_TexBind(0, layer->texture);
12258                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12259                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12260                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12261                                 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);
12262                         }
12263                         else
12264                         {
12265                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12266                                 R_Mesh_TexBind(0, layer->texture);
12267                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12268                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12269                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12270                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12271                                         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);
12272                                 else
12273                                         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);
12274                         }
12275                         break;
12276                 case TEXTURELAYERTYPE_TEXTURE:
12277                         // singletexture unlit texture with transparency support
12278                         R_Mesh_TexBind(0, layer->texture);
12279                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12280                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12281                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12282                         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);
12283                         break;
12284                 case TEXTURELAYERTYPE_FOG:
12285                         // singletexture fogging
12286                         if (layer->texture)
12287                         {
12288                                 R_Mesh_TexBind(0, layer->texture);
12289                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12290                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12291                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12292                         }
12293                         else
12294                         {
12295                                 R_Mesh_TexBind(0, 0);
12296                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12297                         }
12298                         // generate a color array for the fog pass
12299                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12300                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12301                         RSurf_DrawBatch();
12302                         break;
12303                 default:
12304                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12305                 }
12306         }
12307         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12308         {
12309                 GL_DepthFunc(GL_LEQUAL);
12310                 GL_AlphaTest(false);
12311         }
12312 }
12313
12314 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12315 {
12316         int vi;
12317         int j;
12318         r_vertexgeneric_t *batchvertex;
12319         float c[4];
12320
12321 //      R_Mesh_ResetTextureState();
12322         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12323
12324         if(rsurface.texture && rsurface.texture->currentskinframe)
12325         {
12326                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12327                 c[3] *= rsurface.texture->currentalpha;
12328         }
12329         else
12330         {
12331                 c[0] = 1;
12332                 c[1] = 0;
12333                 c[2] = 1;
12334                 c[3] = 1;
12335         }
12336
12337         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12338         {
12339                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12340                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12341                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12342         }
12343
12344         // brighten it up (as texture value 127 means "unlit")
12345         c[0] *= 2 * r_refdef.view.colorscale;
12346         c[1] *= 2 * r_refdef.view.colorscale;
12347         c[2] *= 2 * r_refdef.view.colorscale;
12348
12349         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12350                 c[3] *= r_wateralpha.value;
12351
12352         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12353         {
12354                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12355                 GL_DepthMask(false);
12356         }
12357         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12358         {
12359                 GL_BlendFunc(GL_ONE, GL_ONE);
12360                 GL_DepthMask(false);
12361         }
12362         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12363         {
12364                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12365                 GL_DepthMask(false);
12366         }
12367         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12368         {
12369                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12370                 GL_DepthMask(false);
12371         }
12372         else
12373         {
12374                 GL_BlendFunc(GL_ONE, GL_ZERO);
12375                 GL_DepthMask(writedepth);
12376         }
12377
12378         if (r_showsurfaces.integer == 3)
12379         {
12380                 rsurface.passcolor4f = NULL;
12381
12382                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12383                 {
12384                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12385
12386                         rsurface.passcolor4f = NULL;
12387                         rsurface.passcolor4f_vertexbuffer = 0;
12388                         rsurface.passcolor4f_bufferoffset = 0;
12389                 }
12390                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12391                 {
12392                         qboolean applycolor = true;
12393                         float one = 1.0;
12394
12395                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12396
12397                         r_refdef.lightmapintensity = 1;
12398                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12399                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12400                 }
12401                 else if (FAKELIGHT_ENABLED)
12402                 {
12403                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12404
12405                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12406                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12407                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12408                 }
12409                 else
12410                 {
12411                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12412
12413                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12414                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12415                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12416                 }
12417
12418                 if(!rsurface.passcolor4f)
12419                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12420
12421                 RSurf_DrawBatch_GL11_ApplyAmbient();
12422                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12423                 if(r_refdef.fogenabled)
12424                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12425                 RSurf_DrawBatch_GL11_ClampColor();
12426
12427                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12428                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12429                 RSurf_DrawBatch();
12430         }
12431         else if (!r_refdef.view.showdebug)
12432         {
12433                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12434                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12435                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12436                 {
12437                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12438                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12439                 }
12440                 R_Mesh_PrepareVertices_Generic_Unlock();
12441                 RSurf_DrawBatch();
12442         }
12443         else if (r_showsurfaces.integer == 4)
12444         {
12445                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12446                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12447                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12448                 {
12449                         unsigned char c = vi << 3;
12450                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12451                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12452                 }
12453                 R_Mesh_PrepareVertices_Generic_Unlock();
12454                 RSurf_DrawBatch();
12455         }
12456         else if (r_showsurfaces.integer == 2)
12457         {
12458                 const int *e;
12459                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12460                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12461                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12462                 {
12463                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12464                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12465                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12466                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12467                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12468                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12469                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12470                 }
12471                 R_Mesh_PrepareVertices_Generic_Unlock();
12472                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12473         }
12474         else
12475         {
12476                 int texturesurfaceindex;
12477                 int k;
12478                 const msurface_t *surface;
12479                 unsigned char surfacecolor4ub[4];
12480                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12481                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12482                 vi = 0;
12483                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12484                 {
12485                         surface = texturesurfacelist[texturesurfaceindex];
12486                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12487                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12488                         for (j = 0;j < surface->num_vertices;j++)
12489                         {
12490                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12491                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12492                                 vi++;
12493                         }
12494                 }
12495                 R_Mesh_PrepareVertices_Generic_Unlock();
12496                 RSurf_DrawBatch();
12497         }
12498 }
12499
12500 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12501 {
12502         CHECKGLERROR
12503         RSurf_SetupDepthAndCulling();
12504         if (r_showsurfaces.integer)
12505         {
12506                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12507                 return;
12508         }
12509         switch (vid.renderpath)
12510         {
12511         case RENDERPATH_GL20:
12512         case RENDERPATH_D3D9:
12513         case RENDERPATH_D3D10:
12514         case RENDERPATH_D3D11:
12515         case RENDERPATH_SOFT:
12516         case RENDERPATH_GLES2:
12517                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12518                 break;
12519         case RENDERPATH_GL13:
12520                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12521                 break;
12522         case RENDERPATH_GL11:
12523                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12524                 break;
12525         }
12526         CHECKGLERROR
12527 }
12528
12529 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12530 {
12531         CHECKGLERROR
12532         RSurf_SetupDepthAndCulling();
12533         if (r_showsurfaces.integer)
12534         {
12535                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12536                 return;
12537         }
12538         switch (vid.renderpath)
12539         {
12540         case RENDERPATH_GL20:
12541         case RENDERPATH_D3D9:
12542         case RENDERPATH_D3D10:
12543         case RENDERPATH_D3D11:
12544         case RENDERPATH_SOFT:
12545         case RENDERPATH_GLES2:
12546                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12547                 break;
12548         case RENDERPATH_GL13:
12549                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12550                 break;
12551         case RENDERPATH_GL11:
12552                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12553                 break;
12554         }
12555         CHECKGLERROR
12556 }
12557
12558 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12559 {
12560         int i, j;
12561         int texturenumsurfaces, endsurface;
12562         texture_t *texture;
12563         const msurface_t *surface;
12564 #define MAXBATCH_TRANSPARENTSURFACES 256
12565         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12566
12567         // if the model is static it doesn't matter what value we give for
12568         // wantnormals and wanttangents, so this logic uses only rules applicable
12569         // to a model, knowing that they are meaningless otherwise
12570         if (ent == r_refdef.scene.worldentity)
12571                 RSurf_ActiveWorldEntity();
12572         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12573                 RSurf_ActiveModelEntity(ent, false, false, false);
12574         else
12575         {
12576                 switch (vid.renderpath)
12577                 {
12578                 case RENDERPATH_GL20:
12579                 case RENDERPATH_D3D9:
12580                 case RENDERPATH_D3D10:
12581                 case RENDERPATH_D3D11:
12582                 case RENDERPATH_SOFT:
12583                 case RENDERPATH_GLES2:
12584                         RSurf_ActiveModelEntity(ent, true, true, false);
12585                         break;
12586                 case RENDERPATH_GL13:
12587                 case RENDERPATH_GL11:
12588                         RSurf_ActiveModelEntity(ent, true, false, false);
12589                         break;
12590                 }
12591         }
12592
12593         if (r_transparentdepthmasking.integer)
12594         {
12595                 qboolean setup = false;
12596                 for (i = 0;i < numsurfaces;i = j)
12597                 {
12598                         j = i + 1;
12599                         surface = rsurface.modelsurfaces + surfacelist[i];
12600                         texture = surface->texture;
12601                         rsurface.texture = R_GetCurrentTexture(texture);
12602                         rsurface.lightmaptexture = NULL;
12603                         rsurface.deluxemaptexture = NULL;
12604                         rsurface.uselightmaptexture = false;
12605                         // scan ahead until we find a different texture
12606                         endsurface = min(i + 1024, numsurfaces);
12607                         texturenumsurfaces = 0;
12608                         texturesurfacelist[texturenumsurfaces++] = surface;
12609                         for (;j < endsurface;j++)
12610                         {
12611                                 surface = rsurface.modelsurfaces + surfacelist[j];
12612                                 if (texture != surface->texture)
12613                                         break;
12614                                 texturesurfacelist[texturenumsurfaces++] = surface;
12615                         }
12616                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12617                                 continue;
12618                         // render the range of surfaces as depth
12619                         if (!setup)
12620                         {
12621                                 setup = true;
12622                                 GL_ColorMask(0,0,0,0);
12623                                 GL_Color(1,1,1,1);
12624                                 GL_DepthTest(true);
12625                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12626                                 GL_DepthMask(true);
12627 //                              R_Mesh_ResetTextureState();
12628                                 R_SetupShader_DepthOrShadow();
12629                         }
12630                         RSurf_SetupDepthAndCulling();
12631                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12632                         if (rsurface.batchvertex3fbuffer)
12633                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12634                         else
12635                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12636                         RSurf_DrawBatch();
12637                 }
12638                 if (setup)
12639                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12640         }
12641
12642         for (i = 0;i < numsurfaces;i = j)
12643         {
12644                 j = i + 1;
12645                 surface = rsurface.modelsurfaces + surfacelist[i];
12646                 texture = surface->texture;
12647                 rsurface.texture = R_GetCurrentTexture(texture);
12648                 // scan ahead until we find a different texture
12649                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12650                 texturenumsurfaces = 0;
12651                 texturesurfacelist[texturenumsurfaces++] = surface;
12652                 if(FAKELIGHT_ENABLED)
12653                 {
12654                         rsurface.lightmaptexture = NULL;
12655                         rsurface.deluxemaptexture = NULL;
12656                         rsurface.uselightmaptexture = false;
12657                         for (;j < endsurface;j++)
12658                         {
12659                                 surface = rsurface.modelsurfaces + surfacelist[j];
12660                                 if (texture != surface->texture)
12661                                         break;
12662                                 texturesurfacelist[texturenumsurfaces++] = surface;
12663                         }
12664                 }
12665                 else
12666                 {
12667                         rsurface.lightmaptexture = surface->lightmaptexture;
12668                         rsurface.deluxemaptexture = surface->deluxemaptexture;
12669                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12670                         for (;j < endsurface;j++)
12671                         {
12672                                 surface = rsurface.modelsurfaces + surfacelist[j];
12673                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12674                                         break;
12675                                 texturesurfacelist[texturenumsurfaces++] = surface;
12676                         }
12677                 }
12678                 // render the range of surfaces
12679                 if (ent == r_refdef.scene.worldentity)
12680                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12681                 else
12682                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12683         }
12684         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12685 }
12686
12687 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12688 {
12689         // transparent surfaces get pushed off into the transparent queue
12690         int surfacelistindex;
12691         const msurface_t *surface;
12692         vec3_t tempcenter, center;
12693         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12694         {
12695                 surface = texturesurfacelist[surfacelistindex];
12696                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12697                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12698                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12699                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12700                 if (queueentity->transparent_offset) // transparent offset
12701                 {
12702                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12703                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12704                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12705                 }
12706                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12707         }
12708 }
12709
12710 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12711 {
12712         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12713                 return;
12714         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12715                 return;
12716         RSurf_SetupDepthAndCulling();
12717         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12718         if (rsurface.batchvertex3fbuffer)
12719                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12720         else
12721                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12722         RSurf_DrawBatch();
12723 }
12724
12725 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12726 {
12727         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12728         CHECKGLERROR
12729         if (depthonly)
12730                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12731         else if (prepass)
12732         {
12733                 if (!rsurface.texture->currentnumlayers)
12734                         return;
12735                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12736                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12737                 else
12738                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12739         }
12740         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12741                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12742         else if (!rsurface.texture->currentnumlayers)
12743                 return;
12744         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12745         {
12746                 // in the deferred case, transparent surfaces were queued during prepass
12747                 if (!r_shadow_usingdeferredprepass)
12748                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12749         }
12750         else
12751         {
12752                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12753                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12754         }
12755         CHECKGLERROR
12756 }
12757
12758 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12759 {
12760         int i, j;
12761         texture_t *texture;
12762         R_FrameData_SetMark();
12763         // break the surface list down into batches by texture and use of lightmapping
12764         for (i = 0;i < numsurfaces;i = j)
12765         {
12766                 j = i + 1;
12767                 // texture is the base texture pointer, rsurface.texture is the
12768                 // current frame/skin the texture is directing us to use (for example
12769                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12770                 // use skin 1 instead)
12771                 texture = surfacelist[i]->texture;
12772                 rsurface.texture = R_GetCurrentTexture(texture);
12773                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12774                 {
12775                         // if this texture is not the kind we want, skip ahead to the next one
12776                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12777                                 ;
12778                         continue;
12779                 }
12780                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12781                 {
12782                         rsurface.lightmaptexture = NULL;
12783                         rsurface.deluxemaptexture = NULL;
12784                         rsurface.uselightmaptexture = false;
12785                         // simply scan ahead until we find a different texture or lightmap state
12786                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12787                                 ;
12788                 }
12789                 else
12790                 {
12791                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12792                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12793                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12794                         // simply scan ahead until we find a different texture or lightmap state
12795                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12796                                 ;
12797                 }
12798                 // render the range of surfaces
12799                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12800         }
12801         R_FrameData_ReturnToMark();
12802 }
12803
12804 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12805 {
12806         CHECKGLERROR
12807         if (depthonly)
12808                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12809         else if (prepass)
12810         {
12811                 if (!rsurface.texture->currentnumlayers)
12812                         return;
12813                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12814                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12815                 else
12816                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12817         }
12818         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12819                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12820         else if (!rsurface.texture->currentnumlayers)
12821                 return;
12822         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12823         {
12824                 // in the deferred case, transparent surfaces were queued during prepass
12825                 if (!r_shadow_usingdeferredprepass)
12826                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12827         }
12828         else
12829         {
12830                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12831                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12832         }
12833         CHECKGLERROR
12834 }
12835
12836 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12837 {
12838         int i, j;
12839         texture_t *texture;
12840         R_FrameData_SetMark();
12841         // break the surface list down into batches by texture and use of lightmapping
12842         for (i = 0;i < numsurfaces;i = j)
12843         {
12844                 j = i + 1;
12845                 // texture is the base texture pointer, rsurface.texture is the
12846                 // current frame/skin the texture is directing us to use (for example
12847                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12848                 // use skin 1 instead)
12849                 texture = surfacelist[i]->texture;
12850                 rsurface.texture = R_GetCurrentTexture(texture);
12851                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12852                 {
12853                         // if this texture is not the kind we want, skip ahead to the next one
12854                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12855                                 ;
12856                         continue;
12857                 }
12858                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12859                 {
12860                         rsurface.lightmaptexture = NULL;
12861                         rsurface.deluxemaptexture = NULL;
12862                         rsurface.uselightmaptexture = false;
12863                         // simply scan ahead until we find a different texture or lightmap state
12864                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12865                                 ;
12866                 }
12867                 else
12868                 {
12869                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12870                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12871                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12872                         // simply scan ahead until we find a different texture or lightmap state
12873                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12874                                 ;
12875                 }
12876                 // render the range of surfaces
12877                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12878         }
12879         R_FrameData_ReturnToMark();
12880 }
12881
12882 float locboxvertex3f[6*4*3] =
12883 {
12884         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12885         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12886         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12887         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12888         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12889         1,0,0, 0,0,0, 0,1,0, 1,1,0
12890 };
12891
12892 unsigned short locboxelements[6*2*3] =
12893 {
12894          0, 1, 2, 0, 2, 3,
12895          4, 5, 6, 4, 6, 7,
12896          8, 9,10, 8,10,11,
12897         12,13,14, 12,14,15,
12898         16,17,18, 16,18,19,
12899         20,21,22, 20,22,23
12900 };
12901
12902 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12903 {
12904         int i, j;
12905         cl_locnode_t *loc = (cl_locnode_t *)ent;
12906         vec3_t mins, size;
12907         float vertex3f[6*4*3];
12908         CHECKGLERROR
12909         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12910         GL_DepthMask(false);
12911         GL_DepthRange(0, 1);
12912         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12913         GL_DepthTest(true);
12914         GL_CullFace(GL_NONE);
12915         R_EntityMatrix(&identitymatrix);
12916
12917 //      R_Mesh_ResetTextureState();
12918
12919         i = surfacelist[0];
12920         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12921                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12922                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12923                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12924
12925         if (VectorCompare(loc->mins, loc->maxs))
12926         {
12927                 VectorSet(size, 2, 2, 2);
12928                 VectorMA(loc->mins, -0.5f, size, mins);
12929         }
12930         else
12931         {
12932                 VectorCopy(loc->mins, mins);
12933                 VectorSubtract(loc->maxs, loc->mins, size);
12934         }
12935
12936         for (i = 0;i < 6*4*3;)
12937                 for (j = 0;j < 3;j++, i++)
12938                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12939
12940         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12941         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12942         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12943 }
12944
12945 void R_DrawLocs(void)
12946 {
12947         int index;
12948         cl_locnode_t *loc, *nearestloc;
12949         vec3_t center;
12950         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12951         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12952         {
12953                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12954                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12955         }
12956 }
12957
12958 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12959 {
12960         if (decalsystem->decals)
12961                 Mem_Free(decalsystem->decals);
12962         memset(decalsystem, 0, sizeof(*decalsystem));
12963 }
12964
12965 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)
12966 {
12967         tridecal_t *decal;
12968         tridecal_t *decals;
12969         int i;
12970
12971         // expand or initialize the system
12972         if (decalsystem->maxdecals <= decalsystem->numdecals)
12973         {
12974                 decalsystem_t old = *decalsystem;
12975                 qboolean useshortelements;
12976                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12977                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12978                 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)));
12979                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12980                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12981                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12982                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12983                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12984                 if (decalsystem->numdecals)
12985                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12986                 if (old.decals)
12987                         Mem_Free(old.decals);
12988                 for (i = 0;i < decalsystem->maxdecals*3;i++)
12989                         decalsystem->element3i[i] = i;
12990                 if (useshortelements)
12991                         for (i = 0;i < decalsystem->maxdecals*3;i++)
12992                                 decalsystem->element3s[i] = i;
12993         }
12994
12995         // grab a decal and search for another free slot for the next one
12996         decals = decalsystem->decals;
12997         decal = decalsystem->decals + (i = decalsystem->freedecal++);
12998         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12999                 ;
13000         decalsystem->freedecal = i;
13001         if (decalsystem->numdecals <= i)
13002                 decalsystem->numdecals = i + 1;
13003
13004         // initialize the decal
13005         decal->lived = 0;
13006         decal->triangleindex = triangleindex;
13007         decal->surfaceindex = surfaceindex;
13008         decal->decalsequence = decalsequence;
13009         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13010         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13011         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13012         decal->color4ub[0][3] = 255;
13013         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13014         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13015         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13016         decal->color4ub[1][3] = 255;
13017         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13018         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13019         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13020         decal->color4ub[2][3] = 255;
13021         decal->vertex3f[0][0] = v0[0];
13022         decal->vertex3f[0][1] = v0[1];
13023         decal->vertex3f[0][2] = v0[2];
13024         decal->vertex3f[1][0] = v1[0];
13025         decal->vertex3f[1][1] = v1[1];
13026         decal->vertex3f[1][2] = v1[2];
13027         decal->vertex3f[2][0] = v2[0];
13028         decal->vertex3f[2][1] = v2[1];
13029         decal->vertex3f[2][2] = v2[2];
13030         decal->texcoord2f[0][0] = t0[0];
13031         decal->texcoord2f[0][1] = t0[1];
13032         decal->texcoord2f[1][0] = t1[0];
13033         decal->texcoord2f[1][1] = t1[1];
13034         decal->texcoord2f[2][0] = t2[0];
13035         decal->texcoord2f[2][1] = t2[1];
13036 }
13037
13038 extern cvar_t cl_decals_bias;
13039 extern cvar_t cl_decals_models;
13040 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13041 // baseparms, parms, temps
13042 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)
13043 {
13044         int cornerindex;
13045         int index;
13046         float v[9][3];
13047         const float *vertex3f;
13048         int numpoints;
13049         float points[2][9][3];
13050         float temp[3];
13051         float tc[9][2];
13052         float f;
13053         float c[9][4];
13054         const int *e;
13055
13056         e = rsurface.modelelement3i + 3*triangleindex;
13057
13058         vertex3f = rsurface.modelvertex3f;
13059
13060         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13061         {
13062                 index = 3*e[cornerindex];
13063                 VectorCopy(vertex3f + index, v[cornerindex]);
13064         }
13065         // cull backfaces
13066         //TriangleNormal(v[0], v[1], v[2], normal);
13067         //if (DotProduct(normal, localnormal) < 0.0f)
13068         //      continue;
13069         // clip by each of the box planes formed from the projection matrix
13070         // if anything survives, we emit the decal
13071         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]);
13072         if (numpoints < 3)
13073                 return;
13074         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]);
13075         if (numpoints < 3)
13076                 return;
13077         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]);
13078         if (numpoints < 3)
13079                 return;
13080         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]);
13081         if (numpoints < 3)
13082                 return;
13083         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]);
13084         if (numpoints < 3)
13085                 return;
13086         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]);
13087         if (numpoints < 3)
13088                 return;
13089         // some part of the triangle survived, so we have to accept it...
13090         if (dynamic)
13091         {
13092                 // dynamic always uses the original triangle
13093                 numpoints = 3;
13094                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13095                 {
13096                         index = 3*e[cornerindex];
13097                         VectorCopy(vertex3f + index, v[cornerindex]);
13098                 }
13099         }
13100         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13101         {
13102                 // convert vertex positions to texcoords
13103                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13104                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13105                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13106                 // calculate distance fade from the projection origin
13107                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13108                 f = bound(0.0f, f, 1.0f);
13109                 c[cornerindex][0] = r * f;
13110                 c[cornerindex][1] = g * f;
13111                 c[cornerindex][2] = b * f;
13112                 c[cornerindex][3] = 1.0f;
13113                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13114         }
13115         if (dynamic)
13116                 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);
13117         else
13118                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13119                         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);
13120 }
13121 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)
13122 {
13123         matrix4x4_t projection;
13124         decalsystem_t *decalsystem;
13125         qboolean dynamic;
13126         dp_model_t *model;
13127         const msurface_t *surface;
13128         const msurface_t *surfaces;
13129         const int *surfacelist;
13130         const texture_t *texture;
13131         int numtriangles;
13132         int numsurfacelist;
13133         int surfacelistindex;
13134         int surfaceindex;
13135         int triangleindex;
13136         float localorigin[3];
13137         float localnormal[3];
13138         float localmins[3];
13139         float localmaxs[3];
13140         float localsize;
13141         //float normal[3];
13142         float planes[6][4];
13143         float angles[3];
13144         bih_t *bih;
13145         int bih_triangles_count;
13146         int bih_triangles[256];
13147         int bih_surfaces[256];
13148
13149         decalsystem = &ent->decalsystem;
13150         model = ent->model;
13151         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13152         {
13153                 R_DecalSystem_Reset(&ent->decalsystem);
13154                 return;
13155         }
13156
13157         if (!model->brush.data_leafs && !cl_decals_models.integer)
13158         {
13159                 if (decalsystem->model)
13160                         R_DecalSystem_Reset(decalsystem);
13161                 return;
13162         }
13163
13164         if (decalsystem->model != model)
13165                 R_DecalSystem_Reset(decalsystem);
13166         decalsystem->model = model;
13167
13168         RSurf_ActiveModelEntity(ent, false, false, false);
13169
13170         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13171         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13172         VectorNormalize(localnormal);
13173         localsize = worldsize*rsurface.inversematrixscale;
13174         localmins[0] = localorigin[0] - localsize;
13175         localmins[1] = localorigin[1] - localsize;
13176         localmins[2] = localorigin[2] - localsize;
13177         localmaxs[0] = localorigin[0] + localsize;
13178         localmaxs[1] = localorigin[1] + localsize;
13179         localmaxs[2] = localorigin[2] + localsize;
13180
13181         //VectorCopy(localnormal, planes[4]);
13182         //VectorVectors(planes[4], planes[2], planes[0]);
13183         AnglesFromVectors(angles, localnormal, NULL, false);
13184         AngleVectors(angles, planes[0], planes[2], planes[4]);
13185         VectorNegate(planes[0], planes[1]);
13186         VectorNegate(planes[2], planes[3]);
13187         VectorNegate(planes[4], planes[5]);
13188         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13189         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13190         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13191         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13192         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13193         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13194
13195 #if 1
13196 // works
13197 {
13198         matrix4x4_t forwardprojection;
13199         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13200         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13201 }
13202 #else
13203 // broken
13204 {
13205         float projectionvector[4][3];
13206         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13207         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13208         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13209         projectionvector[0][0] = planes[0][0] * ilocalsize;
13210         projectionvector[0][1] = planes[1][0] * ilocalsize;
13211         projectionvector[0][2] = planes[2][0] * ilocalsize;
13212         projectionvector[1][0] = planes[0][1] * ilocalsize;
13213         projectionvector[1][1] = planes[1][1] * ilocalsize;
13214         projectionvector[1][2] = planes[2][1] * ilocalsize;
13215         projectionvector[2][0] = planes[0][2] * ilocalsize;
13216         projectionvector[2][1] = planes[1][2] * ilocalsize;
13217         projectionvector[2][2] = planes[2][2] * ilocalsize;
13218         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13219         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13220         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13221         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13222 }
13223 #endif
13224
13225         dynamic = model->surfmesh.isanimated;
13226         numsurfacelist = model->nummodelsurfaces;
13227         surfacelist = model->sortedmodelsurfaces;
13228         surfaces = model->data_surfaces;
13229
13230         bih = NULL;
13231         bih_triangles_count = -1;
13232         if(!dynamic)
13233         {
13234                 if(model->render_bih.numleafs)
13235                         bih = &model->render_bih;
13236                 else if(model->collision_bih.numleafs)
13237                         bih = &model->collision_bih;
13238         }
13239         if(bih)
13240                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13241         if(bih_triangles_count == 0)
13242                 return;
13243         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13244                 return;
13245         if(bih_triangles_count > 0)
13246         {
13247                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13248                 {
13249                         surfaceindex = bih_surfaces[triangleindex];
13250                         surface = surfaces + surfaceindex;
13251                         texture = surface->texture;
13252                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13253                                 continue;
13254                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13255                                 continue;
13256                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13257                 }
13258         }
13259         else
13260         {
13261                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13262                 {
13263                         surfaceindex = surfacelist[surfacelistindex];
13264                         surface = surfaces + surfaceindex;
13265                         // check cull box first because it rejects more than any other check
13266                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13267                                 continue;
13268                         // skip transparent surfaces
13269                         texture = surface->texture;
13270                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13271                                 continue;
13272                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13273                                 continue;
13274                         numtriangles = surface->num_triangles;
13275                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13276                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13277                 }
13278         }
13279 }
13280
13281 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13282 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)
13283 {
13284         int renderentityindex;
13285         float worldmins[3];
13286         float worldmaxs[3];
13287         entity_render_t *ent;
13288
13289         if (!cl_decals_newsystem.integer)
13290                 return;
13291
13292         worldmins[0] = worldorigin[0] - worldsize;
13293         worldmins[1] = worldorigin[1] - worldsize;
13294         worldmins[2] = worldorigin[2] - worldsize;
13295         worldmaxs[0] = worldorigin[0] + worldsize;
13296         worldmaxs[1] = worldorigin[1] + worldsize;
13297         worldmaxs[2] = worldorigin[2] + worldsize;
13298
13299         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13300
13301         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13302         {
13303                 ent = r_refdef.scene.entities[renderentityindex];
13304                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13305                         continue;
13306
13307                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13308         }
13309 }
13310
13311 typedef struct r_decalsystem_splatqueue_s
13312 {
13313         vec3_t worldorigin;
13314         vec3_t worldnormal;
13315         float color[4];
13316         float tcrange[4];
13317         float worldsize;
13318         int decalsequence;
13319 }
13320 r_decalsystem_splatqueue_t;
13321
13322 int r_decalsystem_numqueued = 0;
13323 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13324
13325 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)
13326 {
13327         r_decalsystem_splatqueue_t *queue;
13328
13329         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13330                 return;
13331
13332         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13333         VectorCopy(worldorigin, queue->worldorigin);
13334         VectorCopy(worldnormal, queue->worldnormal);
13335         Vector4Set(queue->color, r, g, b, a);
13336         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13337         queue->worldsize = worldsize;
13338         queue->decalsequence = cl.decalsequence++;
13339 }
13340
13341 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13342 {
13343         int i;
13344         r_decalsystem_splatqueue_t *queue;
13345
13346         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13347                 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);
13348         r_decalsystem_numqueued = 0;
13349 }
13350
13351 extern cvar_t cl_decals_max;
13352 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13353 {
13354         int i;
13355         decalsystem_t *decalsystem = &ent->decalsystem;
13356         int numdecals;
13357         int killsequence;
13358         tridecal_t *decal;
13359         float frametime;
13360         float lifetime;
13361
13362         if (!decalsystem->numdecals)
13363                 return;
13364
13365         if (r_showsurfaces.integer)
13366                 return;
13367
13368         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13369         {
13370                 R_DecalSystem_Reset(decalsystem);
13371                 return;
13372         }
13373
13374         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13375         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13376
13377         if (decalsystem->lastupdatetime)
13378                 frametime = (cl.time - decalsystem->lastupdatetime);
13379         else
13380                 frametime = 0;
13381         decalsystem->lastupdatetime = cl.time;
13382         decal = decalsystem->decals;
13383         numdecals = decalsystem->numdecals;
13384
13385         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13386         {
13387                 if (decal->color4ub[0][3])
13388                 {
13389                         decal->lived += frametime;
13390                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13391                         {
13392                                 memset(decal, 0, sizeof(*decal));
13393                                 if (decalsystem->freedecal > i)
13394                                         decalsystem->freedecal = i;
13395                         }
13396                 }
13397         }
13398         decal = decalsystem->decals;
13399         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13400                 numdecals--;
13401
13402         // collapse the array by shuffling the tail decals into the gaps
13403         for (;;)
13404         {
13405                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13406                         decalsystem->freedecal++;
13407                 if (decalsystem->freedecal == numdecals)
13408                         break;
13409                 decal[decalsystem->freedecal] = decal[--numdecals];
13410         }
13411
13412         decalsystem->numdecals = numdecals;
13413
13414         if (numdecals <= 0)
13415         {
13416                 // if there are no decals left, reset decalsystem
13417                 R_DecalSystem_Reset(decalsystem);
13418         }
13419 }
13420
13421 extern skinframe_t *decalskinframe;
13422 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13423 {
13424         int i;
13425         decalsystem_t *decalsystem = &ent->decalsystem;
13426         int numdecals;
13427         tridecal_t *decal;
13428         float faderate;
13429         float alpha;
13430         float *v3f;
13431         float *c4f;
13432         float *t2f;
13433         const int *e;
13434         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13435         int numtris = 0;
13436
13437         numdecals = decalsystem->numdecals;
13438         if (!numdecals)
13439                 return;
13440
13441         if (r_showsurfaces.integer)
13442                 return;
13443
13444         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13445         {
13446                 R_DecalSystem_Reset(decalsystem);
13447                 return;
13448         }
13449
13450         // if the model is static it doesn't matter what value we give for
13451         // wantnormals and wanttangents, so this logic uses only rules applicable
13452         // to a model, knowing that they are meaningless otherwise
13453         if (ent == r_refdef.scene.worldentity)
13454                 RSurf_ActiveWorldEntity();
13455         else
13456                 RSurf_ActiveModelEntity(ent, false, false, false);
13457
13458         decalsystem->lastupdatetime = cl.time;
13459         decal = decalsystem->decals;
13460
13461         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13462
13463         // update vertex positions for animated models
13464         v3f = decalsystem->vertex3f;
13465         c4f = decalsystem->color4f;
13466         t2f = decalsystem->texcoord2f;
13467         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13468         {
13469                 if (!decal->color4ub[0][3])
13470                         continue;
13471
13472                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13473                         continue;
13474
13475                 // update color values for fading decals
13476                 if (decal->lived >= cl_decals_time.value)
13477                 {
13478                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13479                         alpha *= (1.0f/255.0f);
13480                 }
13481                 else
13482                         alpha = 1.0f/255.0f;
13483
13484                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13485                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13486                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13487                 c4f[ 3] = 1;
13488                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13489                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13490                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13491                 c4f[ 7] = 1;
13492                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13493                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13494                 c4f[10] = decal->color4ub[2][2] * alpha;
13495                 c4f[11] = 1;
13496
13497                 t2f[0] = decal->texcoord2f[0][0];
13498                 t2f[1] = decal->texcoord2f[0][1];
13499                 t2f[2] = decal->texcoord2f[1][0];
13500                 t2f[3] = decal->texcoord2f[1][1];
13501                 t2f[4] = decal->texcoord2f[2][0];
13502                 t2f[5] = decal->texcoord2f[2][1];
13503
13504                 // update vertex positions for animated models
13505                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13506                 {
13507                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13508                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13509                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13510                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13511                 }
13512                 else
13513                 {
13514                         VectorCopy(decal->vertex3f[0], v3f);
13515                         VectorCopy(decal->vertex3f[1], v3f + 3);
13516                         VectorCopy(decal->vertex3f[2], v3f + 6);
13517                 }
13518
13519                 if (r_refdef.fogenabled)
13520                 {
13521                         alpha = RSurf_FogVertex(v3f);
13522                         VectorScale(c4f, alpha, c4f);
13523                         alpha = RSurf_FogVertex(v3f + 3);
13524                         VectorScale(c4f + 4, alpha, c4f + 4);
13525                         alpha = RSurf_FogVertex(v3f + 6);
13526                         VectorScale(c4f + 8, alpha, c4f + 8);
13527                 }
13528
13529                 v3f += 9;
13530                 c4f += 12;
13531                 t2f += 6;
13532                 numtris++;
13533         }
13534
13535         if (numtris > 0)
13536         {
13537                 r_refdef.stats.drawndecals += numtris;
13538
13539                 // now render the decals all at once
13540                 // (this assumes they all use one particle font texture!)
13541                 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);
13542 //              R_Mesh_ResetTextureState();
13543                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13544                 GL_DepthMask(false);
13545                 GL_DepthRange(0, 1);
13546                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13547                 GL_DepthTest(true);
13548                 GL_CullFace(GL_NONE);
13549                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13550                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13551                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13552         }
13553 }
13554
13555 static void R_DrawModelDecals(void)
13556 {
13557         int i, numdecals;
13558
13559         // fade faster when there are too many decals
13560         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13561         for (i = 0;i < r_refdef.scene.numentities;i++)
13562                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13563
13564         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13565         for (i = 0;i < r_refdef.scene.numentities;i++)
13566                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13567                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13568
13569         R_DecalSystem_ApplySplatEntitiesQueue();
13570
13571         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13572         for (i = 0;i < r_refdef.scene.numentities;i++)
13573                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13574
13575         r_refdef.stats.totaldecals += numdecals;
13576
13577         if (r_showsurfaces.integer)
13578                 return;
13579
13580         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13581
13582         for (i = 0;i < r_refdef.scene.numentities;i++)
13583         {
13584                 if (!r_refdef.viewcache.entityvisible[i])
13585                         continue;
13586                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13587                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13588         }
13589 }
13590
13591 extern cvar_t mod_collision_bih;
13592 void R_DrawDebugModel(void)
13593 {
13594         entity_render_t *ent = rsurface.entity;
13595         int i, j, k, l, flagsmask;
13596         const msurface_t *surface;
13597         dp_model_t *model = ent->model;
13598         vec3_t v;
13599
13600         switch(vid.renderpath)
13601         {
13602         case RENDERPATH_GL11:
13603         case RENDERPATH_GL13:
13604         case RENDERPATH_GL20:
13605                 break;
13606         case RENDERPATH_D3D9:
13607                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13608                 return;
13609         case RENDERPATH_D3D10:
13610                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13611                 return;
13612         case RENDERPATH_D3D11:
13613                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13614                 return;
13615         case RENDERPATH_SOFT:
13616                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13617                 return;
13618         case RENDERPATH_GLES2:
13619                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13620                 return;
13621         }
13622
13623         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13624
13625 //      R_Mesh_ResetTextureState();
13626         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13627         GL_DepthRange(0, 1);
13628         GL_DepthTest(!r_showdisabledepthtest.integer);
13629         GL_DepthMask(false);
13630         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13631
13632         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13633         {
13634                 int triangleindex;
13635                 int bihleafindex;
13636                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13637                 const q3mbrush_t *brush;
13638                 const bih_t *bih = &model->collision_bih;
13639                 const bih_leaf_t *bihleaf;
13640                 float vertex3f[3][3];
13641                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13642                 cullbox = false;
13643                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13644                 {
13645                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13646                                 continue;
13647                         switch (bihleaf->type)
13648                         {
13649                         case BIH_BRUSH:
13650                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13651                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13652                                 {
13653                                         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);
13654                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13655                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13656                                 }
13657                                 break;
13658                         case BIH_COLLISIONTRIANGLE:
13659                                 triangleindex = bihleaf->itemindex;
13660                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13661                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13662                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13663                                 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);
13664                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13665                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13666                                 break;
13667                         case BIH_RENDERTRIANGLE:
13668                                 triangleindex = bihleaf->itemindex;
13669                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13670                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13671                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13672                                 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);
13673                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13674                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13675                                 break;
13676                         }
13677                 }
13678         }
13679
13680         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13681
13682         if (r_showtris.integer || (r_shownormals.value != 0))
13683         {
13684                 if (r_showdisabledepthtest.integer)
13685                 {
13686                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13687                         GL_DepthMask(false);
13688                 }
13689                 else
13690                 {
13691                         GL_BlendFunc(GL_ONE, GL_ZERO);
13692                         GL_DepthMask(true);
13693                 }
13694                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13695                 {
13696                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13697                                 continue;
13698                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13699                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13700                         {
13701                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13702                                 if (r_showtris.value > 0)
13703                                 {
13704                                         if (!rsurface.texture->currentlayers->depthmask)
13705                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13706                                         else if (ent == r_refdef.scene.worldentity)
13707                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13708                                         else
13709                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13710                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13711                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13712                                         RSurf_DrawBatch();
13713                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13714                                         CHECKGLERROR
13715                                 }
13716                                 if (r_shownormals.value < 0)
13717                                 {
13718                                         qglBegin(GL_LINES);
13719                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13720                                         {
13721                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13722                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13723                                                 qglVertex3f(v[0], v[1], v[2]);
13724                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13725                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13726                                                 qglVertex3f(v[0], v[1], v[2]);
13727                                         }
13728                                         qglEnd();
13729                                         CHECKGLERROR
13730                                 }
13731                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13732                                 {
13733                                         qglBegin(GL_LINES);
13734                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13735                                         {
13736                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13737                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13738                                                 qglVertex3f(v[0], v[1], v[2]);
13739                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13740                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13741                                                 qglVertex3f(v[0], v[1], v[2]);
13742                                         }
13743                                         qglEnd();
13744                                         CHECKGLERROR
13745                                         qglBegin(GL_LINES);
13746                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13747                                         {
13748                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13749                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13750                                                 qglVertex3f(v[0], v[1], v[2]);
13751                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13752                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13753                                                 qglVertex3f(v[0], v[1], v[2]);
13754                                         }
13755                                         qglEnd();
13756                                         CHECKGLERROR
13757                                         qglBegin(GL_LINES);
13758                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13759                                         {
13760                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13761                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13762                                                 qglVertex3f(v[0], v[1], v[2]);
13763                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13764                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13765                                                 qglVertex3f(v[0], v[1], v[2]);
13766                                         }
13767                                         qglEnd();
13768                                         CHECKGLERROR
13769                                 }
13770                         }
13771                 }
13772                 rsurface.texture = NULL;
13773         }
13774 }
13775
13776 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13777 int r_maxsurfacelist = 0;
13778 const msurface_t **r_surfacelist = NULL;
13779 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13780 {
13781         int i, j, endj, flagsmask;
13782         dp_model_t *model = r_refdef.scene.worldmodel;
13783         msurface_t *surfaces;
13784         unsigned char *update;
13785         int numsurfacelist = 0;
13786         if (model == NULL)
13787                 return;
13788
13789         if (r_maxsurfacelist < model->num_surfaces)
13790         {
13791                 r_maxsurfacelist = model->num_surfaces;
13792                 if (r_surfacelist)
13793                         Mem_Free((msurface_t**)r_surfacelist);
13794                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13795         }
13796
13797         RSurf_ActiveWorldEntity();
13798
13799         surfaces = model->data_surfaces;
13800         update = model->brushq1.lightmapupdateflags;
13801
13802         // update light styles on this submodel
13803         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13804         {
13805                 model_brush_lightstyleinfo_t *style;
13806                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13807                 {
13808                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13809                         {
13810                                 int *list = style->surfacelist;
13811                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13812                                 for (j = 0;j < style->numsurfaces;j++)
13813                                         update[list[j]] = true;
13814                         }
13815                 }
13816         }
13817
13818         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13819
13820         if (debug)
13821         {
13822                 R_DrawDebugModel();
13823                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13824                 return;
13825         }
13826
13827         rsurface.lightmaptexture = NULL;
13828         rsurface.deluxemaptexture = NULL;
13829         rsurface.uselightmaptexture = false;
13830         rsurface.texture = NULL;
13831         rsurface.rtlight = NULL;
13832         numsurfacelist = 0;
13833         // add visible surfaces to draw list
13834         for (i = 0;i < model->nummodelsurfaces;i++)
13835         {
13836                 j = model->sortedmodelsurfaces[i];
13837                 if (r_refdef.viewcache.world_surfacevisible[j])
13838                         r_surfacelist[numsurfacelist++] = surfaces + j;
13839         }
13840         // update lightmaps if needed
13841         if (model->brushq1.firstrender)
13842         {
13843                 model->brushq1.firstrender = false;
13844                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13845                         if (update[j])
13846                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13847         }
13848         else if (update)
13849         {
13850                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13851                         if (r_refdef.viewcache.world_surfacevisible[j])
13852                                 if (update[j])
13853                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13854         }
13855         // don't do anything if there were no surfaces
13856         if (!numsurfacelist)
13857         {
13858                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13859                 return;
13860         }
13861         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13862
13863         // add to stats if desired
13864         if (r_speeds.integer && !skysurfaces && !depthonly)
13865         {
13866                 r_refdef.stats.world_surfaces += numsurfacelist;
13867                 for (j = 0;j < numsurfacelist;j++)
13868                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13869         }
13870
13871         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13872 }
13873
13874 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13875 {
13876         int i, j, endj, flagsmask;
13877         dp_model_t *model = ent->model;
13878         msurface_t *surfaces;
13879         unsigned char *update;
13880         int numsurfacelist = 0;
13881         if (model == NULL)
13882                 return;
13883
13884         if (r_maxsurfacelist < model->num_surfaces)
13885         {
13886                 r_maxsurfacelist = model->num_surfaces;
13887                 if (r_surfacelist)
13888                         Mem_Free((msurface_t **)r_surfacelist);
13889                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13890         }
13891
13892         // if the model is static it doesn't matter what value we give for
13893         // wantnormals and wanttangents, so this logic uses only rules applicable
13894         // to a model, knowing that they are meaningless otherwise
13895         if (ent == r_refdef.scene.worldentity)
13896                 RSurf_ActiveWorldEntity();
13897         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13898                 RSurf_ActiveModelEntity(ent, false, false, false);
13899         else if (prepass)
13900                 RSurf_ActiveModelEntity(ent, true, true, true);
13901         else if (depthonly)
13902         {
13903                 switch (vid.renderpath)
13904                 {
13905                 case RENDERPATH_GL20:
13906                 case RENDERPATH_D3D9:
13907                 case RENDERPATH_D3D10:
13908                 case RENDERPATH_D3D11:
13909                 case RENDERPATH_SOFT:
13910                 case RENDERPATH_GLES2:
13911                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13912                         break;
13913                 case RENDERPATH_GL13:
13914                 case RENDERPATH_GL11:
13915                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13916                         break;
13917                 }
13918         }
13919         else
13920         {
13921                 switch (vid.renderpath)
13922                 {
13923                 case RENDERPATH_GL20:
13924                 case RENDERPATH_D3D9:
13925                 case RENDERPATH_D3D10:
13926                 case RENDERPATH_D3D11:
13927                 case RENDERPATH_SOFT:
13928                 case RENDERPATH_GLES2:
13929                         RSurf_ActiveModelEntity(ent, true, true, false);
13930                         break;
13931                 case RENDERPATH_GL13:
13932                 case RENDERPATH_GL11:
13933                         RSurf_ActiveModelEntity(ent, true, false, false);
13934                         break;
13935                 }
13936         }
13937
13938         surfaces = model->data_surfaces;
13939         update = model->brushq1.lightmapupdateflags;
13940
13941         // update light styles
13942         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13943         {
13944                 model_brush_lightstyleinfo_t *style;
13945                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13946                 {
13947                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13948                         {
13949                                 int *list = style->surfacelist;
13950                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13951                                 for (j = 0;j < style->numsurfaces;j++)
13952                                         update[list[j]] = true;
13953                         }
13954                 }
13955         }
13956
13957         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13958
13959         if (debug)
13960         {
13961                 R_DrawDebugModel();
13962                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13963                 return;
13964         }
13965
13966         rsurface.lightmaptexture = NULL;
13967         rsurface.deluxemaptexture = NULL;
13968         rsurface.uselightmaptexture = false;
13969         rsurface.texture = NULL;
13970         rsurface.rtlight = NULL;
13971         numsurfacelist = 0;
13972         // add visible surfaces to draw list
13973         for (i = 0;i < model->nummodelsurfaces;i++)
13974                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13975         // don't do anything if there were no surfaces
13976         if (!numsurfacelist)
13977         {
13978                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13979                 return;
13980         }
13981         // update lightmaps if needed
13982         if (update)
13983         {
13984                 int updated = 0;
13985                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13986                 {
13987                         if (update[j])
13988                         {
13989                                 updated++;
13990                                 R_BuildLightMap(ent, surfaces + j);
13991                         }
13992                 }
13993         }
13994         if (update)
13995                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13996                         if (update[j])
13997                                 R_BuildLightMap(ent, surfaces + j);
13998         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13999
14000         // add to stats if desired
14001         if (r_speeds.integer && !skysurfaces && !depthonly)
14002         {
14003                 r_refdef.stats.entities_surfaces += numsurfacelist;
14004                 for (j = 0;j < numsurfacelist;j++)
14005                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14006         }
14007
14008         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14009 }
14010
14011 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14012 {
14013         static texture_t texture;
14014         static msurface_t surface;
14015         const msurface_t *surfacelist = &surface;
14016
14017         // fake enough texture and surface state to render this geometry
14018
14019         texture.update_lastrenderframe = -1; // regenerate this texture
14020         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14021         texture.currentskinframe = skinframe;
14022         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14023         texture.offsetmapping = OFFSETMAPPING_OFF;
14024         texture.offsetscale = 1;
14025         texture.specularscalemod = 1;
14026         texture.specularpowermod = 1;
14027
14028         surface.texture = &texture;
14029         surface.num_triangles = numtriangles;
14030         surface.num_firsttriangle = firsttriangle;
14031         surface.num_vertices = numvertices;
14032         surface.num_firstvertex = firstvertex;
14033
14034         // now render it
14035         rsurface.texture = R_GetCurrentTexture(surface.texture);
14036         rsurface.lightmaptexture = NULL;
14037         rsurface.deluxemaptexture = NULL;
14038         rsurface.uselightmaptexture = false;
14039         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14040 }
14041
14042 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)
14043 {
14044         static msurface_t surface;
14045         const msurface_t *surfacelist = &surface;
14046
14047         // fake enough texture and surface state to render this geometry
14048         surface.texture = texture;
14049         surface.num_triangles = numtriangles;
14050         surface.num_firsttriangle = firsttriangle;
14051         surface.num_vertices = numvertices;
14052         surface.num_firstvertex = firstvertex;
14053
14054         // now render it
14055         rsurface.texture = R_GetCurrentTexture(surface.texture);
14056         rsurface.lightmaptexture = NULL;
14057         rsurface.deluxemaptexture = NULL;
14058         rsurface.uselightmaptexture = false;
14059         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14060 }