]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
implemented r_shadow_particletrace cvar which enables an exceptionally
[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, FOGWIDTH, 1);
516                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, FOGWIDTH, 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 "#ifdef MODE_DEFERREDBOUNCELIGHT\n"
1062 "varying highp vec4 ModelViewPosition;\n"
1063 "varying highp vec4 LightOriginInvRadius;\n"
1064 "varying mediump vec4 LightColor;\n"
1065 "#endif\n"
1066 "\n"
1067 "#ifdef MODE_LIGHTSOURCE\n"
1068 "uniform highp vec3 LightPosition;\n"
1069 "#endif\n"
1070 "uniform highp vec3 EyePosition;\n"
1071 "#ifdef MODE_LIGHTDIRECTION\n"
1072 "uniform highp vec3 LightDir;\n"
1073 "#endif\n"
1074 "uniform highp vec4 FogPlane;\n"
1075 "\n"
1076 "#ifdef USESHADOWMAPORTHO\n"
1077 "varying mediump vec3 ShadowMapTC;\n"
1078 "#endif\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 "#ifdef MODE_DEFERREDBOUNCELIGHT\n"
1132 "uniform sampler2D Texture_ScreenDepth;\n"
1133 "#endif\n"
1134 "\n"
1135 "uniform lowp vec3 Color_Pants;\n"
1136 "uniform lowp vec3 Color_Shirt;\n"
1137 "uniform lowp vec3 FogColor;\n"
1138 "\n"
1139 "#ifdef USEFOG\n"
1140 "uniform highp float FogRangeRecip;\n"
1141 "uniform highp float FogPlaneViewDist;\n"
1142 "uniform highp float FogHeightFade;\n"
1143 "vec3 FogVertex(vec3 surfacecolor)\n"
1144 "{\n"
1145 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1146 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1147 "       float fogfrac;\n"
1148 "#ifdef USEFOGHEIGHTTEXTURE\n"
1149 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1150 "       fogfrac = fogheightpixel.a;\n"
1151 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1152 "#else\n"
1153 "# ifdef USEFOGOUTSIDE\n"
1154 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1155 "# else\n"
1156 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1157 "# endif\n"
1158 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1159 "#endif\n"
1160 "}\n"
1161 "#endif\n"
1162 "\n"
1163 "#ifdef USEOFFSETMAPPING\n"
1164 "uniform mediump float OffsetMapping_Scale;\n"
1165 "vec2 OffsetMapping(vec2 TexCoord)\n"
1166 "{\n"
1167 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1168 "       // 14 sample relief mapping: linear search and then binary search\n"
1169 "       // this basically steps forward a small amount repeatedly until it finds\n"
1170 "       // itself inside solid, then jitters forward and back using decreasing\n"
1171 "       // amounts to find the impact\n"
1172 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1173 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1174 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1175 "       vec3 RT = vec3(TexCoord, 1);\n"
1176 "       OffsetVector *= 0.1;\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);\n"
1184 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1185 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1186 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1187 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1188 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1189 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1190 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1191 "       return RT.xy;\n"
1192 "#else\n"
1193 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1194 "       // this basically moves forward the full distance, and then backs up based\n"
1195 "       // on height of samples\n"
1196 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1197 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1198 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1199 "       TexCoord += OffsetVector;\n"
1200 "       OffsetVector *= 0.5;\n"
1201 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1202 "       TexCoord -= OffsetVector * texture2D(Texture_Normal, TexCoord).a;\n"
1203 "       return TexCoord;\n"
1204 "#endif\n"
1205 "}\n"
1206 "#endif // USEOFFSETMAPPING\n"
1207 "\n"
1208 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1209 "uniform sampler2D Texture_Attenuation;\n"
1210 "uniform samplerCube Texture_Cube;\n"
1211 "#endif\n"
1212 "\n"
1213 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1214 "\n"
1215 "#ifdef USESHADOWMAP2D\n"
1216 "# ifdef USESHADOWSAMPLER\n"
1217 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1218 "# else\n"
1219 "uniform sampler2D Texture_ShadowMap2D;\n"
1220 "# endif\n"
1221 "#endif\n"
1222 "\n"
1223 "#ifdef USESHADOWMAPVSDCT\n"
1224 "uniform samplerCube Texture_CubeProjection;\n"
1225 "#endif\n"
1226 "\n"
1227 "#if defined(USESHADOWMAP2D)\n"
1228 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1229 "uniform mediump vec4 ShadowMap_Parameters;\n"
1230 "#endif\n"
1231 "\n"
1232 "#if defined(USESHADOWMAP2D)\n"
1233 "# ifdef USESHADOWMAPORTHO\n"
1234 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1235 "# else\n"
1236 "#  ifdef USESHADOWMAPVSDCT\n"
1237 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1238 "{\n"
1239 "       vec3 adir = abs(dir);\n"
1240 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1241 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1242 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1243 "}\n"
1244 "#  else\n"
1245 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1246 "{\n"
1247 "       vec3 adir = abs(dir);\n"
1248 "       float ma = adir.z;\n"
1249 "       vec4 proj = vec4(dir, 2.5);\n"
1250 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1251 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1252 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1253 "       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"
1254 "}\n"
1255 "#  endif\n"
1256 "# endif\n"
1257 "#endif // defined(USESHADOWMAP2D)\n"
1258 "\n"
1259 "# ifdef USESHADOWMAP2D\n"
1260 "float ShadowMapCompare(vec3 dir)\n"
1261 "{\n"
1262 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1263 "       float f;\n"
1264 "\n"
1265 "#  ifdef USESHADOWSAMPLER\n"
1266 "#    ifdef USESHADOWMAPPCF\n"
1267 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1268 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1269 "       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"
1270 "#    else\n"
1271 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1272 "#    endif\n"
1273 "#  else\n"
1274 "#    ifdef USESHADOWMAPPCF\n"
1275 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1276 "#      ifdef GL_ARB_texture_gather\n"
1277 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1278 "#      else\n"
1279 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1280 "#      endif\n"
1281 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1282 "#      if USESHADOWMAPPCF > 1\n"
1283 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1284 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1285 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1286 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1287 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1288 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1289 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1290 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1291 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1292 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1293 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1294 "       locols.yz += group2.ab;\n"
1295 "       hicols.yz += group8.rg;\n"
1296 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1297 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1298 "                               mix(locols, hicols, offset.y);\n"
1299 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1300 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1301 "       f = dot(cols, vec4(1.0/25.0));\n"
1302 "#      else\n"
1303 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1304 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1305 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1306 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1307 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1308 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1309 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1310 "#      endif\n"
1311 "#     else\n"
1312 "#      ifdef GL_EXT_gpu_shader4\n"
1313 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1314 "#      else\n"
1315 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1316 "#      endif\n"
1317 "#      if USESHADOWMAPPCF > 1\n"
1318 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1319 "       center *= ShadowMap_TextureScale;\n"
1320 "       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"
1321 "       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"
1322 "       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"
1323 "       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"
1324 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1325 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1326 "#      else\n"
1327 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1328 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1329 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1330 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1331 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1332 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1333 "#      endif\n"
1334 "#     endif\n"
1335 "#    else\n"
1336 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1337 "#    endif\n"
1338 "#  endif\n"
1339 "#  ifdef USESHADOWMAPORTHO\n"
1340 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1341 "#  else\n"
1342 "       return f;\n"
1343 "#  endif\n"
1344 "}\n"
1345 "# endif\n"
1346 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1347 "#endif // FRAGMENT_SHADER\n"
1348 "\n"
1349 "\n"
1350 "\n"
1351 "\n"
1352 "#ifdef MODE_DEFERREDGEOMETRY\n"
1353 "#ifdef VERTEX_SHADER\n"
1354 "uniform highp mat4 TexMatrix;\n"
1355 "#ifdef USEVERTEXTEXTUREBLEND\n"
1356 "uniform highp mat4 BackgroundTexMatrix;\n"
1357 "#endif\n"
1358 "uniform highp mat4 ModelViewMatrix;\n"
1359 "void main(void)\n"
1360 "{\n"
1361 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1362 "#ifdef USEVERTEXTEXTUREBLEND\n"
1363 "       VertexColor = Attrib_Color;\n"
1364 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1365 "#endif\n"
1366 "\n"
1367 "       // transform unnormalized eye direction into tangent space\n"
1368 "#ifdef USEOFFSETMAPPING\n"
1369 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1370 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1371 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1372 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1373 "#endif\n"
1374 "\n"
1375 "       VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1376 "       VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1377 "       VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1378 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1379 "}\n"
1380 "#endif // VERTEX_SHADER\n"
1381 "\n"
1382 "#ifdef FRAGMENT_SHADER\n"
1383 "void main(void)\n"
1384 "{\n"
1385 "#ifdef USEOFFSETMAPPING\n"
1386 "       // apply offsetmapping\n"
1387 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1388 "#define TexCoord TexCoordOffset\n"
1389 "#endif\n"
1390 "\n"
1391 "#ifdef USEALPHAKILL\n"
1392 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1393 "               discard;\n"
1394 "#endif\n"
1395 "\n"
1396 "#ifdef USEVERTEXTEXTUREBLEND\n"
1397 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1398 "       float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1399 "       //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1400 "       //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1401 "#endif\n"
1402 "\n"
1403 "#ifdef USEVERTEXTEXTUREBLEND\n"
1404 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1405 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1406 "#else\n"
1407 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1408 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1409 "#endif\n"
1410 "\n"
1411 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1412 "}\n"
1413 "#endif // FRAGMENT_SHADER\n"
1414 "#else // !MODE_DEFERREDGEOMETRY\n"
1415 "\n"
1416 "\n"
1417 "\n"
1418 "\n"
1419 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1420 "#ifdef VERTEX_SHADER\n"
1421 "uniform highp mat4 ModelViewMatrix;\n"
1422 "void main(void)\n"
1423 "{\n"
1424 "       ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1425 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1426 "}\n"
1427 "#endif // VERTEX_SHADER\n"
1428 "\n"
1429 "#ifdef FRAGMENT_SHADER\n"
1430 "uniform highp mat4 ViewToLight;\n"
1431 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1432 "uniform highp vec2 ScreenToDepth;\n"
1433 "uniform myhalf3 DeferredColor_Ambient;\n"
1434 "uniform myhalf3 DeferredColor_Diffuse;\n"
1435 "#ifdef USESPECULAR\n"
1436 "uniform myhalf3 DeferredColor_Specular;\n"
1437 "uniform myhalf SpecularPower;\n"
1438 "#endif\n"
1439 "uniform myhalf2 PixelToScreenTexCoord;\n"
1440 "void main(void)\n"
1441 "{\n"
1442 "       // calculate viewspace pixel position\n"
1443 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1444 "       vec3 position;\n"
1445 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1446 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1447 "       // decode viewspace pixel normal\n"
1448 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1449 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1450 "       // surfacenormal = pixel normal in viewspace\n"
1451 "       // LightVector = pixel to light in viewspace\n"
1452 "       // CubeVector = position in lightspace\n"
1453 "       // eyevector = pixel to view in viewspace\n"
1454 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1455 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1456 "#ifdef USEDIFFUSE\n"
1457 "       // calculate diffuse shading\n"
1458 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1459 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1460 "#endif\n"
1461 "#ifdef USESPECULAR\n"
1462 "       // calculate directional shading\n"
1463 "       vec3 eyevector = position * -1.0;\n"
1464 "#  ifdef USEEXACTSPECULARMATH\n"
1465 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1466 "#  else\n"
1467 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1468 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1469 "#  endif\n"
1470 "#endif\n"
1471 "\n"
1472 "#if defined(USESHADOWMAP2D)\n"
1473 "       fade *= ShadowMapCompare(CubeVector);\n"
1474 "#endif\n"
1475 "\n"
1476 "#ifdef USEDIFFUSE\n"
1477 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1478 "#else\n"
1479 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1480 "#endif\n"
1481 "#ifdef USESPECULAR\n"
1482 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1483 "#else\n"
1484 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1485 "#endif\n"
1486 "\n"
1487 "# ifdef USECUBEFILTER\n"
1488 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1489 "       gl_FragData[0].rgb *= cubecolor;\n"
1490 "       gl_FragData[1].rgb *= cubecolor;\n"
1491 "# endif\n"
1492 "}\n"
1493 "#endif // FRAGMENT_SHADER\n"
1494 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1495 "\n"
1496 "\n"
1497 "\n"
1498 "\n"
1499 "#ifdef MODE_DEFERREDBOUNCELIGHT\n"
1500 "#ifdef VERTEX_SHADER\n"
1501 "uniform highp mat4 ModelViewMatrix;\n"
1502 "void main(void)\n"
1503 "{\n"
1504 "       ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1505 "       LightOriginInvRadius.xyz = (ModelViewMatrix * vec4(Attrib_TexCoord0.xyz, 1.0)).xyz;\n"
1506 "       LightOriginInvRadius.w = Attrib_TexCoord0.w;\n"
1507 "       LightColor = Attrib_Color;\n"
1508 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1509 "}\n"
1510 "#endif // VERTEX_SHADER\n"
1511 "\n"
1512 "#ifdef FRAGMENT_SHADER\n"
1513 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1514 "uniform highp vec2 ScreenToDepth;\n"
1515 "uniform myhalf2 PixelToScreenTexCoord;\n"
1516 "void main(void)\n"
1517 "{\n"
1518 "       // calculate viewspace pixel position\n"
1519 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1520 "       vec3 position;\n"
1521 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1522 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1523 "       vec3 CubeVector = (position - LightOriginInvRadius.xyz) * LightOriginInvRadius.w;\n"
1524 "       gl_FragData[0] = vec4(LightColor.rgb * max(0.0, 1.0 - length(CubeVector)), 1.0);\n"
1525 "}\n"
1526 "#endif // FRAGMENT_SHADER\n"
1527 "#else // !MODE_DEFERREDBOUNCELIGHT\n"
1528 "\n"
1529 "\n"
1530 "\n"
1531 "\n"
1532 "#ifdef VERTEX_SHADER\n"
1533 "uniform highp mat4 TexMatrix;\n"
1534 "#ifdef USEVERTEXTEXTUREBLEND\n"
1535 "uniform highp mat4 BackgroundTexMatrix;\n"
1536 "#endif\n"
1537 "#ifdef MODE_LIGHTSOURCE\n"
1538 "uniform highp mat4 ModelToLight;\n"
1539 "#endif\n"
1540 "#ifdef USESHADOWMAPORTHO\n"
1541 "uniform highp mat4 ShadowMapMatrix;\n"
1542 "#endif\n"
1543 "void main(void)\n"
1544 "{\n"
1545 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1546 "       VertexColor = Attrib_Color;\n"
1547 "#endif\n"
1548 "       // copy the surface texcoord\n"
1549 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1550 "#ifdef USEVERTEXTEXTUREBLEND\n"
1551 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1552 "#endif\n"
1553 "#ifdef USELIGHTMAP\n"
1554 "       TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1555 "#endif\n"
1556 "\n"
1557 "#ifdef MODE_LIGHTSOURCE\n"
1558 "       // transform vertex position into light attenuation/cubemap space\n"
1559 "       // (-1 to +1 across the light box)\n"
1560 "       CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1561 "\n"
1562 "# ifdef USEDIFFUSE\n"
1563 "       // transform unnormalized light direction into tangent space\n"
1564 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1565 "       //  normalize it per pixel)\n"
1566 "       vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1567 "       LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1568 "       LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1569 "       LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1570 "# endif\n"
1571 "#endif\n"
1572 "\n"
1573 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1574 "       LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1575 "       LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1576 "       LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1577 "#endif\n"
1578 "\n"
1579 "       // transform unnormalized eye direction into tangent space\n"
1580 "#ifdef USEEYEVECTOR\n"
1581 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1582 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1583 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1584 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1585 "#endif\n"
1586 "\n"
1587 "#ifdef USEFOG\n"
1588 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1589 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1590 "#endif\n"
1591 "\n"
1592 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1593 "       VectorS = Attrib_TexCoord1.xyz;\n"
1594 "       VectorT = Attrib_TexCoord2.xyz;\n"
1595 "       VectorR = Attrib_TexCoord3.xyz;\n"
1596 "#endif\n"
1597 "\n"
1598 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1599 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1600 "\n"
1601 "#ifdef USESHADOWMAPORTHO\n"
1602 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1603 "#endif\n"
1604 "\n"
1605 "#ifdef USEREFLECTION\n"
1606 "       ModelViewProjectionPosition = gl_Position;\n"
1607 "#endif\n"
1608 "}\n"
1609 "#endif // VERTEX_SHADER\n"
1610 "\n"
1611 "\n"
1612 "\n"
1613 "\n"
1614 "#ifdef FRAGMENT_SHADER\n"
1615 "#ifdef USEDEFERREDLIGHTMAP\n"
1616 "uniform myhalf2 PixelToScreenTexCoord;\n"
1617 "uniform myhalf3 DeferredMod_Diffuse;\n"
1618 "uniform myhalf3 DeferredMod_Specular;\n"
1619 "#endif\n"
1620 "uniform myhalf3 Color_Ambient;\n"
1621 "uniform myhalf3 Color_Diffuse;\n"
1622 "uniform myhalf3 Color_Specular;\n"
1623 "uniform myhalf SpecularPower;\n"
1624 "#ifdef USEGLOW\n"
1625 "uniform myhalf3 Color_Glow;\n"
1626 "#endif\n"
1627 "uniform myhalf Alpha;\n"
1628 "#ifdef USEREFLECTION\n"
1629 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1630 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1631 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1632 "uniform lowp vec4 ReflectColor;\n"
1633 "#endif\n"
1634 "#ifdef USEREFLECTCUBE\n"
1635 "uniform highp mat4 ModelToReflectCube;\n"
1636 "uniform sampler2D Texture_ReflectMask;\n"
1637 "uniform samplerCube Texture_ReflectCube;\n"
1638 "#endif\n"
1639 "#ifdef MODE_LIGHTDIRECTION\n"
1640 "uniform myhalf3 LightColor;\n"
1641 "#endif\n"
1642 "#ifdef MODE_LIGHTSOURCE\n"
1643 "uniform myhalf3 LightColor;\n"
1644 "#endif\n"
1645 "void main(void)\n"
1646 "{\n"
1647 "#ifdef USEOFFSETMAPPING\n"
1648 "       // apply offsetmapping\n"
1649 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1650 "#define TexCoord TexCoordOffset\n"
1651 "#endif\n"
1652 "\n"
1653 "       // combine the diffuse textures (base, pants, shirt)\n"
1654 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1655 "#ifdef USEALPHAKILL\n"
1656 "       if (color.a < 0.5)\n"
1657 "               discard;\n"
1658 "#endif\n"
1659 "       color.a *= Alpha;\n"
1660 "#ifdef USECOLORMAPPING\n"
1661 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1662 "#endif\n"
1663 "#ifdef USEVERTEXTEXTUREBLEND\n"
1664 "       myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1665 "       //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1666 "       //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1667 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1668 "       color.a = 1.0;\n"
1669 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1670 "#endif\n"
1671 "\n"
1672 "       // get the surface normal\n"
1673 "#ifdef USEVERTEXTEXTUREBLEND\n"
1674 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1675 "#else\n"
1676 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1677 "#endif\n"
1678 "\n"
1679 "       // get the material colors\n"
1680 "       myhalf3 diffusetex = color.rgb;\n"
1681 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1682 "# ifdef USEVERTEXTEXTUREBLEND\n"
1683 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1684 "# else\n"
1685 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1686 "# endif\n"
1687 "#endif\n"
1688 "\n"
1689 "#ifdef USEREFLECTCUBE\n"
1690 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1691 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1692 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1693 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1694 "#endif\n"
1695 "\n"
1696 "\n"
1697 "\n"
1698 "\n"
1699 "#ifdef MODE_LIGHTSOURCE\n"
1700 "       // light source\n"
1701 "#ifdef USEDIFFUSE\n"
1702 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1703 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1704 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1705 "#ifdef USESPECULAR\n"
1706 "#ifdef USEEXACTSPECULARMATH\n"
1707 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1708 "#else\n"
1709 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1710 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1711 "#endif\n"
1712 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1713 "#endif\n"
1714 "#else\n"
1715 "       color.rgb = diffusetex * Color_Ambient;\n"
1716 "#endif\n"
1717 "       color.rgb *= LightColor;\n"
1718 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1719 "#if defined(USESHADOWMAP2D)\n"
1720 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1721 "#endif\n"
1722 "# ifdef USECUBEFILTER\n"
1723 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1724 "# endif\n"
1725 "#endif // MODE_LIGHTSOURCE\n"
1726 "\n"
1727 "\n"
1728 "\n"
1729 "\n"
1730 "#ifdef MODE_LIGHTDIRECTION\n"
1731 "#define SHADING\n"
1732 "#ifdef USEDIFFUSE\n"
1733 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1734 "#endif\n"
1735 "#define lightcolor LightColor\n"
1736 "#endif // MODE_LIGHTDIRECTION\n"
1737 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1738 "#define SHADING\n"
1739 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1740 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1741 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1742 "       // convert modelspace light vector to tangentspace\n"
1743 "       myhalf3 lightnormal;\n"
1744 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1745 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1746 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1747 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1748 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1749 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1750 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1751 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1752 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1753 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1754 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1755 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1756 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1757 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1758 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1759 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1760 "#define SHADING\n"
1761 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1762 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1763 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1764 "#endif\n"
1765 "\n"
1766 "\n"
1767 "\n"
1768 "\n"
1769 "#ifdef MODE_FAKELIGHT\n"
1770 "#define SHADING\n"
1771 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1772 "myhalf3 lightcolor = myhalf3(1.0);\n"
1773 "#endif // MODE_FAKELIGHT\n"
1774 "\n"
1775 "\n"
1776 "\n"
1777 "\n"
1778 "#ifdef MODE_LIGHTMAP\n"
1779 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1780 "#endif // MODE_LIGHTMAP\n"
1781 "#ifdef MODE_VERTEXCOLOR\n"
1782 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1783 "#endif // MODE_VERTEXCOLOR\n"
1784 "#ifdef MODE_FLATCOLOR\n"
1785 "       color.rgb = diffusetex * Color_Ambient;\n"
1786 "#endif // MODE_FLATCOLOR\n"
1787 "\n"
1788 "\n"
1789 "\n"
1790 "\n"
1791 "#ifdef SHADING\n"
1792 "# ifdef USEDIFFUSE\n"
1793 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1794 "#  ifdef USESPECULAR\n"
1795 "#   ifdef USEEXACTSPECULARMATH\n"
1796 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1797 "#   else\n"
1798 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1799 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1800 "#   endif\n"
1801 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1802 "#  else\n"
1803 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1804 "#  endif\n"
1805 "# else\n"
1806 "       color.rgb = diffusetex * Color_Ambient;\n"
1807 "# endif\n"
1808 "#endif\n"
1809 "\n"
1810 "#ifdef USESHADOWMAPORTHO\n"
1811 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1812 "#endif\n"
1813 "\n"
1814 "#ifdef USEDEFERREDLIGHTMAP\n"
1815 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1816 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1817 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1818 "#endif\n"
1819 "\n"
1820 "#ifdef USEGLOW\n"
1821 "#ifdef USEVERTEXTEXTUREBLEND\n"
1822 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1823 "#else\n"
1824 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1825 "#endif\n"
1826 "#endif\n"
1827 "\n"
1828 "#ifdef USEFOG\n"
1829 "       color.rgb = FogVertex(color.rgb);\n"
1830 "#endif\n"
1831 "\n"
1832 "       // 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"
1833 "#ifdef USEREFLECTION\n"
1834 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1835 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1836 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1837 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1838 "       // FIXME temporary hack to detect the case that the reflection\n"
1839 "       // gets blackened at edges due to leaving the area that contains actual\n"
1840 "       // content.\n"
1841 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1842 "       // 'appening.\n"
1843 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1844 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1845 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1846 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1847 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1848 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1849 "#endif\n"
1850 "\n"
1851 "       gl_FragColor = vec4(color);\n"
1852 "}\n"
1853 "#endif // FRAGMENT_SHADER\n"
1854 "\n"
1855 "#endif // !MODE_DEFERREDBOUNCELIGHT\n"
1856 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1857 "#endif // !MODE_DEFERREDGEOMETRY\n"
1858 "#endif // !MODE_WATER\n"
1859 "#endif // !MODE_REFRACTION\n"
1860 "#endif // !MODE_BLOOMBLUR\n"
1861 "#endif // !MODE_GENERIC\n"
1862 "#endif // !MODE_POSTPROCESS\n"
1863 "#endif // !MODE_SHOWDEPTH\n"
1864 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1865 ;
1866
1867 /*
1868 =========================================================================================================================================================
1869
1870
1871
1872 =========================================================================================================================================================
1873
1874
1875
1876 =========================================================================================================================================================
1877
1878
1879
1880 =========================================================================================================================================================
1881
1882
1883
1884 =========================================================================================================================================================
1885
1886
1887
1888 =========================================================================================================================================================
1889
1890
1891
1892 =========================================================================================================================================================
1893 */
1894
1895 const char *builtinhlslshaderstring =
1896 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1897 "// written by Forest 'LordHavoc' Hale\n"
1898 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1899 "\n"
1900 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1901 "#if defined(USEREFLECTION)\n"
1902 "#undef USESHADOWMAPORTHO\n"
1903 "#endif\n"
1904 "\n"
1905 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1906 "# define USEFOG\n"
1907 "#endif\n"
1908 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1909 "#define USELIGHTMAP\n"
1910 "#endif\n"
1911 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1912 "#define USEEYEVECTOR\n"
1913 "#endif\n"
1914 "\n"
1915 "#ifdef FRAGMENT_SHADER\n"
1916 "#ifdef HLSL\n"
1917 "//#undef USESHADOWMAPPCF\n"
1918 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1919 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1920 "#else\n"
1921 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1922 "#endif\n"
1923 "#endif\n"
1924 "\n"
1925 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1926 "#ifdef VERTEX_SHADER\n"
1927 "void main\n"
1928 "(\n"
1929 "float4 gl_Vertex : POSITION,\n"
1930 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1931 "out float4 gl_Position : POSITION,\n"
1932 "out float Depth : TEXCOORD0\n"
1933 ")\n"
1934 "{\n"
1935 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1936 "       Depth = gl_Position.z;\n"
1937 "}\n"
1938 "#endif\n"
1939 "\n"
1940 "#ifdef FRAGMENT_SHADER\n"
1941 "void main\n"
1942 "(\n"
1943 "float Depth : TEXCOORD0,\n"
1944 "out float4 gl_FragColor : COLOR\n"
1945 ")\n"
1946 "{\n"
1947 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1948 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1949 "       temp.yz -= floor(temp.yz);\n"
1950 "       gl_FragColor = temp;\n"
1951 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1952 "}\n"
1953 "#endif\n"
1954 "#else // !MODE_DEPTH_ORSHADOW\n"
1955 "\n"
1956 "\n"
1957 "\n"
1958 "\n"
1959 "#ifdef MODE_SHOWDEPTH\n"
1960 "#ifdef VERTEX_SHADER\n"
1961 "void main\n"
1962 "(\n"
1963 "float4 gl_Vertex : POSITION,\n"
1964 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1965 "out float4 gl_Position : POSITION,\n"
1966 "out float4 gl_FrontColor : COLOR0\n"
1967 ")\n"
1968 "{\n"
1969 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1970 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1971 "}\n"
1972 "#endif\n"
1973 "\n"
1974 "#ifdef FRAGMENT_SHADER\n"
1975 "void main\n"
1976 "(\n"
1977 "float4 gl_FrontColor : COLOR0,\n"
1978 "out float4 gl_FragColor : COLOR\n"
1979 ")\n"
1980 "{\n"
1981 "       gl_FragColor = gl_FrontColor;\n"
1982 "}\n"
1983 "#endif\n"
1984 "#else // !MODE_SHOWDEPTH\n"
1985 "\n"
1986 "\n"
1987 "\n"
1988 "\n"
1989 "#ifdef MODE_POSTPROCESS\n"
1990 "\n"
1991 "#ifdef VERTEX_SHADER\n"
1992 "void main\n"
1993 "(\n"
1994 "float4 gl_Vertex : POSITION,\n"
1995 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1996 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1997 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1998 "out float4 gl_Position : POSITION,\n"
1999 "out float2 TexCoord1 : TEXCOORD0,\n"
2000 "out float2 TexCoord2 : TEXCOORD1\n"
2001 ")\n"
2002 "{\n"
2003 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2004 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2005 "#ifdef USEBLOOM\n"
2006 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
2007 "#endif\n"
2008 "}\n"
2009 "#endif\n"
2010 "\n"
2011 "#ifdef FRAGMENT_SHADER\n"
2012 "void main\n"
2013 "(\n"
2014 "float2 TexCoord1 : TEXCOORD0,\n"
2015 "float2 TexCoord2 : TEXCOORD1,\n"
2016 "uniform sampler Texture_First : register(s0),\n"
2017 "#ifdef USEBLOOM\n"
2018 "uniform sampler Texture_Second : register(s1),\n"
2019 "#endif\n"
2020 "#ifdef USEGAMMARAMPS\n"
2021 "uniform sampler Texture_GammaRamps : register(s2),\n"
2022 "#endif\n"
2023 "#ifdef USESATURATION\n"
2024 "uniform float Saturation : register(c30),\n"
2025 "#endif\n"
2026 "#ifdef USEVIEWTINT\n"
2027 "uniform float4 ViewTintColor : register(c41),\n"
2028 "#endif\n"
2029 "uniform float4 UserVec1 : register(c37),\n"
2030 "uniform float4 UserVec2 : register(c38),\n"
2031 "uniform float4 UserVec3 : register(c39),\n"
2032 "uniform float4 UserVec4 : register(c40),\n"
2033 "uniform float ClientTime : register(c2),\n"
2034 "uniform float2 PixelSize : register(c25),\n"
2035 "uniform float4 BloomColorSubtract : register(c43),\n"
2036 "out float4 gl_FragColor : COLOR\n"
2037 ")\n"
2038 "{\n"
2039 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2040 "#ifdef USEBLOOM\n"
2041 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2042 "#endif\n"
2043 "#ifdef USEVIEWTINT\n"
2044 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2045 "#endif\n"
2046 "\n"
2047 "#ifdef USEPOSTPROCESSING\n"
2048 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2049 "// 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"
2050 "       float sobel = 1.0;\n"
2051 "       // float2 ts = textureSize(Texture_First, 0);\n"
2052 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2053 "       float2 px = PixelSize;\n"
2054 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2055 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2056 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2057 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2058 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2059 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2060 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2061 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2062 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2063 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2064 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2065 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2066 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2067 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2068 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2069 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2070 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2071 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2072 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2073 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2074 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2075 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2076 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2077 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2078 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2079 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2080 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2081 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2082 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2083 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2084 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2085 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2086 "#endif\n"
2087 "\n"
2088 "#ifdef USESATURATION\n"
2089 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2090 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2091 "       // 'vampire sight' effect, wheres red is compensated\n"
2092 "       #ifdef SATURATION_REDCOMPENSATE\n"
2093 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2094 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2095 "               gl_FragColor.r += r;\n"
2096 "       #else\n"
2097 "               // normal desaturation\n"
2098 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2099 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2100 "       #endif\n"
2101 "#endif\n"
2102 "\n"
2103 "#ifdef USEGAMMARAMPS\n"
2104 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2105 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2106 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2107 "#endif\n"
2108 "}\n"
2109 "#endif\n"
2110 "#else // !MODE_POSTPROCESS\n"
2111 "\n"
2112 "\n"
2113 "\n"
2114 "\n"
2115 "#ifdef MODE_GENERIC\n"
2116 "#ifdef VERTEX_SHADER\n"
2117 "void main\n"
2118 "(\n"
2119 "float4 gl_Vertex : POSITION,\n"
2120 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2121 "float4 gl_Color : COLOR0,\n"
2122 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2123 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2124 "out float4 gl_Position : POSITION,\n"
2125 "#ifdef USEDIFFUSE\n"
2126 "out float2 TexCoord1 : TEXCOORD0,\n"
2127 "#endif\n"
2128 "#ifdef USESPECULAR\n"
2129 "out float2 TexCoord2 : TEXCOORD1,\n"
2130 "#endif\n"
2131 "out float4 gl_FrontColor : COLOR\n"
2132 ")\n"
2133 "{\n"
2134 "#ifdef HLSL\n"
2135 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2136 "#else\n"
2137 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2138 "#endif\n"
2139 "#ifdef USEDIFFUSE\n"
2140 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2141 "#endif\n"
2142 "#ifdef USESPECULAR\n"
2143 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2144 "#endif\n"
2145 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2146 "}\n"
2147 "#endif\n"
2148 "\n"
2149 "#ifdef FRAGMENT_SHADER\n"
2150 "\n"
2151 "void main\n"
2152 "(\n"
2153 "float4 gl_FrontColor : COLOR0,\n"
2154 "float2 TexCoord1 : TEXCOORD0,\n"
2155 "float2 TexCoord2 : TEXCOORD1,\n"
2156 "#ifdef USEDIFFUSE\n"
2157 "uniform sampler Texture_First : register(s0),\n"
2158 "#endif\n"
2159 "#ifdef USESPECULAR\n"
2160 "uniform sampler Texture_Second : register(s1),\n"
2161 "#endif\n"
2162 "out float4 gl_FragColor : COLOR\n"
2163 ")\n"
2164 "{\n"
2165 "#ifdef USEVIEWTINT\n"
2166 "       gl_FragColor = gl_FrontColor;\n"
2167 "#else\n"
2168 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2169 "#endif\n"
2170 "#ifdef USEDIFFUSE\n"
2171 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2172 "#endif\n"
2173 "\n"
2174 "#ifdef USESPECULAR\n"
2175 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2176 "# ifdef USECOLORMAPPING\n"
2177 "       gl_FragColor *= tex2;\n"
2178 "# endif\n"
2179 "# ifdef USEGLOW\n"
2180 "       gl_FragColor += tex2;\n"
2181 "# endif\n"
2182 "# ifdef USEVERTEXTEXTUREBLEND\n"
2183 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2184 "# endif\n"
2185 "#endif\n"
2186 "}\n"
2187 "#endif\n"
2188 "#else // !MODE_GENERIC\n"
2189 "\n"
2190 "\n"
2191 "\n"
2192 "\n"
2193 "#ifdef MODE_BLOOMBLUR\n"
2194 "#ifdef VERTEX_SHADER\n"
2195 "void main\n"
2196 "(\n"
2197 "float4 gl_Vertex : POSITION,\n"
2198 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2199 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2200 "out float4 gl_Position : POSITION,\n"
2201 "out float2 TexCoord : TEXCOORD0\n"
2202 ")\n"
2203 "{\n"
2204 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2205 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2206 "}\n"
2207 "#endif\n"
2208 "\n"
2209 "#ifdef FRAGMENT_SHADER\n"
2210 "\n"
2211 "void main\n"
2212 "(\n"
2213 "float2 TexCoord : TEXCOORD0,\n"
2214 "uniform sampler Texture_First : register(s0),\n"
2215 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2216 "out float4 gl_FragColor : COLOR\n"
2217 ")\n"
2218 "{\n"
2219 "       int i;\n"
2220 "       float2 tc = TexCoord;\n"
2221 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2222 "       tc += BloomBlur_Parameters.xy;\n"
2223 "       for (i = 1;i < SAMPLES;i++)\n"
2224 "       {\n"
2225 "               color += tex2D(Texture_First, tc).rgb;\n"
2226 "               tc += BloomBlur_Parameters.xy;\n"
2227 "       }\n"
2228 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2229 "}\n"
2230 "#endif\n"
2231 "#else // !MODE_BLOOMBLUR\n"
2232 "#ifdef MODE_REFRACTION\n"
2233 "#ifdef VERTEX_SHADER\n"
2234 "void main\n"
2235 "(\n"
2236 "float4 gl_Vertex : POSITION,\n"
2237 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2238 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2239 "uniform float4x4 TexMatrix : register(c0),\n"
2240 "uniform float3 EyePosition : register(c24),\n"
2241 "out float4 gl_Position : POSITION,\n"
2242 "out float2 TexCoord : TEXCOORD0,\n"
2243 "out float3 EyeVector : TEXCOORD1,\n"
2244 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2245 ")\n"
2246 "{\n"
2247 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2248 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2249 "       ModelViewProjectionPosition = gl_Position;\n"
2250 "}\n"
2251 "#endif\n"
2252 "\n"
2253 "#ifdef FRAGMENT_SHADER\n"
2254 "void main\n"
2255 "(\n"
2256 "float2 TexCoord : TEXCOORD0,\n"
2257 "float3 EyeVector : TEXCOORD1,\n"
2258 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2259 "uniform sampler Texture_Normal : register(s0),\n"
2260 "uniform sampler Texture_Refraction : register(s3),\n"
2261 "uniform sampler Texture_Reflection : register(s7),\n"
2262 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2263 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2264 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2265 "uniform float4 RefractColor : register(c29),\n"
2266 "out float4 gl_FragColor : COLOR\n"
2267 ")\n"
2268 "{\n"
2269 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2270 "       //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"
2271 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2272 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2273 "       // FIXME temporary hack to detect the case that the reflection\n"
2274 "       // gets blackened at edges due to leaving the area that contains actual\n"
2275 "       // content.\n"
2276 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2277 "       // 'appening.\n"
2278 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2279 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2280 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2281 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2282 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2283 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2284 "}\n"
2285 "#endif\n"
2286 "#else // !MODE_REFRACTION\n"
2287 "\n"
2288 "\n"
2289 "\n"
2290 "\n"
2291 "#ifdef MODE_WATER\n"
2292 "#ifdef VERTEX_SHADER\n"
2293 "\n"
2294 "void main\n"
2295 "(\n"
2296 "float4 gl_Vertex : POSITION,\n"
2297 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2298 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2299 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2300 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2301 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2302 "uniform float4x4 TexMatrix : register(c0),\n"
2303 "uniform float3 EyePosition : register(c24),\n"
2304 "out float4 gl_Position : POSITION,\n"
2305 "out float2 TexCoord : TEXCOORD0,\n"
2306 "out float3 EyeVector : TEXCOORD1,\n"
2307 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2308 ")\n"
2309 "{\n"
2310 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2311 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2312 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2313 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2314 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2315 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2316 "       ModelViewProjectionPosition = gl_Position;\n"
2317 "}\n"
2318 "#endif\n"
2319 "\n"
2320 "#ifdef FRAGMENT_SHADER\n"
2321 "void main\n"
2322 "(\n"
2323 "float2 TexCoord : TEXCOORD0,\n"
2324 "float3 EyeVector : TEXCOORD1,\n"
2325 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2326 "uniform sampler Texture_Normal : register(s0),\n"
2327 "uniform sampler Texture_Refraction : register(s3),\n"
2328 "uniform sampler Texture_Reflection : register(s7),\n"
2329 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2330 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2331 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2332 "uniform float4 RefractColor : register(c29),\n"
2333 "uniform float4 ReflectColor : register(c26),\n"
2334 "uniform float ReflectFactor : register(c27),\n"
2335 "uniform float ReflectOffset : register(c28),\n"
2336 "out float4 gl_FragColor : COLOR\n"
2337 ")\n"
2338 "{\n"
2339 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2340 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2341 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2342 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2343 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2344 "       // FIXME temporary hack to detect the case that the reflection\n"
2345 "       // gets blackened at edges due to leaving the area that contains actual\n"
2346 "       // content.\n"
2347 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2348 "       // 'appening.\n"
2349 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2350 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2351 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2352 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2353 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2354 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2355 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2356 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2357 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2358 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2359 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2360 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2361 "}\n"
2362 "#endif\n"
2363 "#else // !MODE_WATER\n"
2364 "\n"
2365 "\n"
2366 "\n"
2367 "\n"
2368 "// 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"
2369 "\n"
2370 "// fragment shader specific:\n"
2371 "#ifdef FRAGMENT_SHADER\n"
2372 "\n"
2373 "#ifdef USEFOG\n"
2374 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2375 "{\n"
2376 "       float fogfrac;\n"
2377 "#ifdef USEFOGHEIGHTTEXTURE\n"
2378 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2379 "       fogfrac = fogheightpixel.a;\n"
2380 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2381 "#else\n"
2382 "# ifdef USEFOGOUTSIDE\n"
2383 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2384 "# else\n"
2385 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2386 "# endif\n"
2387 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2388 "#endif\n"
2389 "}\n"
2390 "#endif\n"
2391 "\n"
2392 "#ifdef USEOFFSETMAPPING\n"
2393 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2394 "{\n"
2395 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2396 "       // 14 sample relief mapping: linear search and then binary search\n"
2397 "       // this basically steps forward a small amount repeatedly until it finds\n"
2398 "       // itself inside solid, then jitters forward and back using decreasing\n"
2399 "       // amounts to find the impact\n"
2400 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2401 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2402 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2403 "       float3 RT = float3(TexCoord, 1);\n"
2404 "       OffsetVector *= 0.1;\n"
2405 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2406 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2407 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2408 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2409 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2410 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2411 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2412 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2413 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2414 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2415 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2416 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2417 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2418 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2419 "       return RT.xy;\n"
2420 "#else\n"
2421 "       // 3 sample offset mapping (only 3 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2422 "       // this basically moves forward the full distance, and then backs up based\n"
2423 "       // on height of samples\n"
2424 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2425 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2426 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2427 "       TexCoord += OffsetVector;\n"
2428 "       OffsetVector *= 0.333;\n"
2429 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2430 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2431 "       TexCoord -= OffsetVector * tex2D(Texture_Normal, TexCoord).a;\n"
2432 "       return TexCoord;\n"
2433 "#endif\n"
2434 "}\n"
2435 "#endif // USEOFFSETMAPPING\n"
2436 "\n"
2437 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2438 "#if defined(USESHADOWMAP2D)\n"
2439 "# ifdef USESHADOWMAPORTHO\n"
2440 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2441 "# else\n"
2442 "#  ifdef USESHADOWMAPVSDCT\n"
2443 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2444 "{\n"
2445 "       float3 adir = abs(dir);\n"
2446 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2447 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2448 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2449 "}\n"
2450 "#  else\n"
2451 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2452 "{\n"
2453 "       float3 adir = abs(dir);\n"
2454 "       float ma = adir.z;\n"
2455 "       float4 proj = float4(dir, 2.5);\n"
2456 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2457 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2458 "#ifdef HLSL\n"
2459 "       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"
2460 "#else\n"
2461 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2462 "       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"
2463 "#endif\n"
2464 "}\n"
2465 "#  endif\n"
2466 "# endif\n"
2467 "#endif // defined(USESHADOWMAP2D)\n"
2468 "\n"
2469 "# ifdef USESHADOWMAP2D\n"
2470 "#ifdef USESHADOWMAPVSDCT\n"
2471 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2472 "#else\n"
2473 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2474 "#endif\n"
2475 "{\n"
2476 "#ifdef USESHADOWMAPVSDCT\n"
2477 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2478 "#else\n"
2479 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2480 "#endif\n"
2481 "       float f;\n"
2482 "\n"
2483 "#  ifdef USESHADOWSAMPLER\n"
2484 "#    ifdef USESHADOWMAPPCF\n"
2485 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2486 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2487 "       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"
2488 "#    else\n"
2489 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2490 "#    endif\n"
2491 "#  else\n"
2492 "#    ifdef USESHADOWMAPPCF\n"
2493 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2494 "#      ifdef GL_ARB_texture_gather\n"
2495 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2496 "#      else\n"
2497 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2498 "#      endif\n"
2499 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2500 "#      if USESHADOWMAPPCF > 1\n"
2501 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2502 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2503 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2504 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2505 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2506 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2507 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2508 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2509 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2510 "       float4 locols = float4(group1.ab, group3.ab);\n"
2511 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2512 "       locols.yz += group2.ab;\n"
2513 "       hicols.yz += group8.rg;\n"
2514 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2515 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2516 "                               lerp(locols, hicols, offset.y);\n"
2517 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2518 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2519 "       f = dot(cols, float4(1.0/25.0));\n"
2520 "#      else\n"
2521 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2522 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2523 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2524 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2525 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2526 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2527 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2528 "#      endif\n"
2529 "#     else\n"
2530 "#      ifdef GL_EXT_gpu_shader4\n"
2531 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2532 "#      else\n"
2533 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2534 "#      endif\n"
2535 "#      if USESHADOWMAPPCF > 1\n"
2536 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2537 "       center *= ShadowMap_TextureScale;\n"
2538 "       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"
2539 "       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"
2540 "       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"
2541 "       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"
2542 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2543 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2544 "#      else\n"
2545 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2546 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2547 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2548 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2549 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2550 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2551 "#      endif\n"
2552 "#     endif\n"
2553 "#    else\n"
2554 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2555 "#    endif\n"
2556 "#  endif\n"
2557 "#  ifdef USESHADOWMAPORTHO\n"
2558 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2559 "#  else\n"
2560 "       return f;\n"
2561 "#  endif\n"
2562 "}\n"
2563 "# endif\n"
2564 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2565 "#endif // FRAGMENT_SHADER\n"
2566 "\n"
2567 "\n"
2568 "\n"
2569 "\n"
2570 "#ifdef MODE_DEFERREDGEOMETRY\n"
2571 "#ifdef VERTEX_SHADER\n"
2572 "void main\n"
2573 "(\n"
2574 "float4 gl_Vertex : POSITION,\n"
2575 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2576 "#ifdef USEVERTEXTEXTUREBLEND\n"
2577 "float4 gl_Color : COLOR0,\n"
2578 "#endif\n"
2579 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2580 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2581 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2582 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2583 "uniform float4x4 TexMatrix : register(c0),\n"
2584 "#ifdef USEVERTEXTEXTUREBLEND\n"
2585 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2586 "#endif\n"
2587 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2588 "#ifdef USEOFFSETMAPPING\n"
2589 "uniform float3 EyePosition : register(c24),\n"
2590 "#endif\n"
2591 "out float4 gl_Position : POSITION,\n"
2592 "#ifdef USEVERTEXTEXTUREBLEND\n"
2593 "out float4 gl_FrontColor : COLOR,\n"
2594 "#endif\n"
2595 "out float4 TexCoordBoth : TEXCOORD0,\n"
2596 "#ifdef USEOFFSETMAPPING\n"
2597 "out float3 EyeVector : TEXCOORD2,\n"
2598 "#endif\n"
2599 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2600 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2601 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2602 ")\n"
2603 "{\n"
2604 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2605 "#ifdef USEVERTEXTEXTUREBLEND\n"
2606 "#ifdef HLSL\n"
2607 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2608 "#else\n"
2609 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2610 "#endif\n"
2611 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2612 "#endif\n"
2613 "\n"
2614 "       // transform unnormalized eye direction into tangent space\n"
2615 "#ifdef USEOFFSETMAPPING\n"
2616 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2617 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2618 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2619 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2620 "#endif\n"
2621 "\n"
2622 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2623 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2624 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2625 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2626 "       VectorR.w = gl_Position.z;\n"
2627 "}\n"
2628 "#endif // VERTEX_SHADER\n"
2629 "\n"
2630 "#ifdef FRAGMENT_SHADER\n"
2631 "void main\n"
2632 "(\n"
2633 "float4 TexCoordBoth : TEXCOORD0,\n"
2634 "float3 EyeVector : TEXCOORD2,\n"
2635 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2636 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2637 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2638 "uniform sampler Texture_Normal : register(s0),\n"
2639 "#ifdef USEALPHAKILL\n"
2640 "uniform sampler Texture_Color : register(s1),\n"
2641 "#endif\n"
2642 "uniform sampler Texture_Gloss : register(s2),\n"
2643 "#ifdef USEVERTEXTEXTUREBLEND\n"
2644 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2645 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2646 "#endif\n"
2647 "#ifdef USEOFFSETMAPPING\n"
2648 "uniform float OffsetMapping_Scale : register(c24),\n"
2649 "#endif\n"
2650 "uniform half SpecularPower : register(c36),\n"
2651 "#ifdef HLSL\n"
2652 "out float4 gl_FragData0 : COLOR0,\n"
2653 "out float4 gl_FragData1 : COLOR1\n"
2654 "#else\n"
2655 "out float4 gl_FragColor : COLOR\n"
2656 "#endif\n"
2657 ")\n"
2658 "{\n"
2659 "       float2 TexCoord = TexCoordBoth.xy;\n"
2660 "#ifdef USEOFFSETMAPPING\n"
2661 "       // apply offsetmapping\n"
2662 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2663 "#define TexCoord TexCoordOffset\n"
2664 "#endif\n"
2665 "\n"
2666 "#ifdef USEALPHAKILL\n"
2667 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2668 "               discard;\n"
2669 "#endif\n"
2670 "\n"
2671 "#ifdef USEVERTEXTEXTUREBLEND\n"
2672 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2673 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2674 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2675 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2676 "#endif\n"
2677 "\n"
2678 "#ifdef USEVERTEXTEXTUREBLEND\n"
2679 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2680 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2681 "#else\n"
2682 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2683 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2684 "#endif\n"
2685 "\n"
2686 "#ifdef HLSL\n"
2687 "       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"
2688 "       float Depth = VectorR.w / 256.0;\n"
2689 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2690 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2691 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2692 "       gl_FragData1 = depthcolor;\n"
2693 "#else\n"
2694 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2695 "#endif\n"
2696 "}\n"
2697 "#endif // FRAGMENT_SHADER\n"
2698 "#else // !MODE_DEFERREDGEOMETRY\n"
2699 "\n"
2700 "\n"
2701 "\n"
2702 "\n"
2703 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2704 "#ifdef VERTEX_SHADER\n"
2705 "void main\n"
2706 "(\n"
2707 "float4 gl_Vertex : POSITION,\n"
2708 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2709 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2710 "out float4 gl_Position : POSITION,\n"
2711 "out float4 ModelViewPosition : TEXCOORD0\n"
2712 ")\n"
2713 "{\n"
2714 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2715 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2716 "}\n"
2717 "#endif // VERTEX_SHADER\n"
2718 "\n"
2719 "#ifdef FRAGMENT_SHADER\n"
2720 "void main\n"
2721 "(\n"
2722 "#ifdef HLSL\n"
2723 "float2 Pixel : VPOS,\n"
2724 "#else\n"
2725 "float2 Pixel : WPOS,\n"
2726 "#endif\n"
2727 "float4 ModelViewPosition : TEXCOORD0,\n"
2728 "uniform float4x4 ViewToLight : register(c44),\n"
2729 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2730 "uniform float3 LightPosition : register(c23),\n"
2731 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2732 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2733 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2734 "#ifdef USESPECULAR\n"
2735 "uniform half3 DeferredColor_Specular : register(c11),\n"
2736 "uniform half SpecularPower : register(c36),\n"
2737 "#endif\n"
2738 "uniform sampler Texture_Attenuation : register(s9),\n"
2739 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2740 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2741 "\n"
2742 "#ifdef USECUBEFILTER\n"
2743 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2744 "#endif\n"
2745 "\n"
2746 "#ifdef USESHADOWMAP2D\n"
2747 "# ifdef USESHADOWSAMPLER\n"
2748 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2749 "# else\n"
2750 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2751 "# endif\n"
2752 "#endif\n"
2753 "\n"
2754 "#ifdef USESHADOWMAPVSDCT\n"
2755 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2756 "#endif\n"
2757 "\n"
2758 "#if defined(USESHADOWMAP2D)\n"
2759 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2760 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2761 "#endif\n"
2762 "\n"
2763 "out float4 gl_FragData0 : COLOR0,\n"
2764 "out float4 gl_FragData1 : COLOR1\n"
2765 ")\n"
2766 "{\n"
2767 "       // calculate viewspace pixel position\n"
2768 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2769 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2770 "       float3 position;\n"
2771 "#ifdef HLSL\n"
2772 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2773 "#else\n"
2774 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2775 "#endif\n"
2776 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2777 "       // decode viewspace pixel normal\n"
2778 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2779 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2780 "       // surfacenormal = pixel normal in viewspace\n"
2781 "       // LightVector = pixel to light in viewspace\n"
2782 "       // CubeVector = position in lightspace\n"
2783 "       // eyevector = pixel to view in viewspace\n"
2784 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2785 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2786 "#ifdef USEDIFFUSE\n"
2787 "       // calculate diffuse shading\n"
2788 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2789 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2790 "#endif\n"
2791 "#ifdef USESPECULAR\n"
2792 "       // calculate directional shading\n"
2793 "       float3 eyevector = position * -1.0;\n"
2794 "#  ifdef USEEXACTSPECULARMATH\n"
2795 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2796 "#  else\n"
2797 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2798 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2799 "#  endif\n"
2800 "#endif\n"
2801 "\n"
2802 "#if defined(USESHADOWMAP2D)\n"
2803 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2804 "#ifdef USESHADOWMAPVSDCT\n"
2805 ", Texture_CubeProjection\n"
2806 "#endif\n"
2807 "       ));\n"
2808 "#endif\n"
2809 "\n"
2810 "#ifdef USEDIFFUSE\n"
2811 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2812 "#else\n"
2813 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2814 "#endif\n"
2815 "#ifdef USESPECULAR\n"
2816 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2817 "#else\n"
2818 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2819 "#endif\n"
2820 "\n"
2821 "# ifdef USECUBEFILTER\n"
2822 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2823 "       gl_FragData0.rgb *= cubecolor;\n"
2824 "       gl_FragData1.rgb *= cubecolor;\n"
2825 "# endif\n"
2826 "}\n"
2827 "#endif // FRAGMENT_SHADER\n"
2828 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2829 "\n"
2830 "\n"
2831 "\n"
2832 "\n"
2833 "#ifdef VERTEX_SHADER\n"
2834 "void main\n"
2835 "(\n"
2836 "float4 gl_Vertex : POSITION,\n"
2837 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2838 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2839 "float4 gl_Color : COLOR0,\n"
2840 "#endif\n"
2841 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2842 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2843 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2844 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2845 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2846 "\n"
2847 "uniform float3 EyePosition : register(c24),\n"
2848 "uniform float4x4 TexMatrix : register(c0),\n"
2849 "#ifdef USEVERTEXTEXTUREBLEND\n"
2850 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2851 "#endif\n"
2852 "#ifdef MODE_LIGHTSOURCE\n"
2853 "uniform float4x4 ModelToLight : register(c20),\n"
2854 "#endif\n"
2855 "#ifdef MODE_LIGHTSOURCE\n"
2856 "uniform float3 LightPosition : register(c27),\n"
2857 "#endif\n"
2858 "#ifdef MODE_LIGHTDIRECTION\n"
2859 "uniform float3 LightDir : register(c26),\n"
2860 "#endif\n"
2861 "uniform float4 FogPlane : register(c25),\n"
2862 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2863 "uniform float3 LightPosition : register(c27),\n"
2864 "#endif\n"
2865 "#ifdef USESHADOWMAPORTHO\n"
2866 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2867 "#endif\n"
2868 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2869 "out float4 gl_FrontColor : COLOR,\n"
2870 "#endif\n"
2871 "out float4 TexCoordBoth : TEXCOORD0,\n"
2872 "#ifdef USELIGHTMAP\n"
2873 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2874 "#endif\n"
2875 "#ifdef USEEYEVECTOR\n"
2876 "out float3 EyeVector : TEXCOORD2,\n"
2877 "#endif\n"
2878 "#ifdef USEREFLECTION\n"
2879 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2880 "#endif\n"
2881 "#ifdef USEFOG\n"
2882 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2883 "#endif\n"
2884 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2885 "out float3 LightVector : TEXCOORD1,\n"
2886 "#endif\n"
2887 "#ifdef MODE_LIGHTSOURCE\n"
2888 "out float3 CubeVector : TEXCOORD3,\n"
2889 "#endif\n"
2890 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2891 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2892 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2893 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2894 "#endif\n"
2895 "#ifdef USESHADOWMAPORTHO\n"
2896 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2897 "#endif\n"
2898 "out float4 gl_Position : POSITION\n"
2899 ")\n"
2900 "{\n"
2901 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2902 "#ifdef HLSL\n"
2903 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2904 "#else\n"
2905 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2906 "#endif\n"
2907 "#endif\n"
2908 "       // copy the surface texcoord\n"
2909 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2910 "#ifdef USEVERTEXTEXTUREBLEND\n"
2911 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2912 "#endif\n"
2913 "#ifdef USELIGHTMAP\n"
2914 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2915 "#endif\n"
2916 "\n"
2917 "#ifdef MODE_LIGHTSOURCE\n"
2918 "       // transform vertex position into light attenuation/cubemap space\n"
2919 "       // (-1 to +1 across the light box)\n"
2920 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2921 "\n"
2922 "# ifdef USEDIFFUSE\n"
2923 "       // transform unnormalized light direction into tangent space\n"
2924 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2925 "       //  normalize it per pixel)\n"
2926 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2927 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2928 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2929 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2930 "# endif\n"
2931 "#endif\n"
2932 "\n"
2933 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2934 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2935 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2936 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2937 "#endif\n"
2938 "\n"
2939 "       // transform unnormalized eye direction into tangent space\n"
2940 "#ifdef USEEYEVECTOR\n"
2941 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2942 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2943 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2944 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2945 "#endif\n"
2946 "\n"
2947 "#ifdef USEFOG\n"
2948 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2949 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2950 "#endif\n"
2951 "\n"
2952 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2953 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2954 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2955 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2956 "#endif\n"
2957 "\n"
2958 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2959 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2960 "\n"
2961 "#ifdef USESHADOWMAPORTHO\n"
2962 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2963 "#endif\n"
2964 "\n"
2965 "#ifdef USEREFLECTION\n"
2966 "       ModelViewProjectionPosition = gl_Position;\n"
2967 "#endif\n"
2968 "}\n"
2969 "#endif // VERTEX_SHADER\n"
2970 "\n"
2971 "\n"
2972 "\n"
2973 "\n"
2974 "#ifdef FRAGMENT_SHADER\n"
2975 "void main\n"
2976 "(\n"
2977 "#ifdef USEDEFERREDLIGHTMAP\n"
2978 "#ifdef HLSL\n"
2979 "float2 Pixel : VPOS,\n"
2980 "#else\n"
2981 "float2 Pixel : WPOS,\n"
2982 "#endif\n"
2983 "#endif\n"
2984 "float4 gl_FrontColor : COLOR,\n"
2985 "float4 TexCoordBoth : TEXCOORD0,\n"
2986 "#ifdef USELIGHTMAP\n"
2987 "float2 TexCoordLightmap : TEXCOORD1,\n"
2988 "#endif\n"
2989 "#ifdef USEEYEVECTOR\n"
2990 "float3 EyeVector : TEXCOORD2,\n"
2991 "#endif\n"
2992 "#ifdef USEREFLECTION\n"
2993 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2994 "#endif\n"
2995 "#ifdef USEFOG\n"
2996 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2997 "#endif\n"
2998 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2999 "float3 LightVector : TEXCOORD1,\n"
3000 "#endif\n"
3001 "#ifdef MODE_LIGHTSOURCE\n"
3002 "float3 CubeVector : TEXCOORD3,\n"
3003 "#endif\n"
3004 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3005 "float4 ModelViewPosition : TEXCOORD0,\n"
3006 "#endif\n"
3007 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
3008 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
3009 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
3010 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
3011 "#endif\n"
3012 "#ifdef USESHADOWMAPORTHO\n"
3013 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
3014 "#endif\n"
3015 "\n"
3016 "uniform sampler Texture_Normal : register(s0),\n"
3017 "uniform sampler Texture_Color : register(s1),\n"
3018 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3019 "uniform sampler Texture_Gloss : register(s2),\n"
3020 "#endif\n"
3021 "#ifdef USEGLOW\n"
3022 "uniform sampler Texture_Glow : register(s3),\n"
3023 "#endif\n"
3024 "#ifdef USEVERTEXTEXTUREBLEND\n"
3025 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
3026 "uniform sampler Texture_SecondaryColor : register(s5),\n"
3027 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3028 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3029 "#endif\n"
3030 "#ifdef USEGLOW\n"
3031 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3032 "#endif\n"
3033 "#endif\n"
3034 "#ifdef USECOLORMAPPING\n"
3035 "uniform sampler Texture_Pants : register(s4),\n"
3036 "uniform sampler Texture_Shirt : register(s7),\n"
3037 "#endif\n"
3038 "#ifdef USEFOG\n"
3039 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3040 "uniform sampler Texture_FogMask : register(s8),\n"
3041 "#endif\n"
3042 "#ifdef USELIGHTMAP\n"
3043 "uniform sampler Texture_Lightmap : register(s9),\n"
3044 "#endif\n"
3045 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3046 "uniform sampler Texture_Deluxemap : register(s10),\n"
3047 "#endif\n"
3048 "#ifdef USEREFLECTION\n"
3049 "uniform sampler Texture_Reflection : register(s7),\n"
3050 "#endif\n"
3051 "\n"
3052 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3053 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3054 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3055 "#endif\n"
3056 "#ifdef USEDEFERREDLIGHTMAP\n"
3057 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3058 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3059 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3060 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3061 "#endif\n"
3062 "\n"
3063 "#ifdef USECOLORMAPPING\n"
3064 "uniform half3 Color_Pants : register(c7),\n"
3065 "uniform half3 Color_Shirt : register(c8),\n"
3066 "#endif\n"
3067 "#ifdef USEFOG\n"
3068 "uniform float3 FogColor : register(c16),\n"
3069 "uniform float FogRangeRecip : register(c20),\n"
3070 "uniform float FogPlaneViewDist : register(c19),\n"
3071 "uniform float FogHeightFade : register(c17),\n"
3072 "#endif\n"
3073 "\n"
3074 "#ifdef USEOFFSETMAPPING\n"
3075 "uniform float OffsetMapping_Scale : register(c24),\n"
3076 "#endif\n"
3077 "\n"
3078 "#ifdef USEDEFERREDLIGHTMAP\n"
3079 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3080 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3081 "uniform half3 DeferredMod_Specular : register(c13),\n"
3082 "#endif\n"
3083 "uniform half3 Color_Ambient : register(c3),\n"
3084 "uniform half3 Color_Diffuse : register(c4),\n"
3085 "uniform half3 Color_Specular : register(c5),\n"
3086 "uniform half SpecularPower : register(c36),\n"
3087 "#ifdef USEGLOW\n"
3088 "uniform half3 Color_Glow : register(c6),\n"
3089 "#endif\n"
3090 "uniform half Alpha : register(c0),\n"
3091 "#ifdef USEREFLECTION\n"
3092 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3093 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3094 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3095 "uniform half4 ReflectColor : register(c26),\n"
3096 "#endif\n"
3097 "#ifdef USEREFLECTCUBE\n"
3098 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3099 "uniform sampler Texture_ReflectMask : register(s5),\n"
3100 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3101 "#endif\n"
3102 "#ifdef MODE_LIGHTDIRECTION\n"
3103 "uniform half3 LightColor : register(c21),\n"
3104 "#endif\n"
3105 "#ifdef MODE_LIGHTSOURCE\n"
3106 "uniform half3 LightColor : register(c21),\n"
3107 "#endif\n"
3108 "\n"
3109 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3110 "uniform sampler Texture_Attenuation : register(s9),\n"
3111 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3112 "#endif\n"
3113 "\n"
3114 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3115 "\n"
3116 "#ifdef USESHADOWMAP2D\n"
3117 "# ifdef USESHADOWSAMPLER\n"
3118 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3119 "# else\n"
3120 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3121 "# endif\n"
3122 "#endif\n"
3123 "\n"
3124 "#ifdef USESHADOWMAPVSDCT\n"
3125 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3126 "#endif\n"
3127 "\n"
3128 "#if defined(USESHADOWMAP2D)\n"
3129 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3130 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3131 "#endif\n"
3132 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3133 "\n"
3134 "out float4 gl_FragColor : COLOR\n"
3135 ")\n"
3136 "{\n"
3137 "       float2 TexCoord = TexCoordBoth.xy;\n"
3138 "#ifdef USEVERTEXTEXTUREBLEND\n"
3139 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3140 "#endif\n"
3141 "#ifdef USEOFFSETMAPPING\n"
3142 "       // apply offsetmapping\n"
3143 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3144 "#define TexCoord TexCoordOffset\n"
3145 "#endif\n"
3146 "\n"
3147 "       // combine the diffuse textures (base, pants, shirt)\n"
3148 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3149 "#ifdef USEALPHAKILL\n"
3150 "       if (color.a < 0.5)\n"
3151 "               discard;\n"
3152 "#endif\n"
3153 "       color.a *= Alpha;\n"
3154 "#ifdef USECOLORMAPPING\n"
3155 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3156 "#endif\n"
3157 "#ifdef USEVERTEXTEXTUREBLEND\n"
3158 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3159 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3160 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3161 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3162 "       color.a = 1.0;\n"
3163 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3164 "#endif\n"
3165 "\n"
3166 "       // get the surface normal\n"
3167 "#ifdef USEVERTEXTEXTUREBLEND\n"
3168 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3169 "#else\n"
3170 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3171 "#endif\n"
3172 "\n"
3173 "       // get the material colors\n"
3174 "       half3 diffusetex = color.rgb;\n"
3175 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3176 "# ifdef USEVERTEXTEXTUREBLEND\n"
3177 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3178 "# else\n"
3179 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3180 "# endif\n"
3181 "#endif\n"
3182 "\n"
3183 "#ifdef USEREFLECTCUBE\n"
3184 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3185 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3186 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3187 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3188 "#endif\n"
3189 "\n"
3190 "\n"
3191 "\n"
3192 "\n"
3193 "#ifdef MODE_LIGHTSOURCE\n"
3194 "       // light source\n"
3195 "#ifdef USEDIFFUSE\n"
3196 "       half3 lightnormal = half3(normalize(LightVector));\n"
3197 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3198 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3199 "#ifdef USESPECULAR\n"
3200 "#ifdef USEEXACTSPECULARMATH\n"
3201 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3202 "#else\n"
3203 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3204 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3205 "#endif\n"
3206 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3207 "#endif\n"
3208 "#else\n"
3209 "       color.rgb = diffusetex * Color_Ambient;\n"
3210 "#endif\n"
3211 "       color.rgb *= LightColor;\n"
3212 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3213 "#if defined(USESHADOWMAP2D)\n"
3214 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3215 "#ifdef USESHADOWMAPVSDCT\n"
3216 ", Texture_CubeProjection\n"
3217 "#endif\n"
3218 "       ));\n"
3219 "\n"
3220 "#endif\n"
3221 "# ifdef USECUBEFILTER\n"
3222 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3223 "# endif\n"
3224 "\n"
3225 "#ifdef USESHADOWMAP2D\n"
3226 "#ifdef USESHADOWMAPVSDCT\n"
3227 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3228 "#else\n"
3229 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3230 "#endif\n"
3231 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3232 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3233 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3234 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3235 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3236 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3237 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3238 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3239 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3240 "//     color.r = half(shadowmaptc.z);\n"
3241 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3242 "//     color.r = half(shadowmaptc.z);\n"
3243 "//     color.r = 1;\n"
3244 "//     color.rgb = abs(CubeVector);\n"
3245 "#endif\n"
3246 "//     color.rgb = half3(1,1,1);\n"
3247 "#endif // MODE_LIGHTSOURCE\n"
3248 "\n"
3249 "\n"
3250 "\n"
3251 "\n"
3252 "#ifdef MODE_LIGHTDIRECTION\n"
3253 "#define SHADING\n"
3254 "#ifdef USEDIFFUSE\n"
3255 "       half3 lightnormal = half3(normalize(LightVector));\n"
3256 "#endif\n"
3257 "#define lightcolor LightColor\n"
3258 "#endif // MODE_LIGHTDIRECTION\n"
3259 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3260 "#define SHADING\n"
3261 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3262 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3263 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3264 "       // convert modelspace light vector to tangentspace\n"
3265 "       half3 lightnormal;\n"
3266 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3267 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3268 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3269 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3270 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3271 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3272 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3273 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3274 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3275 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3276 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3277 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3278 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3279 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3280 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3281 "#define SHADING\n"
3282 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3283 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3284 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3285 "#endif\n"
3286 "\n"
3287 "\n"
3288 "\n"
3289 "\n"
3290 "#ifdef MODE_FAKELIGHT\n"
3291 "#define SHADING\n"
3292 "half3 lightnormal = half3(normalize(EyeVector));\n"
3293 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3294 "#endif // MODE_FAKELIGHT\n"
3295 "\n"
3296 "\n"
3297 "\n"
3298 "\n"
3299 "#ifdef MODE_LIGHTMAP\n"
3300 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3301 "#endif // MODE_LIGHTMAP\n"
3302 "#ifdef MODE_VERTEXCOLOR\n"
3303 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3304 "#endif // MODE_VERTEXCOLOR\n"
3305 "#ifdef MODE_FLATCOLOR\n"
3306 "       color.rgb = diffusetex * Color_Ambient;\n"
3307 "#endif // MODE_FLATCOLOR\n"
3308 "\n"
3309 "\n"
3310 "\n"
3311 "\n"
3312 "#ifdef SHADING\n"
3313 "# ifdef USEDIFFUSE\n"
3314 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3315 "#  ifdef USESPECULAR\n"
3316 "#   ifdef USEEXACTSPECULARMATH\n"
3317 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3318 "#   else\n"
3319 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3320 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3321 "#   endif\n"
3322 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3323 "#  else\n"
3324 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3325 "#  endif\n"
3326 "# else\n"
3327 "       color.rgb = diffusetex * Color_Ambient;\n"
3328 "# endif\n"
3329 "#endif\n"
3330 "\n"
3331 "#ifdef USESHADOWMAPORTHO\n"
3332 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3333 "#endif\n"
3334 "\n"
3335 "#ifdef USEDEFERREDLIGHTMAP\n"
3336 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3337 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3338 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3339 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3340 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3341 "#endif\n"
3342 "\n"
3343 "#ifdef USEGLOW\n"
3344 "#ifdef USEVERTEXTEXTUREBLEND\n"
3345 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3346 "#else\n"
3347 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3348 "#endif\n"
3349 "#endif\n"
3350 "\n"
3351 "#ifdef USEFOG\n"
3352 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3353 "#endif\n"
3354 "\n"
3355 "       // 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"
3356 "#ifdef USEREFLECTION\n"
3357 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3358 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3359 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3360 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3361 "       // FIXME temporary hack to detect the case that the reflection\n"
3362 "       // gets blackened at edges due to leaving the area that contains actual\n"
3363 "       // content.\n"
3364 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3365 "       // 'appening.\n"
3366 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3367 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3368 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3369 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3370 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3371 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3372 "#endif\n"
3373 "\n"
3374 "       gl_FragColor = float4(color);\n"
3375 "}\n"
3376 "#endif // FRAGMENT_SHADER\n"
3377 "\n"
3378 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3379 "#endif // !MODE_DEFERREDGEOMETRY\n"
3380 "#endif // !MODE_WATER\n"
3381 "#endif // !MODE_REFRACTION\n"
3382 "#endif // !MODE_BLOOMBLUR\n"
3383 "#endif // !MODE_GENERIC\n"
3384 "#endif // !MODE_POSTPROCESS\n"
3385 "#endif // !MODE_SHOWDEPTH\n"
3386 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3387 ;
3388
3389 char *glslshaderstring = NULL;
3390 char *hlslshaderstring = NULL;
3391
3392 //=======================================================================================================================================================
3393
3394 typedef struct shaderpermutationinfo_s
3395 {
3396         const char *pretext;
3397         const char *name;
3398 }
3399 shaderpermutationinfo_t;
3400
3401 typedef struct shadermodeinfo_s
3402 {
3403         const char *vertexfilename;
3404         const char *geometryfilename;
3405         const char *fragmentfilename;
3406         const char *pretext;
3407         const char *name;
3408 }
3409 shadermodeinfo_t;
3410
3411 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3412 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3413 {
3414         {"#define USEDIFFUSE\n", " diffuse"},
3415         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3416         {"#define USEVIEWTINT\n", " viewtint"},
3417         {"#define USECOLORMAPPING\n", " colormapping"},
3418         {"#define USESATURATION\n", " saturation"},
3419         {"#define USEFOGINSIDE\n", " foginside"},
3420         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3421         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3422         {"#define USEGAMMARAMPS\n", " gammaramps"},
3423         {"#define USECUBEFILTER\n", " cubefilter"},
3424         {"#define USEGLOW\n", " glow"},
3425         {"#define USEBLOOM\n", " bloom"},
3426         {"#define USESPECULAR\n", " specular"},
3427         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3428         {"#define USEREFLECTION\n", " reflection"},
3429         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3430         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3431         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3432         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3433         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3434         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3435         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3436         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3437         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3438         {"#define USEALPHAKILL\n", " alphakill"},
3439         {"#define USEREFLECTCUBE\n", " reflectcube"},
3440         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3441 };
3442
3443 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3444 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3445 {
3446         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3447         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3448         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3449         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3450         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3451         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3452         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3453         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3454         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3455         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3456         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3457         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3458         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3459         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3460         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3461         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3462         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDBOUNCELIGHT\n", " deferredbouncelight"},
3463 };
3464
3465 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3466 {
3467         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3468         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3469         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3470         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3471         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3472         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3473         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3474         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3475         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3476         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3477         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3478         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3479         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3480         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3481         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3482         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3483         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDBOUNCELIGHT\n", " deferredbouncelight"},
3484 };
3485
3486 struct r_glsl_permutation_s;
3487 typedef struct r_glsl_permutation_s
3488 {
3489         /// hash lookup data
3490         struct r_glsl_permutation_s *hashnext;
3491         unsigned int mode;
3492         unsigned int permutation;
3493
3494         /// indicates if we have tried compiling this permutation already
3495         qboolean compiled;
3496         /// 0 if compilation failed
3497         int program;
3498         // texture units assigned to each detected uniform
3499         int tex_Texture_First;
3500         int tex_Texture_Second;
3501         int tex_Texture_GammaRamps;
3502         int tex_Texture_Normal;
3503         int tex_Texture_Color;
3504         int tex_Texture_Gloss;
3505         int tex_Texture_Glow;
3506         int tex_Texture_SecondaryNormal;
3507         int tex_Texture_SecondaryColor;
3508         int tex_Texture_SecondaryGloss;
3509         int tex_Texture_SecondaryGlow;
3510         int tex_Texture_Pants;
3511         int tex_Texture_Shirt;
3512         int tex_Texture_FogHeightTexture;
3513         int tex_Texture_FogMask;
3514         int tex_Texture_Lightmap;
3515         int tex_Texture_Deluxemap;
3516         int tex_Texture_Attenuation;
3517         int tex_Texture_Cube;
3518         int tex_Texture_Refraction;
3519         int tex_Texture_Reflection;
3520         int tex_Texture_ShadowMap2D;
3521         int tex_Texture_CubeProjection;
3522         int tex_Texture_ScreenDepth;
3523         int tex_Texture_ScreenNormalMap;
3524         int tex_Texture_ScreenDiffuse;
3525         int tex_Texture_ScreenSpecular;
3526         int tex_Texture_ReflectMask;
3527         int tex_Texture_ReflectCube;
3528         /// locations of detected uniforms in program object, or -1 if not found
3529         int loc_Texture_First;
3530         int loc_Texture_Second;
3531         int loc_Texture_GammaRamps;
3532         int loc_Texture_Normal;
3533         int loc_Texture_Color;
3534         int loc_Texture_Gloss;
3535         int loc_Texture_Glow;
3536         int loc_Texture_SecondaryNormal;
3537         int loc_Texture_SecondaryColor;
3538         int loc_Texture_SecondaryGloss;
3539         int loc_Texture_SecondaryGlow;
3540         int loc_Texture_Pants;
3541         int loc_Texture_Shirt;
3542         int loc_Texture_FogHeightTexture;
3543         int loc_Texture_FogMask;
3544         int loc_Texture_Lightmap;
3545         int loc_Texture_Deluxemap;
3546         int loc_Texture_Attenuation;
3547         int loc_Texture_Cube;
3548         int loc_Texture_Refraction;
3549         int loc_Texture_Reflection;
3550         int loc_Texture_ShadowMap2D;
3551         int loc_Texture_CubeProjection;
3552         int loc_Texture_ScreenDepth;
3553         int loc_Texture_ScreenNormalMap;
3554         int loc_Texture_ScreenDiffuse;
3555         int loc_Texture_ScreenSpecular;
3556         int loc_Texture_ReflectMask;
3557         int loc_Texture_ReflectCube;
3558         int loc_Alpha;
3559         int loc_BloomBlur_Parameters;
3560         int loc_ClientTime;
3561         int loc_Color_Ambient;
3562         int loc_Color_Diffuse;
3563         int loc_Color_Specular;
3564         int loc_Color_Glow;
3565         int loc_Color_Pants;
3566         int loc_Color_Shirt;
3567         int loc_DeferredColor_Ambient;
3568         int loc_DeferredColor_Diffuse;
3569         int loc_DeferredColor_Specular;
3570         int loc_DeferredMod_Diffuse;
3571         int loc_DeferredMod_Specular;
3572         int loc_DistortScaleRefractReflect;
3573         int loc_EyePosition;
3574         int loc_FogColor;
3575         int loc_FogHeightFade;
3576         int loc_FogPlane;
3577         int loc_FogPlaneViewDist;
3578         int loc_FogRangeRecip;
3579         int loc_LightColor;
3580         int loc_LightDir;
3581         int loc_LightPosition;
3582         int loc_OffsetMapping_Scale;
3583         int loc_PixelSize;
3584         int loc_ReflectColor;
3585         int loc_ReflectFactor;
3586         int loc_ReflectOffset;
3587         int loc_RefractColor;
3588         int loc_Saturation;
3589         int loc_ScreenCenterRefractReflect;
3590         int loc_ScreenScaleRefractReflect;
3591         int loc_ScreenToDepth;
3592         int loc_ShadowMap_Parameters;
3593         int loc_ShadowMap_TextureScale;
3594         int loc_SpecularPower;
3595         int loc_UserVec1;
3596         int loc_UserVec2;
3597         int loc_UserVec3;
3598         int loc_UserVec4;
3599         int loc_ViewTintColor;
3600         int loc_ViewToLight;
3601         int loc_ModelToLight;
3602         int loc_TexMatrix;
3603         int loc_BackgroundTexMatrix;
3604         int loc_ModelViewProjectionMatrix;
3605         int loc_ModelViewMatrix;
3606         int loc_PixelToScreenTexCoord;
3607         int loc_ModelToReflectCube;
3608         int loc_ShadowMapMatrix;
3609         int loc_BloomColorSubtract;
3610         int loc_NormalmapScrollBlend;
3611 }
3612 r_glsl_permutation_t;
3613
3614 #define SHADERPERMUTATION_HASHSIZE 256
3615
3616
3617 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3618 // these can NOT degrade! only use for simple stuff
3619 enum
3620 {
3621         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3622         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3623         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3624         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3625         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3626         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3627 };
3628 #define SHADERSTATICPARMS_COUNT 6
3629
3630 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3631 static int shaderstaticparms_count = 0;
3632
3633 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3634 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3635 qboolean R_CompileShader_CheckStaticParms(void)
3636 {
3637         static int r_compileshader_staticparms_save[1];
3638         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3639         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3640
3641         // detect all
3642         if (r_glsl_saturation_redcompensate.integer)
3643                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3644         if (r_shadow_glossexact.integer)
3645                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3646         if (r_glsl_postprocess.integer)
3647         {
3648                 if (r_glsl_postprocess_uservec1_enable.integer)
3649                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3650                 if (r_glsl_postprocess_uservec2_enable.integer)
3651                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3652                 if (r_glsl_postprocess_uservec3_enable.integer)
3653                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3654                 if (r_glsl_postprocess_uservec4_enable.integer)
3655                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3656         }
3657         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3658 }
3659
3660 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3661         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3662                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3663         else \
3664                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3665 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3666 {
3667         shaderstaticparms_count = 0;
3668
3669         // emit all
3670         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3671         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3672         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3673         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3674         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3675         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3676 }
3677
3678 /// information about each possible shader permutation
3679 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3680 /// currently selected permutation
3681 r_glsl_permutation_t *r_glsl_permutation;
3682 /// storage for permutations linked in the hash table
3683 memexpandablearray_t r_glsl_permutationarray;
3684
3685 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3686 {
3687         //unsigned int hashdepth = 0;
3688         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3689         r_glsl_permutation_t *p;
3690         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3691         {
3692                 if (p->mode == mode && p->permutation == permutation)
3693                 {
3694                         //if (hashdepth > 10)
3695                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3696                         return p;
3697                 }
3698                 //hashdepth++;
3699         }
3700         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3701         p->mode = mode;
3702         p->permutation = permutation;
3703         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3704         r_glsl_permutationhash[mode][hashindex] = p;
3705         //if (hashdepth > 10)
3706         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3707         return p;
3708 }
3709
3710 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3711 {
3712         char *shaderstring;
3713         if (!filename || !filename[0])
3714                 return NULL;
3715         if (!strcmp(filename, "glsl/default.glsl"))
3716         {
3717                 if (!glslshaderstring)
3718                 {
3719                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3720                         if (glslshaderstring)
3721                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3722                         else
3723                                 glslshaderstring = (char *)builtinshaderstring;
3724                 }
3725                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3726                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3727                 return shaderstring;
3728         }
3729         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3730         if (shaderstring)
3731         {
3732                 if (printfromdisknotice)
3733                         Con_DPrintf("from disk %s... ", filename);
3734                 return shaderstring;
3735         }
3736         return shaderstring;
3737 }
3738
3739 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3740 {
3741         int i;
3742         int sampler;
3743         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3744         char *vertexstring, *geometrystring, *fragmentstring;
3745         char permutationname[256];
3746         int vertstrings_count = 0;
3747         int geomstrings_count = 0;
3748         int fragstrings_count = 0;
3749         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3750         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3751         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3752
3753         if (p->compiled)
3754                 return;
3755         p->compiled = true;
3756         p->program = 0;
3757
3758         permutationname[0] = 0;
3759         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3760         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3761         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3762
3763         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3764
3765         // the first pretext is which type of shader to compile as
3766         // (later these will all be bound together as a program object)
3767         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3768         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3769         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3770
3771         // the second pretext is the mode (for example a light source)
3772         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3773         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3774         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3775         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3776
3777         // now add all the permutation pretexts
3778         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3779         {
3780                 if (permutation & (1<<i))
3781                 {
3782                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3783                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3784                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3785                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3786                 }
3787                 else
3788                 {
3789                         // keep line numbers correct
3790                         vertstrings_list[vertstrings_count++] = "\n";
3791                         geomstrings_list[geomstrings_count++] = "\n";
3792                         fragstrings_list[fragstrings_count++] = "\n";
3793                 }
3794         }
3795
3796         // add static parms
3797         R_CompileShader_AddStaticParms(mode, permutation);
3798         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3799         vertstrings_count += shaderstaticparms_count;
3800         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3801         geomstrings_count += shaderstaticparms_count;
3802         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3803         fragstrings_count += shaderstaticparms_count;
3804
3805         // now append the shader text itself
3806         vertstrings_list[vertstrings_count++] = vertexstring;
3807         geomstrings_list[geomstrings_count++] = geometrystring;
3808         fragstrings_list[fragstrings_count++] = fragmentstring;
3809
3810         // if any sources were NULL, clear the respective list
3811         if (!vertexstring)
3812                 vertstrings_count = 0;
3813         if (!geometrystring)
3814                 geomstrings_count = 0;
3815         if (!fragmentstring)
3816                 fragstrings_count = 0;
3817
3818         // compile the shader program
3819         if (vertstrings_count + geomstrings_count + fragstrings_count)
3820                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3821         if (p->program)
3822         {
3823                 CHECKGLERROR
3824                 qglUseProgram(p->program);CHECKGLERROR
3825                 // look up all the uniform variable names we care about, so we don't
3826                 // have to look them up every time we set them
3827
3828                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
3829                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
3830                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3831                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
3832                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
3833                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
3834                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
3835                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3836                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3837                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3838                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3839                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
3840                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
3841                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3842                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
3843                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
3844                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3845                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
3846                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
3847                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
3848                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
3849                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3850                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3851                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3852                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3853                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3854                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3855                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3856                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3857                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
3858                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3859                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
3860                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
3861                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
3862                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
3863                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
3864                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
3865                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
3866                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3867                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3868                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3869                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3870                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3871                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3872                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
3873                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
3874                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
3875                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
3876                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3877                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
3878                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
3879                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
3880                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
3881                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3882                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
3883                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
3884                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
3885                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
3886                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
3887                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
3888                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3889                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3890                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
3891                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3892                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3893                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
3894                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
3895                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
3896                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
3897                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
3898                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
3899                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
3900                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
3901                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
3902                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3903                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
3904                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3905                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3906                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
3907                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3908                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
3909                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3910                 // initialize the samplers to refer to the texture units we use
3911                 p->tex_Texture_First = -1;
3912                 p->tex_Texture_Second = -1;
3913                 p->tex_Texture_GammaRamps = -1;
3914                 p->tex_Texture_Normal = -1;
3915                 p->tex_Texture_Color = -1;
3916                 p->tex_Texture_Gloss = -1;
3917                 p->tex_Texture_Glow = -1;
3918                 p->tex_Texture_SecondaryNormal = -1;
3919                 p->tex_Texture_SecondaryColor = -1;
3920                 p->tex_Texture_SecondaryGloss = -1;
3921                 p->tex_Texture_SecondaryGlow = -1;
3922                 p->tex_Texture_Pants = -1;
3923                 p->tex_Texture_Shirt = -1;
3924                 p->tex_Texture_FogHeightTexture = -1;
3925                 p->tex_Texture_FogMask = -1;
3926                 p->tex_Texture_Lightmap = -1;
3927                 p->tex_Texture_Deluxemap = -1;
3928                 p->tex_Texture_Attenuation = -1;
3929                 p->tex_Texture_Cube = -1;
3930                 p->tex_Texture_Refraction = -1;
3931                 p->tex_Texture_Reflection = -1;
3932                 p->tex_Texture_ShadowMap2D = -1;
3933                 p->tex_Texture_CubeProjection = -1;
3934                 p->tex_Texture_ScreenDepth = -1;
3935                 p->tex_Texture_ScreenNormalMap = -1;
3936                 p->tex_Texture_ScreenDiffuse = -1;
3937                 p->tex_Texture_ScreenSpecular = -1;
3938                 p->tex_Texture_ReflectMask = -1;
3939                 p->tex_Texture_ReflectCube = -1;
3940                 sampler = 0;
3941                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
3942                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
3943                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
3944                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
3945                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
3946                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
3947                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
3948                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3949                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
3950                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
3951                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
3952                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
3953                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
3954                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3955                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
3956                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
3957                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
3958                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
3959                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
3960                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
3961                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
3962                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
3963                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
3964                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
3965                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3966                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
3967                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
3968                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
3969                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
3970                 CHECKGLERROR
3971                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3972         }
3973         else
3974                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3975
3976         // free the strings
3977         if (vertexstring)
3978                 Mem_Free(vertexstring);
3979         if (geometrystring)
3980                 Mem_Free(geometrystring);
3981         if (fragmentstring)
3982                 Mem_Free(fragmentstring);
3983 }
3984
3985 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3986 {
3987         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3988         if (r_glsl_permutation != perm)
3989         {
3990                 r_glsl_permutation = perm;
3991                 if (!r_glsl_permutation->program)
3992                 {
3993                         if (!r_glsl_permutation->compiled)
3994                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3995                         if (!r_glsl_permutation->program)
3996                         {
3997                                 // remove features until we find a valid permutation
3998                                 int i;
3999                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4000                                 {
4001                                         // reduce i more quickly whenever it would not remove any bits
4002                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4003                                         if (!(permutation & j))
4004                                                 continue;
4005                                         permutation -= j;
4006                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4007                                         if (!r_glsl_permutation->compiled)
4008                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4009                                         if (r_glsl_permutation->program)
4010                                                 break;
4011                                 }
4012                                 if (i >= SHADERPERMUTATION_COUNT)
4013                                 {
4014                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4015                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4016                                         qglUseProgram(0);CHECKGLERROR
4017                                         return; // no bit left to clear, entire mode is broken
4018                                 }
4019                         }
4020                 }
4021                 CHECKGLERROR
4022                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
4023         }
4024         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4025         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4026         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
4027 }
4028
4029 #ifdef SUPPORTD3D
4030
4031 #ifdef SUPPORTD3D
4032 #include <d3d9.h>
4033 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4034 extern D3DCAPS9 vid_d3d9caps;
4035 #endif
4036
4037 struct r_hlsl_permutation_s;
4038 typedef struct r_hlsl_permutation_s
4039 {
4040         /// hash lookup data
4041         struct r_hlsl_permutation_s *hashnext;
4042         unsigned int mode;
4043         unsigned int permutation;
4044
4045         /// indicates if we have tried compiling this permutation already
4046         qboolean compiled;
4047         /// NULL if compilation failed
4048         IDirect3DVertexShader9 *vertexshader;
4049         IDirect3DPixelShader9 *pixelshader;
4050 }
4051 r_hlsl_permutation_t;
4052
4053 typedef enum D3DVSREGISTER_e
4054 {
4055         D3DVSREGISTER_TexMatrix = 0, // float4x4
4056         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4057         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4058         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4059         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4060         D3DVSREGISTER_ModelToLight = 20, // float4x4
4061         D3DVSREGISTER_EyePosition = 24,
4062         D3DVSREGISTER_FogPlane = 25,
4063         D3DVSREGISTER_LightDir = 26,
4064         D3DVSREGISTER_LightPosition = 27,
4065 }
4066 D3DVSREGISTER_t;
4067
4068 typedef enum D3DPSREGISTER_e
4069 {
4070         D3DPSREGISTER_Alpha = 0,
4071         D3DPSREGISTER_BloomBlur_Parameters = 1,
4072         D3DPSREGISTER_ClientTime = 2,
4073         D3DPSREGISTER_Color_Ambient = 3,
4074         D3DPSREGISTER_Color_Diffuse = 4,
4075         D3DPSREGISTER_Color_Specular = 5,
4076         D3DPSREGISTER_Color_Glow = 6,
4077         D3DPSREGISTER_Color_Pants = 7,
4078         D3DPSREGISTER_Color_Shirt = 8,
4079         D3DPSREGISTER_DeferredColor_Ambient = 9,
4080         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4081         D3DPSREGISTER_DeferredColor_Specular = 11,
4082         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4083         D3DPSREGISTER_DeferredMod_Specular = 13,
4084         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4085         D3DPSREGISTER_EyePosition = 15, // unused
4086         D3DPSREGISTER_FogColor = 16,
4087         D3DPSREGISTER_FogHeightFade = 17,
4088         D3DPSREGISTER_FogPlane = 18,
4089         D3DPSREGISTER_FogPlaneViewDist = 19,
4090         D3DPSREGISTER_FogRangeRecip = 20,
4091         D3DPSREGISTER_LightColor = 21,
4092         D3DPSREGISTER_LightDir = 22, // unused
4093         D3DPSREGISTER_LightPosition = 23,
4094         D3DPSREGISTER_OffsetMapping_Scale = 24,
4095         D3DPSREGISTER_PixelSize = 25,
4096         D3DPSREGISTER_ReflectColor = 26,
4097         D3DPSREGISTER_ReflectFactor = 27,
4098         D3DPSREGISTER_ReflectOffset = 28,
4099         D3DPSREGISTER_RefractColor = 29,
4100         D3DPSREGISTER_Saturation = 30,
4101         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4102         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4103         D3DPSREGISTER_ScreenToDepth = 33,
4104         D3DPSREGISTER_ShadowMap_Parameters = 34,
4105         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4106         D3DPSREGISTER_SpecularPower = 36,
4107         D3DPSREGISTER_UserVec1 = 37,
4108         D3DPSREGISTER_UserVec2 = 38,
4109         D3DPSREGISTER_UserVec3 = 39,
4110         D3DPSREGISTER_UserVec4 = 40,
4111         D3DPSREGISTER_ViewTintColor = 41,
4112         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4113         D3DPSREGISTER_BloomColorSubtract = 43,
4114         D3DPSREGISTER_ViewToLight = 44, // float4x4
4115         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4116         D3DPSREGISTER_NormalmapScrollBlend = 52,
4117         // next at 53
4118 }
4119 D3DPSREGISTER_t;
4120
4121 /// information about each possible shader permutation
4122 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4123 /// currently selected permutation
4124 r_hlsl_permutation_t *r_hlsl_permutation;
4125 /// storage for permutations linked in the hash table
4126 memexpandablearray_t r_hlsl_permutationarray;
4127
4128 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4129 {
4130         //unsigned int hashdepth = 0;
4131         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4132         r_hlsl_permutation_t *p;
4133         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4134         {
4135                 if (p->mode == mode && p->permutation == permutation)
4136                 {
4137                         //if (hashdepth > 10)
4138                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4139                         return p;
4140                 }
4141                 //hashdepth++;
4142         }
4143         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4144         p->mode = mode;
4145         p->permutation = permutation;
4146         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4147         r_hlsl_permutationhash[mode][hashindex] = p;
4148         //if (hashdepth > 10)
4149         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4150         return p;
4151 }
4152
4153 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4154 {
4155         char *shaderstring;
4156         if (!filename || !filename[0])
4157                 return NULL;
4158         if (!strcmp(filename, "hlsl/default.hlsl"))
4159         {
4160                 if (!hlslshaderstring)
4161                 {
4162                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4163                         if (hlslshaderstring)
4164                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4165                         else
4166                                 hlslshaderstring = (char *)builtinhlslshaderstring;
4167                 }
4168                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4169                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4170                 return shaderstring;
4171         }
4172         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4173         if (shaderstring)
4174         {
4175                 if (printfromdisknotice)
4176                         Con_DPrintf("from disk %s... ", filename);
4177                 return shaderstring;
4178         }
4179         return shaderstring;
4180 }
4181
4182 #include <d3dx9.h>
4183 //#include <d3dx9shader.h>
4184 //#include <d3dx9mesh.h>
4185
4186 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4187 {
4188         DWORD *vsbin = NULL;
4189         DWORD *psbin = NULL;
4190         fs_offset_t vsbinsize;
4191         fs_offset_t psbinsize;
4192 //      IDirect3DVertexShader9 *vs = NULL;
4193 //      IDirect3DPixelShader9 *ps = NULL;
4194         ID3DXBuffer *vslog = NULL;
4195         ID3DXBuffer *vsbuffer = NULL;
4196         ID3DXConstantTable *vsconstanttable = NULL;
4197         ID3DXBuffer *pslog = NULL;
4198         ID3DXBuffer *psbuffer = NULL;
4199         ID3DXConstantTable *psconstanttable = NULL;
4200         int vsresult = 0;
4201         int psresult = 0;
4202         char temp[MAX_INPUTLINE];
4203         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4204         qboolean debugshader = gl_paranoid.integer != 0;
4205         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4206         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4207         if (!debugshader)
4208         {
4209                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4210                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4211         }
4212         if ((!vsbin && vertstring) || (!psbin && fragstring))
4213         {
4214                 const char* dllnames_d3dx9 [] =
4215                 {
4216                         "d3dx9_43.dll",
4217                         "d3dx9_42.dll",
4218                         "d3dx9_41.dll",
4219                         "d3dx9_40.dll",
4220                         "d3dx9_39.dll",
4221                         "d3dx9_38.dll",
4222                         "d3dx9_37.dll",
4223                         "d3dx9_36.dll",
4224                         "d3dx9_35.dll",
4225                         "d3dx9_34.dll",
4226                         "d3dx9_33.dll",
4227                         "d3dx9_32.dll",
4228                         "d3dx9_31.dll",
4229                         "d3dx9_30.dll",
4230                         "d3dx9_29.dll",
4231                         "d3dx9_28.dll",
4232                         "d3dx9_27.dll",
4233                         "d3dx9_26.dll",
4234                         "d3dx9_25.dll",
4235                         "d3dx9_24.dll",
4236                         NULL
4237                 };
4238                 dllhandle_t d3dx9_dll = NULL;
4239                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4240                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4241                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4242                 dllfunction_t d3dx9_dllfuncs[] =
4243                 {
4244                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4245                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4246                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4247                         {NULL, NULL}
4248                 };
4249                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4250                 {
4251                         DWORD shaderflags = 0;
4252                         if (debugshader)
4253                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4254                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4255                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4256                         if (vertstring && vertstring[0])
4257                         {
4258                                 if (debugshader)
4259                                 {
4260 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4261 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4262                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4263                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4264                                 }
4265                                 else
4266                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4267                                 if (vsbuffer)
4268                                 {
4269                                         vsbinsize = vsbuffer->GetBufferSize();
4270                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4271                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4272                                         vsbuffer->Release();
4273                                 }
4274                                 if (vslog)
4275                                 {
4276                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4277                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4278                                         vslog->Release();
4279                                 }
4280                         }
4281                         if (fragstring && fragstring[0])
4282                         {
4283                                 if (debugshader)
4284                                 {
4285 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4286 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4287                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4288                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4289                                 }
4290                                 else
4291                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4292                                 if (psbuffer)
4293                                 {
4294                                         psbinsize = psbuffer->GetBufferSize();
4295                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4296                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4297                                         psbuffer->Release();
4298                                 }
4299                                 if (pslog)
4300                                 {
4301                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4302                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4303                                         pslog->Release();
4304                                 }
4305                         }
4306                         Sys_UnloadLibrary(&d3dx9_dll);
4307                 }
4308                 else
4309                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4310         }
4311         if (vsbin && psbin)
4312         {
4313                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4314                 if (FAILED(vsresult))
4315                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4316                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4317                 if (FAILED(psresult))
4318                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4319         }
4320         // free the shader data
4321         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4322         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4323 }
4324
4325 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4326 {
4327         int i;
4328         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4329         int vertstring_length = 0;
4330         int geomstring_length = 0;
4331         int fragstring_length = 0;
4332         char *t;
4333         char *vertexstring, *geometrystring, *fragmentstring;
4334         char *vertstring, *geomstring, *fragstring;
4335         char permutationname[256];
4336         char cachename[256];
4337         int vertstrings_count = 0;
4338         int geomstrings_count = 0;
4339         int fragstrings_count = 0;
4340         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4341         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4342         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4343
4344         if (p->compiled)
4345                 return;
4346         p->compiled = true;
4347         p->vertexshader = NULL;
4348         p->pixelshader = NULL;
4349
4350         permutationname[0] = 0;
4351         cachename[0] = 0;
4352         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4353         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4354         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4355
4356         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4357         strlcat(cachename, "hlsl/", sizeof(cachename));
4358
4359         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4360         vertstrings_count = 0;
4361         geomstrings_count = 0;
4362         fragstrings_count = 0;
4363         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4364         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4365         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4366
4367         // the first pretext is which type of shader to compile as
4368         // (later these will all be bound together as a program object)
4369         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4370         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4371         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4372
4373         // the second pretext is the mode (for example a light source)
4374         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4375         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4376         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4377         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4378         strlcat(cachename, modeinfo->name, sizeof(cachename));
4379
4380         // now add all the permutation pretexts
4381         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4382         {
4383                 if (permutation & (1<<i))
4384                 {
4385                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4386                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4387                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4388                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4389                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4390                 }
4391                 else
4392                 {
4393                         // keep line numbers correct
4394                         vertstrings_list[vertstrings_count++] = "\n";
4395                         geomstrings_list[geomstrings_count++] = "\n";
4396                         fragstrings_list[fragstrings_count++] = "\n";
4397                 }
4398         }
4399
4400         // add static parms
4401         R_CompileShader_AddStaticParms(mode, permutation);
4402         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4403         vertstrings_count += shaderstaticparms_count;
4404         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4405         geomstrings_count += shaderstaticparms_count;
4406         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4407         fragstrings_count += shaderstaticparms_count;
4408
4409         // replace spaces in the cachename with _ characters
4410         for (i = 0;cachename[i];i++)
4411                 if (cachename[i] == ' ')
4412                         cachename[i] = '_';
4413
4414         // now append the shader text itself
4415         vertstrings_list[vertstrings_count++] = vertexstring;
4416         geomstrings_list[geomstrings_count++] = geometrystring;
4417         fragstrings_list[fragstrings_count++] = fragmentstring;
4418
4419         // if any sources were NULL, clear the respective list
4420         if (!vertexstring)
4421                 vertstrings_count = 0;
4422         if (!geometrystring)
4423                 geomstrings_count = 0;
4424         if (!fragmentstring)
4425                 fragstrings_count = 0;
4426
4427         vertstring_length = 0;
4428         for (i = 0;i < vertstrings_count;i++)
4429                 vertstring_length += strlen(vertstrings_list[i]);
4430         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4431         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4432                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4433
4434         geomstring_length = 0;
4435         for (i = 0;i < geomstrings_count;i++)
4436                 geomstring_length += strlen(geomstrings_list[i]);
4437         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4438         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4439                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4440
4441         fragstring_length = 0;
4442         for (i = 0;i < fragstrings_count;i++)
4443                 fragstring_length += strlen(fragstrings_list[i]);
4444         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4445         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4446                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4447
4448         // try to load the cached shader, or generate one
4449         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4450
4451         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4452                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4453         else
4454                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4455
4456         // free the strings
4457         if (vertstring)
4458                 Mem_Free(vertstring);
4459         if (geomstring)
4460                 Mem_Free(geomstring);
4461         if (fragstring)
4462                 Mem_Free(fragstring);
4463         if (vertexstring)
4464                 Mem_Free(vertexstring);
4465         if (geometrystring)
4466                 Mem_Free(geometrystring);
4467         if (fragmentstring)
4468                 Mem_Free(fragmentstring);
4469 }
4470
4471 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4472 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4473 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);}
4474 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);}
4475 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);}
4476 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);}
4477
4478 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4479 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4480 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);}
4481 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);}
4482 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);}
4483 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);}
4484
4485 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4486 {
4487         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4488         if (r_hlsl_permutation != perm)
4489         {
4490                 r_hlsl_permutation = perm;
4491                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4492                 {
4493                         if (!r_hlsl_permutation->compiled)
4494                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4495                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4496                         {
4497                                 // remove features until we find a valid permutation
4498                                 int i;
4499                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4500                                 {
4501                                         // reduce i more quickly whenever it would not remove any bits
4502                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4503                                         if (!(permutation & j))
4504                                                 continue;
4505                                         permutation -= j;
4506                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4507                                         if (!r_hlsl_permutation->compiled)
4508                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4509                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4510                                                 break;
4511                                 }
4512                                 if (i >= SHADERPERMUTATION_COUNT)
4513                                 {
4514                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4515                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4516                                         return; // no bit left to clear, entire mode is broken
4517                                 }
4518                         }
4519                 }
4520                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4521                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4522         }
4523         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4524         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4525         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4526 }
4527 #endif
4528
4529 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4530 {
4531         DPSOFTRAST_SetShader(mode, permutation);
4532         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4533         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4534         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4535 }
4536
4537 void R_GLSL_Restart_f(void)
4538 {
4539         unsigned int i, limit;
4540         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4541                 Mem_Free(glslshaderstring);
4542         glslshaderstring = NULL;
4543         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4544                 Mem_Free(hlslshaderstring);
4545         hlslshaderstring = NULL;
4546         switch(vid.renderpath)
4547         {
4548         case RENDERPATH_D3D9:
4549 #ifdef SUPPORTD3D
4550                 {
4551                         r_hlsl_permutation_t *p;
4552                         r_hlsl_permutation = NULL;
4553                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4554                         for (i = 0;i < limit;i++)
4555                         {
4556                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4557                                 {
4558                                         if (p->vertexshader)
4559                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4560                                         if (p->pixelshader)
4561                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4562                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4563                                 }
4564                         }
4565                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4566                 }
4567 #endif
4568                 break;
4569         case RENDERPATH_D3D10:
4570                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4571                 break;
4572         case RENDERPATH_D3D11:
4573                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4574                 break;
4575         case RENDERPATH_GL20:
4576         case RENDERPATH_GLES2:
4577                 {
4578                         r_glsl_permutation_t *p;
4579                         r_glsl_permutation = NULL;
4580                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4581                         for (i = 0;i < limit;i++)
4582                         {
4583                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4584                                 {
4585                                         GL_Backend_FreeProgram(p->program);
4586                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4587                                 }
4588                         }
4589                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4590                 }
4591                 break;
4592         case RENDERPATH_GL13:
4593         case RENDERPATH_GL11:
4594                 break;
4595         case RENDERPATH_SOFT:
4596                 break;
4597         }
4598 }
4599
4600 void R_GLSL_DumpShader_f(void)
4601 {
4602         int i;
4603         qfile_t *file;
4604
4605         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4606         if (file)
4607         {
4608                 FS_Print(file, "/* The engine may define the following macros:\n");
4609                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4610                 for (i = 0;i < SHADERMODE_COUNT;i++)
4611                         FS_Print(file, glslshadermodeinfo[i].pretext);
4612                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4613                         FS_Print(file, shaderpermutationinfo[i].pretext);
4614                 FS_Print(file, "*/\n");
4615                 FS_Print(file, builtinshaderstring);
4616                 FS_Close(file);
4617                 Con_Printf("glsl/default.glsl written\n");
4618         }
4619         else
4620                 Con_Printf("failed to write to glsl/default.glsl\n");
4621
4622         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4623         if (file)
4624         {
4625                 FS_Print(file, "/* The engine may define the following macros:\n");
4626                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4627                 for (i = 0;i < SHADERMODE_COUNT;i++)
4628                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4629                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4630                         FS_Print(file, shaderpermutationinfo[i].pretext);
4631                 FS_Print(file, "*/\n");
4632                 FS_Print(file, builtinhlslshaderstring);
4633                 FS_Close(file);
4634                 Con_Printf("hlsl/default.hlsl written\n");
4635         }
4636         else
4637                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4638 }
4639
4640 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4641 {
4642         if (!second)
4643                 texturemode = GL_MODULATE;
4644         switch (vid.renderpath)
4645         {
4646         case RENDERPATH_D3D9:
4647 #ifdef SUPPORTD3D
4648                 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))));
4649                 R_Mesh_TexBind(GL20TU_FIRST , first );
4650                 R_Mesh_TexBind(GL20TU_SECOND, second);
4651 #endif
4652                 break;
4653         case RENDERPATH_D3D10:
4654                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4655                 break;
4656         case RENDERPATH_D3D11:
4657                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4658                 break;
4659         case RENDERPATH_GL20:
4660         case RENDERPATH_GLES2:
4661                 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))));
4662                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4663                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4664                 break;
4665         case RENDERPATH_GL13:
4666                 R_Mesh_TexBind(0, first );
4667                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4668                 R_Mesh_TexBind(1, second);
4669                 if (second)
4670                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4671                 break;
4672         case RENDERPATH_GL11:
4673                 R_Mesh_TexBind(0, first );
4674                 break;
4675         case RENDERPATH_SOFT:
4676                 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))));
4677                 R_Mesh_TexBind(GL20TU_FIRST , first );
4678                 R_Mesh_TexBind(GL20TU_SECOND, second);
4679                 break;
4680         }
4681 }
4682
4683 void R_SetupShader_DepthOrShadow(void)
4684 {
4685         switch (vid.renderpath)
4686         {
4687         case RENDERPATH_D3D9:
4688 #ifdef SUPPORTD3D
4689                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4690 #endif
4691                 break;
4692         case RENDERPATH_D3D10:
4693                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4694                 break;
4695         case RENDERPATH_D3D11:
4696                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4697                 break;
4698         case RENDERPATH_GL20:
4699         case RENDERPATH_GLES2:
4700                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4701                 break;
4702         case RENDERPATH_GL13:
4703                 R_Mesh_TexBind(0, 0);
4704                 R_Mesh_TexBind(1, 0);
4705                 break;
4706         case RENDERPATH_GL11:
4707                 R_Mesh_TexBind(0, 0);
4708                 break;
4709         case RENDERPATH_SOFT:
4710                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4711                 break;
4712         }
4713 }
4714
4715 void R_SetupShader_ShowDepth(void)
4716 {
4717         switch (vid.renderpath)
4718         {
4719         case RENDERPATH_D3D9:
4720 #ifdef SUPPORTHLSL
4721                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4722 #endif
4723                 break;
4724         case RENDERPATH_D3D10:
4725                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4726                 break;
4727         case RENDERPATH_D3D11:
4728                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4729                 break;
4730         case RENDERPATH_GL20:
4731         case RENDERPATH_GLES2:
4732                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4733                 break;
4734         case RENDERPATH_GL13:
4735                 break;
4736         case RENDERPATH_GL11:
4737                 break;
4738         case RENDERPATH_SOFT:
4739                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4740                 break;
4741         }
4742 }
4743
4744 extern qboolean r_shadow_usingdeferredprepass;
4745 extern cvar_t r_shadow_deferred_8bitrange;
4746 extern rtexture_t *r_shadow_attenuationgradienttexture;
4747 extern rtexture_t *r_shadow_attenuation2dtexture;
4748 extern rtexture_t *r_shadow_attenuation3dtexture;
4749 extern qboolean r_shadow_usingshadowmap2d;
4750 extern qboolean r_shadow_usingshadowmaportho;
4751 extern float r_shadow_shadowmap_texturescale[2];
4752 extern float r_shadow_shadowmap_parameters[4];
4753 extern qboolean r_shadow_shadowmapvsdct;
4754 extern qboolean r_shadow_shadowmapsampler;
4755 extern int r_shadow_shadowmappcf;
4756 extern rtexture_t *r_shadow_shadowmap2dtexture;
4757 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4758 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4759 extern matrix4x4_t r_shadow_shadowmapmatrix;
4760 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4761 extern int r_shadow_prepass_width;
4762 extern int r_shadow_prepass_height;
4763 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4764 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4765 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4766 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4767 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4768 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4769 {
4770         // a blendfunc allows colormod if:
4771         // a) it can never keep the destination pixel invariant, or
4772         // b) it can keep the destination pixel invariant, and still can do so if colormodded
4773         // this is to prevent unintended side effects from colormod
4774
4775         // in formulas:
4776         // IF there is a (s, sa) for which for all (d, da),
4777         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4778         // THEN, for this (s, sa) and all (colormod, d, da):
4779         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4780         // OBVIOUSLY, this means that
4781         //   s*colormod * src(s*colormod, d, sa, da) = 0
4782         //   dst(s*colormod, d, sa, da)              = 1
4783
4784         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4785
4786         // main condition to leave dst color invariant:
4787         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4788         //   src == GL_ZERO:
4789         //     s * 0 + d * dst(s, d, sa, da) == d
4790         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4791         //       => colormod is a problem for GL_SRC_COLOR only
4792         //   src == GL_ONE:
4793         //     s + d * dst(s, d, sa, da) == d
4794         //       => s == 0
4795         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4796         //       => colormod is never problematic for these
4797         //   src == GL_SRC_COLOR:
4798         //     s*s + d * dst(s, d, sa, da) == d
4799         //       => s == 0
4800         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4801         //       => colormod is never problematic for these
4802         //   src == GL_ONE_MINUS_SRC_COLOR:
4803         //     s*(1-s) + d * dst(s, d, sa, da) == d
4804         //       => s == 0 or s == 1
4805         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4806         //       => colormod is a problem for GL_SRC_COLOR only
4807         //   src == GL_DST_COLOR
4808         //     s*d + d * dst(s, d, sa, da) == d
4809         //       => s == 1
4810         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4811         //       => colormod is always a problem
4812         //     or
4813         //       => s == 0
4814         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4815         //       => colormod is never problematic for these
4816         //       => BUT, we do not know s! We must assume it is problematic
4817         //       then... except in GL_ONE case, where we know all invariant
4818         //       cases are fine
4819         //   src == GL_ONE_MINUS_DST_COLOR
4820         //     s*(1-d) + d * dst(s, d, sa, da) == d
4821         //       => s == 0 (1-d is impossible to handle for our desired result)
4822         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4823         //       => colormod is never problematic for these
4824         //   src == GL_SRC_ALPHA
4825         //     s*sa + d * dst(s, d, sa, da) == d
4826         //       => s == 0, or sa == 0
4827         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4828         //       => colormod breaks in the case GL_SRC_COLOR only
4829         //   src == GL_ONE_MINUS_SRC_ALPHA
4830         //     s*(1-sa) + d * dst(s, d, sa, da) == d
4831         //       => s == 0, or sa == 1
4832         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4833         //       => colormod breaks in the case GL_SRC_COLOR only
4834         //   src == GL_DST_ALPHA
4835         //     s*da + d * dst(s, d, sa, da) == d
4836         //       => s == 0
4837         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4838         //       => colormod is never problematic for these
4839
4840         switch(src)
4841         {
4842                 case GL_ZERO:
4843                 case GL_ONE_MINUS_SRC_COLOR:
4844                 case GL_SRC_ALPHA:
4845                 case GL_ONE_MINUS_SRC_ALPHA:
4846                         if(dst == GL_SRC_COLOR)
4847                                 return false;
4848                         return true;
4849                 case GL_ONE:
4850                 case GL_SRC_COLOR:
4851                 case GL_ONE_MINUS_DST_COLOR:
4852                 case GL_DST_ALPHA:
4853                 case GL_ONE_MINUS_DST_ALPHA:
4854                         return true;
4855                 case GL_DST_COLOR:
4856                         if(dst == GL_ONE)
4857                                 return true;
4858                         return false;
4859                 default:
4860                         return false;
4861         }
4862 }
4863 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)
4864 {
4865         // select a permutation of the lighting shader appropriate to this
4866         // combination of texture, entity, light source, and fogging, only use the
4867         // minimum features necessary to avoid wasting rendering time in the
4868         // fragment shader on features that are not being used
4869         unsigned int permutation = 0;
4870         unsigned int mode = 0;
4871         qboolean allow_colormod;
4872         static float dummy_colormod[3] = {1, 1, 1};
4873         float *colormod = rsurface.colormod;
4874         float m16f[16];
4875         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4876         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4877                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4878         if (rsurfacepass == RSURFPASS_BACKGROUND)
4879         {
4880                 // distorted background
4881                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4882                 {
4883                         mode = SHADERMODE_WATER;
4884                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4885                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4886                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4887                         {
4888                                 // this is the right thing to do for wateralpha
4889                                 GL_BlendFunc(GL_ONE, GL_ZERO);
4890                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4891                         }
4892                         else
4893                         {
4894                                 // this is the right thing to do for entity alpha
4895                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4896                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4897                         }
4898                 }
4899                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4900                 {
4901                         mode = SHADERMODE_REFRACTION;
4902                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4903                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4904                 }
4905                 else
4906                 {
4907                         mode = SHADERMODE_GENERIC;
4908                         permutation |= SHADERPERMUTATION_DIFFUSE;
4909                         GL_BlendFunc(GL_ONE, GL_ZERO);
4910                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4911                 }
4912         }
4913         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4914         {
4915                 if (r_glsl_offsetmapping.integer)
4916                 {
4917                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4918                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4919                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4920                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4921                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4922                         {
4923                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4924                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4925                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4926                         }
4927                 }
4928                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4929                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4930                 // normalmap (deferred prepass), may use alpha test on diffuse
4931                 mode = SHADERMODE_DEFERREDGEOMETRY;
4932                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4933                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4934                 GL_BlendFunc(GL_ONE, GL_ZERO);
4935                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4936         }
4937         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4938         {
4939                 if (r_glsl_offsetmapping.integer)
4940                 {
4941                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4942                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4943                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4944                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4945                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4946                         {
4947                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4948                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4949                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4950                         }
4951                 }
4952                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4953                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4954                 // light source
4955                 mode = SHADERMODE_LIGHTSOURCE;
4956                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4957                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4958                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4959                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4960                 if (diffusescale > 0)
4961                         permutation |= SHADERPERMUTATION_DIFFUSE;
4962                 if (specularscale > 0)
4963                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4964                 if (r_refdef.fogenabled)
4965                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4966                 if (rsurface.texture->colormapping)
4967                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4968                 if (r_shadow_usingshadowmap2d)
4969                 {
4970                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4971                         if(r_shadow_shadowmapvsdct)
4972                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4973
4974                         if (r_shadow_shadowmapsampler)
4975                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4976                         if (r_shadow_shadowmappcf > 1)
4977                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4978                         else if (r_shadow_shadowmappcf)
4979                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4980                 }
4981                 if (rsurface.texture->reflectmasktexture)
4982                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4983                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4984                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4985         }
4986         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4987         {
4988                 if (r_glsl_offsetmapping.integer)
4989                 {
4990                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4991                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4992                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4993                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4994                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4995                         {
4996                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4997                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4998                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4999                         }
5000                 }
5001                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5002                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5003                 // unshaded geometry (fullbright or ambient model lighting)
5004                 mode = SHADERMODE_FLATCOLOR;
5005                 ambientscale = diffusescale = specularscale = 0;
5006                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5007                         permutation |= SHADERPERMUTATION_GLOW;
5008                 if (r_refdef.fogenabled)
5009                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5010                 if (rsurface.texture->colormapping)
5011                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5012                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5013                 {
5014                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5015                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5016
5017                         if (r_shadow_shadowmapsampler)
5018                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5019                         if (r_shadow_shadowmappcf > 1)
5020                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5021                         else if (r_shadow_shadowmappcf)
5022                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5023                 }
5024                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5025                         permutation |= SHADERPERMUTATION_REFLECTION;
5026                 if (rsurface.texture->reflectmasktexture)
5027                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5028                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5029                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5030         }
5031         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5032         {
5033                 if (r_glsl_offsetmapping.integer)
5034                 {
5035                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5036                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5037                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5038                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5039                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5040                         {
5041                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5042                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5043                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5044                         }
5045                 }
5046                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5047                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5048                 // directional model lighting
5049                 mode = SHADERMODE_LIGHTDIRECTION;
5050                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5051                         permutation |= SHADERPERMUTATION_GLOW;
5052                 permutation |= SHADERPERMUTATION_DIFFUSE;
5053                 if (specularscale > 0)
5054                         permutation |= SHADERPERMUTATION_SPECULAR;
5055                 if (r_refdef.fogenabled)
5056                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5057                 if (rsurface.texture->colormapping)
5058                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5059                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5060                 {
5061                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5062                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5063
5064                         if (r_shadow_shadowmapsampler)
5065                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5066                         if (r_shadow_shadowmappcf > 1)
5067                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5068                         else if (r_shadow_shadowmappcf)
5069                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5070                 }
5071                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5072                         permutation |= SHADERPERMUTATION_REFLECTION;
5073                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5074                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5075                 if (rsurface.texture->reflectmasktexture)
5076                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5077                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5078                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5079         }
5080         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5081         {
5082                 if (r_glsl_offsetmapping.integer)
5083                 {
5084                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5085                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5086                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5087                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5088                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5089                         {
5090                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5091                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5092                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5093                         }
5094                 }
5095                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5096                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5097                 // ambient model lighting
5098                 mode = SHADERMODE_LIGHTDIRECTION;
5099                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5100                         permutation |= SHADERPERMUTATION_GLOW;
5101                 if (r_refdef.fogenabled)
5102                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5103                 if (rsurface.texture->colormapping)
5104                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5105                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5106                 {
5107                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5108                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5109
5110                         if (r_shadow_shadowmapsampler)
5111                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5112                         if (r_shadow_shadowmappcf > 1)
5113                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5114                         else if (r_shadow_shadowmappcf)
5115                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5116                 }
5117                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5118                         permutation |= SHADERPERMUTATION_REFLECTION;
5119                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5120                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5121                 if (rsurface.texture->reflectmasktexture)
5122                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5123                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5124                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5125         }
5126         else
5127         {
5128                 if (r_glsl_offsetmapping.integer)
5129                 {
5130                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5131                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5132                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5133                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5134                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5135                         {
5136                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5137                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5138                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5139                         }
5140                 }
5141                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5142                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5143                 // lightmapped wall
5144                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5145                         permutation |= SHADERPERMUTATION_GLOW;
5146                 if (r_refdef.fogenabled)
5147                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5148                 if (rsurface.texture->colormapping)
5149                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5150                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5151                 {
5152                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5153                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5154
5155                         if (r_shadow_shadowmapsampler)
5156                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5157                         if (r_shadow_shadowmappcf > 1)
5158                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5159                         else if (r_shadow_shadowmappcf)
5160                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5161                 }
5162                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5163                         permutation |= SHADERPERMUTATION_REFLECTION;
5164                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5165                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5166                 if (rsurface.texture->reflectmasktexture)
5167                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5168                 if (FAKELIGHT_ENABLED)
5169                 {
5170                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5171                         mode = SHADERMODE_FAKELIGHT;
5172                         permutation |= SHADERPERMUTATION_DIFFUSE;
5173                         if (specularscale > 0)
5174                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5175                 }
5176                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5177                 {
5178                         // deluxemapping (light direction texture)
5179                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5180                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5181                         else
5182                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5183                         permutation |= SHADERPERMUTATION_DIFFUSE;
5184                         if (specularscale > 0)
5185                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5186                 }
5187                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5188                 {
5189                         // fake deluxemapping (uniform light direction in tangentspace)
5190                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5191                         permutation |= SHADERPERMUTATION_DIFFUSE;
5192                         if (specularscale > 0)
5193                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5194                 }
5195                 else if (rsurface.uselightmaptexture)
5196                 {
5197                         // ordinary lightmapping (q1bsp, q3bsp)
5198                         mode = SHADERMODE_LIGHTMAP;
5199                 }
5200                 else
5201                 {
5202                         // ordinary vertex coloring (q3bsp)
5203                         mode = SHADERMODE_VERTEXCOLOR;
5204                 }
5205                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5206                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5207         }
5208         if(!allow_colormod)
5209                 colormod = dummy_colormod;
5210         switch(vid.renderpath)
5211         {
5212         case RENDERPATH_D3D9:
5213 #ifdef SUPPORTD3D
5214                 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);
5215                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5216                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5217                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5218                 if (mode == SHADERMODE_LIGHTSOURCE)
5219                 {
5220                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5221                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5222                 }
5223                 else
5224                 {
5225                         if (mode == SHADERMODE_LIGHTDIRECTION)
5226                         {
5227                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5228                         }
5229                 }
5230                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5231                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5232                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5233                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5234                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5235
5236                 if (mode == SHADERMODE_LIGHTSOURCE)
5237                 {
5238                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5239                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5240                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5241                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5242                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5243
5244                         // additive passes are only darkened by fog, not tinted
5245                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5246                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5247                 }
5248                 else
5249                 {
5250                         if (mode == SHADERMODE_FLATCOLOR)
5251                         {
5252                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5253                         }
5254                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5255                         {
5256                                 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]);
5257                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5258                                 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);
5259                                 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);
5260                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5261                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5262                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5263                         }
5264                         else
5265                         {
5266                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5267                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5268                                 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);
5269                                 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);
5270                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5271                         }
5272                         // additive passes are only darkened by fog, not tinted
5273                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5274                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5275                         else
5276                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5277                         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);
5278                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5279                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5280                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5281                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5282                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5283                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5284                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5285                         if (mode == SHADERMODE_WATER)
5286                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5287                 }
5288                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5289                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5290                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5291                 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));
5292                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5293                 if (rsurface.texture->pantstexture)
5294                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5295                 else
5296                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5297                 if (rsurface.texture->shirttexture)
5298                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5299                 else
5300                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5301                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5302                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5303                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5304                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5305                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5306                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5307                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5308
5309                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5310                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5311                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5312                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5313                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5314                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5315                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5316                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5317                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5318                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5319                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5320                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5321                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5322                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5323                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5324                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5325                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5326                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5327                 {
5328                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5329                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5330                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5331                 }
5332                 else
5333                 {
5334                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5335                 }
5336 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5337 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5338                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5339                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5340                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5341                 {
5342                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5343                         if (rsurface.rtlight)
5344                         {
5345                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5346                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5347                         }
5348                 }
5349 #endif
5350                 break;
5351         case RENDERPATH_D3D10:
5352                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5353                 break;
5354         case RENDERPATH_D3D11:
5355                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5356                 break;
5357         case RENDERPATH_GL20:
5358         case RENDERPATH_GLES2:
5359                 if (!vid.useinterleavedarrays)
5360                 {
5361                         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);
5362                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5363                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5364                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5365                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5366                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5367                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5368                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5369                 }
5370                 else
5371                 {
5372                         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);
5373                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5374                 }
5375                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5376                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5377                 if (mode == SHADERMODE_LIGHTSOURCE)
5378                 {
5379                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5380                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5381                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5382                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5383                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5384                         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);
5385         
5386                         // additive passes are only darkened by fog, not tinted
5387                         if (r_glsl_permutation->loc_FogColor >= 0)
5388                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5389                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5390                 }
5391                 else
5392                 {
5393                         if (mode == SHADERMODE_FLATCOLOR)
5394                         {
5395                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5396                         }
5397                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5398                         {
5399                                 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]);
5400                                 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]);
5401                                 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);
5402                                 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);
5403                                 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);
5404                                 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]);
5405                                 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]);
5406                         }
5407                         else
5408                         {
5409                                 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]);
5410                                 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]);
5411                                 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);
5412                                 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);
5413                                 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);
5414                         }
5415                         // additive passes are only darkened by fog, not tinted
5416                         if (r_glsl_permutation->loc_FogColor >= 0)
5417                         {
5418                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5419                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5420                                 else
5421                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5422                         }
5423                         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);
5424                         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]);
5425                         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]);
5426                         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]);
5427                         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]);
5428                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5429                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5430                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5431                         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]);
5432                 }
5433                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5434                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5435                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5436                 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]);
5437                 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]);
5438
5439                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5440                 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));
5441                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5442                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5443                 {
5444                         if (rsurface.texture->pantstexture)
5445                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5446                         else
5447                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5448                 }
5449                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5450                 {
5451                         if (rsurface.texture->shirttexture)
5452                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5453                         else
5454                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5455                 }
5456                 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]);
5457                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5458                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5459                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5460                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5461                 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]);
5462                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5463
5464                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
5465                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
5466                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
5467                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
5468                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
5469                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
5470                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
5471                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
5472                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
5473                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
5474                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
5475                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
5476                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
5477                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
5478                 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);
5479                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
5480                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
5481                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5482                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5483                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
5484                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5485                 {
5486                         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);
5487                         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);
5488                         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);
5489                 }
5490                 else
5491                 {
5492                         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);
5493                 }
5494                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
5495                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
5496                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
5497                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
5498                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5499                 {
5500                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
5501                         if (rsurface.rtlight)
5502                         {
5503                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
5504                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
5505                         }
5506                 }
5507                 CHECKGLERROR
5508                 break;
5509         case RENDERPATH_GL13:
5510         case RENDERPATH_GL11:
5511                 break;
5512         case RENDERPATH_SOFT:
5513                 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);
5514                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5515                 R_SetupShader_SetPermutationSoft(mode, permutation);
5516                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5517                 if (mode == SHADERMODE_LIGHTSOURCE)
5518                 {
5519                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5520                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5521                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5522                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5523                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5524                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5525         
5526                         // additive passes are only darkened by fog, not tinted
5527                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5528                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5529                 }
5530                 else
5531                 {
5532                         if (mode == SHADERMODE_FLATCOLOR)
5533                         {
5534                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5535                         }
5536                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5537                         {
5538                                 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]);
5539                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5540                                 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);
5541                                 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);
5542                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5543                                 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]);
5544                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5545                         }
5546                         else
5547                         {
5548                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5549                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5550                                 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);
5551                                 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);
5552                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5553                         }
5554                         // additive passes are only darkened by fog, not tinted
5555                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5556                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5557                         else
5558                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5559                         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);
5560                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5561                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5562                         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]);
5563                         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]);
5564                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5565                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5566                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5567                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5568                 }
5569                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5570                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5571                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5572                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5573                 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]);
5574
5575                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5576                 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));
5577                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5578                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5579                 {
5580                         if (rsurface.texture->pantstexture)
5581                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5582                         else
5583                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5584                 }
5585                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5586                 {
5587                         if (rsurface.texture->shirttexture)
5588                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5589                         else
5590                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5591                 }
5592                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5593                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5594                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5595                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5596                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5597                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5598                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5599
5600                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5601                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5602                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5603                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5604                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5605                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5606                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5607                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5608                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5609                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5610                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5611                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5612                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5613                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5614                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5615                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5616                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5617                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5618                 {
5619                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5620                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5621                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5622                 }
5623                 else
5624                 {
5625                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5626                 }
5627 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5628 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5629                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5630                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5631                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5632                 {
5633                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5634                         if (rsurface.rtlight)
5635                         {
5636                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5637                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5638                         }
5639                 }
5640                 break;
5641         }
5642 }
5643
5644 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5645 {
5646         // select a permutation of the lighting shader appropriate to this
5647         // combination of texture, entity, light source, and fogging, only use the
5648         // minimum features necessary to avoid wasting rendering time in the
5649         // fragment shader on features that are not being used
5650         unsigned int permutation = 0;
5651         unsigned int mode = 0;
5652         const float *lightcolorbase = rtlight->currentcolor;
5653         float ambientscale = rtlight->ambientscale;
5654         float diffusescale = rtlight->diffusescale;
5655         float specularscale = rtlight->specularscale;
5656         // this is the location of the light in view space
5657         vec3_t viewlightorigin;
5658         // this transforms from view space (camera) to light space (cubemap)
5659         matrix4x4_t viewtolight;
5660         matrix4x4_t lighttoview;
5661         float viewtolight16f[16];
5662         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5663         // light source
5664         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5665         if (rtlight->currentcubemap != r_texture_whitecube)
5666                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5667         if (diffusescale > 0)
5668                 permutation |= SHADERPERMUTATION_DIFFUSE;
5669         if (specularscale > 0)
5670                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5671         if (r_shadow_usingshadowmap2d)
5672         {
5673                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5674                 if (r_shadow_shadowmapvsdct)
5675                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5676
5677                 if (r_shadow_shadowmapsampler)
5678                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5679                 if (r_shadow_shadowmappcf > 1)
5680                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5681                 else if (r_shadow_shadowmappcf)
5682                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5683         }
5684         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5685         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5686         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5687         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5688         switch(vid.renderpath)
5689         {
5690         case RENDERPATH_D3D9:
5691 #ifdef SUPPORTD3D
5692                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5693                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5694                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5695                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5696                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5697                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5698                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5699                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5700                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5701                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5702                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5703
5704                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5705                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
5706                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5707                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5708                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
5709                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5710 #endif
5711                 break;
5712         case RENDERPATH_D3D10:
5713                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5714                 break;
5715         case RENDERPATH_D3D11:
5716                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5717                 break;
5718         case RENDERPATH_GL20:
5719         case RENDERPATH_GLES2:
5720                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5721                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5722                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5723                 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);
5724                 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);
5725                 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);
5726                 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]);
5727                 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]);
5728                 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));
5729                 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]);
5730                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
5731
5732                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
5733                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
5734                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
5735                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
5736                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
5737                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
5738                 break;
5739         case RENDERPATH_GL13:
5740         case RENDERPATH_GL11:
5741                 break;
5742         case RENDERPATH_SOFT:
5743                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5744                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5745                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
5746                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5747                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5748                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5749                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5750                 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]);
5751                 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));
5752                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5753                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5754
5755                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5756                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5757                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5758                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5759                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5760                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5761                 break;
5762         }
5763 }
5764
5765 void R_SetupShader_DeferredBounceLight(void)
5766 {
5767         // array of particle lights that contribute only ambient color
5768         unsigned int permutation = 0;
5769         unsigned int mode = 0;
5770         mode = SHADERMODE_DEFERREDBOUNCELIGHT;
5771         switch(vid.renderpath)
5772         {
5773         case RENDERPATH_D3D9:
5774 #ifdef SUPPORTD3D
5775                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5776                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5777                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5778
5779                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
5780 #endif
5781                 break;
5782         case RENDERPATH_D3D10:
5783                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5784                 break;
5785         case RENDERPATH_D3D11:
5786                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5787                 break;
5788         case RENDERPATH_GL20:
5789         case RENDERPATH_GLES2:
5790                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5791                 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]);
5792                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
5793
5794                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
5795                 break;
5796         case RENDERPATH_GL13:
5797         case RENDERPATH_GL11:
5798                 break;
5799         case RENDERPATH_SOFT:
5800                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5801                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5802                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5803
5804                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5805                 break;
5806         }
5807 }
5808
5809 #define SKINFRAME_HASH 1024
5810
5811 typedef struct
5812 {
5813         int loadsequence; // incremented each level change
5814         memexpandablearray_t array;
5815         skinframe_t *hash[SKINFRAME_HASH];
5816 }
5817 r_skinframe_t;
5818 r_skinframe_t r_skinframe;
5819
5820 void R_SkinFrame_PrepareForPurge(void)
5821 {
5822         r_skinframe.loadsequence++;
5823         // wrap it without hitting zero
5824         if (r_skinframe.loadsequence >= 200)
5825                 r_skinframe.loadsequence = 1;
5826 }
5827
5828 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5829 {
5830         if (!skinframe)
5831                 return;
5832         // mark the skinframe as used for the purging code
5833         skinframe->loadsequence = r_skinframe.loadsequence;
5834 }
5835
5836 void R_SkinFrame_Purge(void)
5837 {
5838         int i;
5839         skinframe_t *s;
5840         for (i = 0;i < SKINFRAME_HASH;i++)
5841         {
5842                 for (s = r_skinframe.hash[i];s;s = s->next)
5843                 {
5844                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5845                         {
5846                                 if (s->merged == s->base)
5847                                         s->merged = NULL;
5848                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5849                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5850                                 R_PurgeTexture(s->merged);s->merged = NULL;
5851                                 R_PurgeTexture(s->base  );s->base   = NULL;
5852                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5853                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5854                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5855                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5856                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5857                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5858                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5859                                 s->loadsequence = 0;
5860                         }
5861                 }
5862         }
5863 }
5864
5865 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5866         skinframe_t *item;
5867         char basename[MAX_QPATH];
5868
5869         Image_StripImageExtension(name, basename, sizeof(basename));
5870
5871         if( last == NULL ) {
5872                 int hashindex;
5873                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5874                 item = r_skinframe.hash[hashindex];
5875         } else {
5876                 item = last->next;
5877         }
5878
5879         // linearly search through the hash bucket
5880         for( ; item ; item = item->next ) {
5881                 if( !strcmp( item->basename, basename ) ) {
5882                         return item;
5883                 }
5884         }
5885         return NULL;
5886 }
5887
5888 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5889 {
5890         skinframe_t *item;
5891         int hashindex;
5892         char basename[MAX_QPATH];
5893
5894         Image_StripImageExtension(name, basename, sizeof(basename));
5895
5896         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5897         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5898                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5899                         break;
5900
5901         if (!item) {
5902                 rtexture_t *dyntexture;
5903                 // check whether its a dynamic texture
5904                 dyntexture = CL_GetDynTexture( basename );
5905                 if (!add && !dyntexture)
5906                         return NULL;
5907                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5908                 memset(item, 0, sizeof(*item));
5909                 strlcpy(item->basename, basename, sizeof(item->basename));
5910                 item->base = dyntexture; // either NULL or dyntexture handle
5911                 item->textureflags = textureflags;
5912                 item->comparewidth = comparewidth;
5913                 item->compareheight = compareheight;
5914                 item->comparecrc = comparecrc;
5915                 item->next = r_skinframe.hash[hashindex];
5916                 r_skinframe.hash[hashindex] = item;
5917         }
5918         else if( item->base == NULL )
5919         {
5920                 rtexture_t *dyntexture;
5921                 // check whether its a dynamic texture
5922                 // 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]
5923                 dyntexture = CL_GetDynTexture( basename );
5924                 item->base = dyntexture; // either NULL or dyntexture handle
5925         }
5926
5927         R_SkinFrame_MarkUsed(item);
5928         return item;
5929 }
5930
5931 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5932         { \
5933                 unsigned long long avgcolor[5], wsum; \
5934                 int pix, comp, w; \
5935                 avgcolor[0] = 0; \
5936                 avgcolor[1] = 0; \
5937                 avgcolor[2] = 0; \
5938                 avgcolor[3] = 0; \
5939                 avgcolor[4] = 0; \
5940                 wsum = 0; \
5941                 for(pix = 0; pix < cnt; ++pix) \
5942                 { \
5943                         w = 0; \
5944                         for(comp = 0; comp < 3; ++comp) \
5945                                 w += getpixel; \
5946                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5947                         { \
5948                                 ++wsum; \
5949                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5950                                 w = getpixel; \
5951                                 for(comp = 0; comp < 3; ++comp) \
5952                                         avgcolor[comp] += getpixel * w; \
5953                                 avgcolor[3] += w; \
5954                         } \
5955                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5956                         avgcolor[4] += getpixel; \
5957                 } \
5958                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5959                         avgcolor[3] = 1; \
5960                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5961                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5962                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5963                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5964         }
5965
5966 extern cvar_t gl_picmip;
5967 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5968 {
5969         int j;
5970         unsigned char *pixels;
5971         unsigned char *bumppixels;
5972         unsigned char *basepixels = NULL;
5973         int basepixels_width = 0;
5974         int basepixels_height = 0;
5975         skinframe_t *skinframe;
5976         rtexture_t *ddsbase = NULL;
5977         qboolean ddshasalpha = false;
5978         float ddsavgcolor[4];
5979         char basename[MAX_QPATH];
5980         int miplevel = R_PicmipForFlags(textureflags);
5981         int savemiplevel = miplevel;
5982         int mymiplevel;
5983
5984         if (cls.state == ca_dedicated)
5985                 return NULL;
5986
5987         // return an existing skinframe if already loaded
5988         // if loading of the first image fails, don't make a new skinframe as it
5989         // would cause all future lookups of this to be missing
5990         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5991         if (skinframe && skinframe->base)
5992                 return skinframe;
5993
5994         Image_StripImageExtension(name, basename, sizeof(basename));
5995
5996         // check for DDS texture file first
5997         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5998         {
5999                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6000                 if (basepixels == NULL)
6001                         return NULL;
6002         }
6003
6004         // FIXME handle miplevel
6005
6006         if (developer_loading.integer)
6007                 Con_Printf("loading skin \"%s\"\n", name);
6008
6009         // we've got some pixels to store, so really allocate this new texture now
6010         if (!skinframe)
6011                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6012         skinframe->stain = NULL;
6013         skinframe->merged = NULL;
6014         skinframe->base = NULL;
6015         skinframe->pants = NULL;
6016         skinframe->shirt = NULL;
6017         skinframe->nmap = NULL;
6018         skinframe->gloss = NULL;
6019         skinframe->glow = NULL;
6020         skinframe->fog = NULL;
6021         skinframe->reflect = NULL;
6022         skinframe->hasalpha = false;
6023
6024         if (ddsbase)
6025         {
6026                 skinframe->base = ddsbase;
6027                 skinframe->hasalpha = ddshasalpha;
6028                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6029                 if (r_loadfog && skinframe->hasalpha)
6030                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6031                 //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]);
6032         }
6033         else
6034         {
6035                 basepixels_width = image_width;
6036                 basepixels_height = image_height;
6037                 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);
6038                 if (textureflags & TEXF_ALPHA)
6039                 {
6040                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6041                         {
6042                                 if (basepixels[j] < 255)
6043                                 {
6044                                         skinframe->hasalpha = true;
6045                                         break;
6046                                 }
6047                         }
6048                         if (r_loadfog && skinframe->hasalpha)
6049                         {
6050                                 // has transparent pixels
6051                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6052                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6053                                 {
6054                                         pixels[j+0] = 255;
6055                                         pixels[j+1] = 255;
6056                                         pixels[j+2] = 255;
6057                                         pixels[j+3] = basepixels[j+3];
6058                                 }
6059                                 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);
6060                                 Mem_Free(pixels);
6061                         }
6062                 }
6063                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6064                 //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]);
6065                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6066                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6067                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6068                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6069         }
6070
6071         if (r_loaddds)
6072         {
6073                 mymiplevel = savemiplevel;
6074                 if (r_loadnormalmap)
6075                         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);
6076                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6077                 if (r_loadgloss)
6078                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6079                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6080                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6081                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6082         }
6083
6084         // _norm is the name used by tenebrae and has been adopted as standard
6085         if (r_loadnormalmap && skinframe->nmap == NULL)
6086         {
6087                 mymiplevel = savemiplevel;
6088                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6089                 {
6090                         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);
6091                         Mem_Free(pixels);
6092                         pixels = NULL;
6093                 }
6094                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6095                 {
6096                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6097                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6098                         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);
6099                         Mem_Free(pixels);
6100                         Mem_Free(bumppixels);
6101                 }
6102                 else if (r_shadow_bumpscale_basetexture.value > 0)
6103                 {
6104                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6105                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6106                         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);
6107                         Mem_Free(pixels);
6108                 }
6109                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6110                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6111         }
6112
6113         // _luma is supported only for tenebrae compatibility
6114         // _glow is the preferred name
6115         mymiplevel = savemiplevel;
6116         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))))
6117         {
6118                 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);
6119                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6120                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6121                 Mem_Free(pixels);pixels = NULL;
6122         }
6123
6124         mymiplevel = savemiplevel;
6125         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6126         {
6127                 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);
6128                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6129                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6130                 Mem_Free(pixels);
6131                 pixels = NULL;
6132         }
6133
6134         mymiplevel = savemiplevel;
6135         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6136         {
6137                 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);
6138                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6139                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6140                 Mem_Free(pixels);
6141                 pixels = NULL;
6142         }
6143
6144         mymiplevel = savemiplevel;
6145         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6146         {
6147                 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);
6148                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6149                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6150                 Mem_Free(pixels);
6151                 pixels = NULL;
6152         }
6153
6154         mymiplevel = savemiplevel;
6155         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6156         {
6157                 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);
6158                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6159                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6160                 Mem_Free(pixels);
6161                 pixels = NULL;
6162         }
6163
6164         if (basepixels)
6165                 Mem_Free(basepixels);
6166
6167         return skinframe;
6168 }
6169
6170 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6171 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6172 {
6173         int i;
6174         unsigned char *temp1, *temp2;
6175         skinframe_t *skinframe;
6176
6177         if (cls.state == ca_dedicated)
6178                 return NULL;
6179
6180         // if already loaded just return it, otherwise make a new skinframe
6181         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6182         if (skinframe && skinframe->base)
6183                 return skinframe;
6184
6185         skinframe->stain = NULL;
6186         skinframe->merged = NULL;
6187         skinframe->base = NULL;
6188         skinframe->pants = NULL;
6189         skinframe->shirt = NULL;
6190         skinframe->nmap = NULL;
6191         skinframe->gloss = NULL;
6192         skinframe->glow = NULL;
6193         skinframe->fog = NULL;
6194         skinframe->reflect = NULL;
6195         skinframe->hasalpha = false;
6196
6197         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6198         if (!skindata)
6199                 return NULL;
6200
6201         if (developer_loading.integer)
6202                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6203
6204         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6205         {
6206                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6207                 temp2 = temp1 + width * height * 4;
6208                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6209                 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);
6210                 Mem_Free(temp1);
6211         }
6212         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6213         if (textureflags & TEXF_ALPHA)
6214         {
6215                 for (i = 3;i < width * height * 4;i += 4)
6216                 {
6217                         if (skindata[i] < 255)
6218                         {
6219                                 skinframe->hasalpha = true;
6220                                 break;
6221                         }
6222                 }
6223                 if (r_loadfog && skinframe->hasalpha)
6224                 {
6225                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6226                         memcpy(fogpixels, skindata, width * height * 4);
6227                         for (i = 0;i < width * height * 4;i += 4)
6228                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6229                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6230                         Mem_Free(fogpixels);
6231                 }
6232         }
6233
6234         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6235         //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]);
6236
6237         return skinframe;
6238 }
6239
6240 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6241 {
6242         int i;
6243         int featuresmask;
6244         skinframe_t *skinframe;
6245
6246         if (cls.state == ca_dedicated)
6247                 return NULL;
6248
6249         // if already loaded just return it, otherwise make a new skinframe
6250         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6251         if (skinframe && skinframe->base)
6252                 return skinframe;
6253
6254         skinframe->stain = NULL;
6255         skinframe->merged = NULL;
6256         skinframe->base = NULL;
6257         skinframe->pants = NULL;
6258         skinframe->shirt = NULL;
6259         skinframe->nmap = NULL;
6260         skinframe->gloss = NULL;
6261         skinframe->glow = NULL;
6262         skinframe->fog = NULL;
6263         skinframe->reflect = NULL;
6264         skinframe->hasalpha = false;
6265
6266         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6267         if (!skindata)
6268                 return NULL;
6269
6270         if (developer_loading.integer)
6271                 Con_Printf("loading quake skin \"%s\"\n", name);
6272
6273         // 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)
6274         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6275         memcpy(skinframe->qpixels, skindata, width*height);
6276         skinframe->qwidth = width;
6277         skinframe->qheight = height;
6278
6279         featuresmask = 0;
6280         for (i = 0;i < width * height;i++)
6281                 featuresmask |= palette_featureflags[skindata[i]];
6282
6283         skinframe->hasalpha = false;
6284         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6285         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6286         skinframe->qgeneratemerged = true;
6287         skinframe->qgeneratebase = skinframe->qhascolormapping;
6288         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6289
6290         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6291         //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]);
6292
6293         return skinframe;
6294 }
6295
6296 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6297 {
6298         int width;
6299         int height;
6300         unsigned char *skindata;
6301
6302         if (!skinframe->qpixels)
6303                 return;
6304
6305         if (!skinframe->qhascolormapping)
6306                 colormapped = false;
6307
6308         if (colormapped)
6309         {
6310                 if (!skinframe->qgeneratebase)
6311                         return;
6312         }
6313         else
6314         {
6315                 if (!skinframe->qgeneratemerged)
6316                         return;
6317         }
6318
6319         width = skinframe->qwidth;
6320         height = skinframe->qheight;
6321         skindata = skinframe->qpixels;
6322
6323         if (skinframe->qgeneratenmap)
6324         {
6325                 unsigned char *temp1, *temp2;
6326                 skinframe->qgeneratenmap = false;
6327                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6328                 temp2 = temp1 + width * height * 4;
6329                 // use either a custom palette or the quake palette
6330                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6331                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6332                 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);
6333                 Mem_Free(temp1);
6334         }
6335
6336         if (skinframe->qgenerateglow)
6337         {
6338                 skinframe->qgenerateglow = false;
6339                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6340         }
6341
6342         if (colormapped)
6343         {
6344                 skinframe->qgeneratebase = false;
6345                 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);
6346                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6347                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6348         }
6349         else
6350         {
6351                 skinframe->qgeneratemerged = false;
6352                 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);
6353         }
6354
6355         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6356         {
6357                 Mem_Free(skinframe->qpixels);
6358                 skinframe->qpixels = NULL;
6359         }
6360 }
6361
6362 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)
6363 {
6364         int i;
6365         skinframe_t *skinframe;
6366
6367         if (cls.state == ca_dedicated)
6368                 return NULL;
6369
6370         // if already loaded just return it, otherwise make a new skinframe
6371         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6372         if (skinframe && skinframe->base)
6373                 return skinframe;
6374
6375         skinframe->stain = NULL;
6376         skinframe->merged = NULL;
6377         skinframe->base = NULL;
6378         skinframe->pants = NULL;
6379         skinframe->shirt = NULL;
6380         skinframe->nmap = NULL;
6381         skinframe->gloss = NULL;
6382         skinframe->glow = NULL;
6383         skinframe->fog = NULL;
6384         skinframe->reflect = NULL;
6385         skinframe->hasalpha = false;
6386
6387         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6388         if (!skindata)
6389                 return NULL;
6390
6391         if (developer_loading.integer)
6392                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6393
6394         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6395         if (textureflags & TEXF_ALPHA)
6396         {
6397                 for (i = 0;i < width * height;i++)
6398                 {
6399                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6400                         {
6401                                 skinframe->hasalpha = true;
6402                                 break;
6403                         }
6404                 }
6405                 if (r_loadfog && skinframe->hasalpha)
6406                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6407         }
6408
6409         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6410         //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]);
6411
6412         return skinframe;
6413 }
6414
6415 skinframe_t *R_SkinFrame_LoadMissing(void)
6416 {
6417         skinframe_t *skinframe;
6418
6419         if (cls.state == ca_dedicated)
6420                 return NULL;
6421
6422         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6423         skinframe->stain = NULL;
6424         skinframe->merged = NULL;
6425         skinframe->base = NULL;
6426         skinframe->pants = NULL;
6427         skinframe->shirt = NULL;
6428         skinframe->nmap = NULL;
6429         skinframe->gloss = NULL;
6430         skinframe->glow = NULL;
6431         skinframe->fog = NULL;
6432         skinframe->reflect = NULL;
6433         skinframe->hasalpha = false;
6434
6435         skinframe->avgcolor[0] = rand() / RAND_MAX;
6436         skinframe->avgcolor[1] = rand() / RAND_MAX;
6437         skinframe->avgcolor[2] = rand() / RAND_MAX;
6438         skinframe->avgcolor[3] = 1;
6439
6440         return skinframe;
6441 }
6442
6443 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6444 typedef struct suffixinfo_s
6445 {
6446         const char *suffix;
6447         qboolean flipx, flipy, flipdiagonal;
6448 }
6449 suffixinfo_t;
6450 static suffixinfo_t suffix[3][6] =
6451 {
6452         {
6453                 {"px",   false, false, false},
6454                 {"nx",   false, false, false},
6455                 {"py",   false, false, false},
6456                 {"ny",   false, false, false},
6457                 {"pz",   false, false, false},
6458                 {"nz",   false, false, false}
6459         },
6460         {
6461                 {"posx", false, false, false},
6462                 {"negx", false, false, false},
6463                 {"posy", false, false, false},
6464                 {"negy", false, false, false},
6465                 {"posz", false, false, false},
6466                 {"negz", false, false, false}
6467         },
6468         {
6469                 {"rt",    true, false,  true},
6470                 {"lf",   false,  true,  true},
6471                 {"ft",    true,  true, false},
6472                 {"bk",   false, false, false},
6473                 {"up",    true, false,  true},
6474                 {"dn",    true, false,  true}
6475         }
6476 };
6477
6478 static int componentorder[4] = {0, 1, 2, 3};
6479
6480 rtexture_t *R_LoadCubemap(const char *basename)
6481 {
6482         int i, j, cubemapsize;
6483         unsigned char *cubemappixels, *image_buffer;
6484         rtexture_t *cubemaptexture;
6485         char name[256];
6486         // must start 0 so the first loadimagepixels has no requested width/height
6487         cubemapsize = 0;
6488         cubemappixels = NULL;
6489         cubemaptexture = NULL;
6490         // keep trying different suffix groups (posx, px, rt) until one loads
6491         for (j = 0;j < 3 && !cubemappixels;j++)
6492         {
6493                 // load the 6 images in the suffix group
6494                 for (i = 0;i < 6;i++)
6495                 {
6496                         // generate an image name based on the base and and suffix
6497                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6498                         // load it
6499                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6500                         {
6501                                 // an image loaded, make sure width and height are equal
6502                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6503                                 {
6504                                         // if this is the first image to load successfully, allocate the cubemap memory
6505                                         if (!cubemappixels && image_width >= 1)
6506                                         {
6507                                                 cubemapsize = image_width;
6508                                                 // note this clears to black, so unavailable sides are black
6509                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6510                                         }
6511                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6512                                         if (cubemappixels)
6513                                                 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);
6514                                 }
6515                                 else
6516                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6517                                 // free the image
6518                                 Mem_Free(image_buffer);
6519                         }
6520                 }
6521         }
6522         // if a cubemap loaded, upload it
6523         if (cubemappixels)
6524         {
6525                 if (developer_loading.integer)
6526                         Con_Printf("loading cubemap \"%s\"\n", basename);
6527
6528                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6529                 Mem_Free(cubemappixels);
6530         }
6531         else
6532         {
6533                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6534                 if (developer_loading.integer)
6535                 {
6536                         Con_Printf("(tried tried images ");
6537                         for (j = 0;j < 3;j++)
6538                                 for (i = 0;i < 6;i++)
6539                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6540                         Con_Print(" and was unable to find any of them).\n");
6541                 }
6542         }
6543         return cubemaptexture;
6544 }
6545
6546 rtexture_t *R_GetCubemap(const char *basename)
6547 {
6548         int i;
6549         for (i = 0;i < r_texture_numcubemaps;i++)
6550                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6551                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6552         if (i >= MAX_CUBEMAPS)
6553                 return r_texture_whitecube;
6554         r_texture_numcubemaps++;
6555         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6556         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6557         return r_texture_cubemaps[i].texture;
6558 }
6559
6560 void R_FreeCubemaps(void)
6561 {
6562         int i;
6563         for (i = 0;i < r_texture_numcubemaps;i++)
6564         {
6565                 if (developer_loading.integer)
6566                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6567                 if (r_texture_cubemaps[i].texture)
6568                         R_FreeTexture(r_texture_cubemaps[i].texture);
6569         }
6570         r_texture_numcubemaps = 0;
6571 }
6572
6573 void R_Main_FreeViewCache(void)
6574 {
6575         if (r_refdef.viewcache.entityvisible)
6576                 Mem_Free(r_refdef.viewcache.entityvisible);
6577         if (r_refdef.viewcache.world_pvsbits)
6578                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6579         if (r_refdef.viewcache.world_leafvisible)
6580                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6581         if (r_refdef.viewcache.world_surfacevisible)
6582                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6583         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6584 }
6585
6586 void R_Main_ResizeViewCache(void)
6587 {
6588         int numentities = r_refdef.scene.numentities;
6589         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6590         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6591         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6592         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6593         if (r_refdef.viewcache.maxentities < numentities)
6594         {
6595                 r_refdef.viewcache.maxentities = numentities;
6596                 if (r_refdef.viewcache.entityvisible)
6597                         Mem_Free(r_refdef.viewcache.entityvisible);
6598                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6599         }
6600         if (r_refdef.viewcache.world_numclusters != numclusters)
6601         {
6602                 r_refdef.viewcache.world_numclusters = numclusters;
6603                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6604                 if (r_refdef.viewcache.world_pvsbits)
6605                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6606                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6607         }
6608         if (r_refdef.viewcache.world_numleafs != numleafs)
6609         {
6610                 r_refdef.viewcache.world_numleafs = numleafs;
6611                 if (r_refdef.viewcache.world_leafvisible)
6612                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6613                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6614         }
6615         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6616         {
6617                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6618                 if (r_refdef.viewcache.world_surfacevisible)
6619                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6620                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6621         }
6622 }
6623
6624 extern rtexture_t *loadingscreentexture;
6625 void gl_main_start(void)
6626 {
6627         loadingscreentexture = NULL;
6628         r_texture_blanknormalmap = NULL;
6629         r_texture_white = NULL;
6630         r_texture_grey128 = NULL;
6631         r_texture_black = NULL;
6632         r_texture_whitecube = NULL;
6633         r_texture_normalizationcube = NULL;
6634         r_texture_fogattenuation = NULL;
6635         r_texture_fogheighttexture = NULL;
6636         r_texture_gammaramps = NULL;
6637         r_texture_numcubemaps = 0;
6638
6639         r_loaddds = r_texture_dds_load.integer != 0;
6640         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6641
6642         switch(vid.renderpath)
6643         {
6644         case RENDERPATH_GL20:
6645         case RENDERPATH_D3D9:
6646         case RENDERPATH_D3D10:
6647         case RENDERPATH_D3D11:
6648         case RENDERPATH_SOFT:
6649                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6650                 Cvar_SetValueQuick(&gl_combine, 1);
6651                 Cvar_SetValueQuick(&r_glsl, 1);
6652                 r_loadnormalmap = true;
6653                 r_loadgloss = true;
6654                 r_loadfog = false;
6655                 break;
6656         case RENDERPATH_GL13:
6657                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6658                 Cvar_SetValueQuick(&gl_combine, 1);
6659                 Cvar_SetValueQuick(&r_glsl, 0);
6660                 r_loadnormalmap = false;
6661                 r_loadgloss = false;
6662                 r_loadfog = true;
6663                 break;
6664         case RENDERPATH_GL11:
6665                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6666                 Cvar_SetValueQuick(&gl_combine, 0);
6667                 Cvar_SetValueQuick(&r_glsl, 0);
6668                 r_loadnormalmap = false;
6669                 r_loadgloss = false;
6670                 r_loadfog = true;
6671                 break;
6672         case RENDERPATH_GLES2:
6673                 Cvar_SetValueQuick(&r_textureunits, 1);
6674                 Cvar_SetValueQuick(&gl_combine, 1);
6675                 Cvar_SetValueQuick(&r_glsl, 1);
6676                 r_loadnormalmap = true;
6677                 r_loadgloss = false;
6678                 r_loadfog = false;
6679                 break;
6680         }
6681
6682         R_AnimCache_Free();
6683         R_FrameData_Reset();
6684
6685         r_numqueries = 0;
6686         r_maxqueries = 0;
6687         memset(r_queries, 0, sizeof(r_queries));
6688
6689         r_qwskincache = NULL;
6690         r_qwskincache_size = 0;
6691
6692         // set up r_skinframe loading system for textures
6693         memset(&r_skinframe, 0, sizeof(r_skinframe));
6694         r_skinframe.loadsequence = 1;
6695         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6696
6697         r_main_texturepool = R_AllocTexturePool();
6698         R_BuildBlankTextures();
6699         R_BuildNoTexture();
6700         if (vid.support.arb_texture_cube_map)
6701         {
6702                 R_BuildWhiteCube();
6703                 R_BuildNormalizationCube();
6704         }
6705         r_texture_fogattenuation = NULL;
6706         r_texture_fogheighttexture = NULL;
6707         r_texture_gammaramps = NULL;
6708         //r_texture_fogintensity = NULL;
6709         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6710         memset(&r_waterstate, 0, sizeof(r_waterstate));
6711         r_glsl_permutation = NULL;
6712         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6713         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6714         glslshaderstring = NULL;
6715 #ifdef SUPPORTD3D
6716         r_hlsl_permutation = NULL;
6717         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6718         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6719 #endif
6720         hlslshaderstring = NULL;
6721         memset(&r_svbsp, 0, sizeof (r_svbsp));
6722
6723         r_refdef.fogmasktable_density = 0;
6724 }
6725
6726 void gl_main_shutdown(void)
6727 {
6728         R_AnimCache_Free();
6729         R_FrameData_Reset();
6730
6731         R_Main_FreeViewCache();
6732
6733         switch(vid.renderpath)
6734         {
6735         case RENDERPATH_GL11:
6736         case RENDERPATH_GL13:
6737         case RENDERPATH_GL20:
6738         case RENDERPATH_GLES2:
6739                 if (r_maxqueries)
6740                         qglDeleteQueriesARB(r_maxqueries, r_queries);
6741                 break;
6742         case RENDERPATH_D3D9:
6743                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6744                 break;
6745         case RENDERPATH_D3D10:
6746                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6747                 break;
6748         case RENDERPATH_D3D11:
6749                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6750                 break;
6751         case RENDERPATH_SOFT:
6752                 break;
6753         }
6754
6755         r_numqueries = 0;
6756         r_maxqueries = 0;
6757         memset(r_queries, 0, sizeof(r_queries));
6758
6759         r_qwskincache = NULL;
6760         r_qwskincache_size = 0;
6761
6762         // clear out the r_skinframe state
6763         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6764         memset(&r_skinframe, 0, sizeof(r_skinframe));
6765
6766         if (r_svbsp.nodes)
6767                 Mem_Free(r_svbsp.nodes);
6768         memset(&r_svbsp, 0, sizeof (r_svbsp));
6769         R_FreeTexturePool(&r_main_texturepool);
6770         loadingscreentexture = NULL;
6771         r_texture_blanknormalmap = NULL;
6772         r_texture_white = NULL;
6773         r_texture_grey128 = NULL;
6774         r_texture_black = NULL;
6775         r_texture_whitecube = NULL;
6776         r_texture_normalizationcube = NULL;
6777         r_texture_fogattenuation = NULL;
6778         r_texture_fogheighttexture = NULL;
6779         r_texture_gammaramps = NULL;
6780         r_texture_numcubemaps = 0;
6781         //r_texture_fogintensity = NULL;
6782         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6783         memset(&r_waterstate, 0, sizeof(r_waterstate));
6784         R_GLSL_Restart_f();
6785
6786         r_glsl_permutation = NULL;
6787         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6788         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6789         glslshaderstring = NULL;
6790 #ifdef SUPPORTD3D
6791         r_hlsl_permutation = NULL;
6792         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6793         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6794 #endif
6795         hlslshaderstring = NULL;
6796 }
6797
6798 extern void CL_ParseEntityLump(char *entitystring);
6799 void gl_main_newmap(void)
6800 {
6801         // FIXME: move this code to client
6802         char *entities, entname[MAX_QPATH];
6803         if (r_qwskincache)
6804                 Mem_Free(r_qwskincache);
6805         r_qwskincache = NULL;
6806         r_qwskincache_size = 0;
6807         if (cl.worldmodel)
6808         {
6809                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6810                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6811                 {
6812                         CL_ParseEntityLump(entities);
6813                         Mem_Free(entities);
6814                         return;
6815                 }
6816                 if (cl.worldmodel->brush.entities)
6817                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6818         }
6819         R_Main_FreeViewCache();
6820
6821         R_FrameData_Reset();
6822 }
6823
6824 void GL_Main_Init(void)
6825 {
6826         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6827
6828         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6829         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6830         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6831         if (gamemode == GAME_NEHAHRA)
6832         {
6833                 Cvar_RegisterVariable (&gl_fogenable);
6834                 Cvar_RegisterVariable (&gl_fogdensity);
6835                 Cvar_RegisterVariable (&gl_fogred);
6836                 Cvar_RegisterVariable (&gl_foggreen);
6837                 Cvar_RegisterVariable (&gl_fogblue);
6838                 Cvar_RegisterVariable (&gl_fogstart);
6839                 Cvar_RegisterVariable (&gl_fogend);
6840                 Cvar_RegisterVariable (&gl_skyclip);
6841         }
6842         Cvar_RegisterVariable(&r_motionblur);
6843         Cvar_RegisterVariable(&r_motionblur_maxblur);
6844         Cvar_RegisterVariable(&r_motionblur_bmin);
6845         Cvar_RegisterVariable(&r_motionblur_vmin);
6846         Cvar_RegisterVariable(&r_motionblur_vmax);
6847         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6848         Cvar_RegisterVariable(&r_motionblur_randomize);
6849         Cvar_RegisterVariable(&r_damageblur);
6850         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6851         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6852         Cvar_RegisterVariable(&r_equalize_entities_by);
6853         Cvar_RegisterVariable(&r_equalize_entities_to);
6854         Cvar_RegisterVariable(&r_depthfirst);
6855         Cvar_RegisterVariable(&r_useinfinitefarclip);
6856         Cvar_RegisterVariable(&r_farclip_base);
6857         Cvar_RegisterVariable(&r_farclip_world);
6858         Cvar_RegisterVariable(&r_nearclip);
6859         Cvar_RegisterVariable(&r_showbboxes);
6860         Cvar_RegisterVariable(&r_showsurfaces);
6861         Cvar_RegisterVariable(&r_showtris);
6862         Cvar_RegisterVariable(&r_shownormals);
6863         Cvar_RegisterVariable(&r_showlighting);
6864         Cvar_RegisterVariable(&r_showshadowvolumes);
6865         Cvar_RegisterVariable(&r_showcollisionbrushes);
6866         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6867         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6868         Cvar_RegisterVariable(&r_showdisabledepthtest);
6869         Cvar_RegisterVariable(&r_drawportals);
6870         Cvar_RegisterVariable(&r_drawentities);
6871         Cvar_RegisterVariable(&r_draw2d);
6872         Cvar_RegisterVariable(&r_drawworld);
6873         Cvar_RegisterVariable(&r_cullentities_trace);
6874         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6875         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6876         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6877         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6878         Cvar_RegisterVariable(&r_drawviewmodel);
6879         Cvar_RegisterVariable(&r_drawexteriormodel);
6880         Cvar_RegisterVariable(&r_speeds);
6881         Cvar_RegisterVariable(&r_fullbrights);
6882         Cvar_RegisterVariable(&r_wateralpha);
6883         Cvar_RegisterVariable(&r_dynamic);
6884         Cvar_RegisterVariable(&r_fakelight);
6885         Cvar_RegisterVariable(&r_fakelight_intensity);
6886         Cvar_RegisterVariable(&r_fullbright);
6887         Cvar_RegisterVariable(&r_shadows);
6888         Cvar_RegisterVariable(&r_shadows_darken);
6889         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6890         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6891         Cvar_RegisterVariable(&r_shadows_throwdistance);
6892         Cvar_RegisterVariable(&r_shadows_throwdirection);
6893         Cvar_RegisterVariable(&r_shadows_focus);
6894         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6895         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6896         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6897         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6898         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6899         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6900         Cvar_RegisterVariable(&r_fog_exp2);
6901         Cvar_RegisterVariable(&r_drawfog);
6902         Cvar_RegisterVariable(&r_transparentdepthmasking);
6903         Cvar_RegisterVariable(&r_texture_dds_load);
6904         Cvar_RegisterVariable(&r_texture_dds_save);
6905         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6906         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6907         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6908         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6909         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6910         Cvar_RegisterVariable(&r_textureunits);
6911         Cvar_RegisterVariable(&gl_combine);
6912         Cvar_RegisterVariable(&r_glsl);
6913         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6914         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6915         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6916         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6917         Cvar_RegisterVariable(&r_glsl_postprocess);
6918         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6919         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6920         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6921         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6922         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6923         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6924         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6925         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6926
6927         Cvar_RegisterVariable(&r_water);
6928         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6929         Cvar_RegisterVariable(&r_water_clippingplanebias);
6930         Cvar_RegisterVariable(&r_water_refractdistort);
6931         Cvar_RegisterVariable(&r_water_reflectdistort);
6932         Cvar_RegisterVariable(&r_water_scissormode);
6933         Cvar_RegisterVariable(&r_lerpsprites);
6934         Cvar_RegisterVariable(&r_lerpmodels);
6935         Cvar_RegisterVariable(&r_lerplightstyles);
6936         Cvar_RegisterVariable(&r_waterscroll);
6937         Cvar_RegisterVariable(&r_bloom);
6938         Cvar_RegisterVariable(&r_bloom_colorscale);
6939         Cvar_RegisterVariable(&r_bloom_brighten);
6940         Cvar_RegisterVariable(&r_bloom_blur);
6941         Cvar_RegisterVariable(&r_bloom_resolution);
6942         Cvar_RegisterVariable(&r_bloom_colorexponent);
6943         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6944         Cvar_RegisterVariable(&r_hdr);
6945         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6946         Cvar_RegisterVariable(&r_hdr_glowintensity);
6947         Cvar_RegisterVariable(&r_hdr_range);
6948         Cvar_RegisterVariable(&r_hdr_irisadaptation);
6949         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6950         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6951         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6952         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6953         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6954         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6955         Cvar_RegisterVariable(&developer_texturelogging);
6956         Cvar_RegisterVariable(&gl_lightmaps);
6957         Cvar_RegisterVariable(&r_test);
6958         Cvar_RegisterVariable(&r_glsl_saturation);
6959         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6960         Cvar_RegisterVariable(&r_framedatasize);
6961         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6962                 Cvar_SetValue("r_fullbrights", 0);
6963         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6964
6965         Cvar_RegisterVariable(&r_track_sprites);
6966         Cvar_RegisterVariable(&r_track_sprites_flags);
6967         Cvar_RegisterVariable(&r_track_sprites_scalew);
6968         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6969         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6970         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6971         Cvar_RegisterVariable(&r_overheadsprites_scalex);
6972         Cvar_RegisterVariable(&r_overheadsprites_scaley);
6973 }
6974
6975 extern void R_Textures_Init(void);
6976 extern void GL_Draw_Init(void);
6977 extern void GL_Main_Init(void);
6978 extern void R_Shadow_Init(void);
6979 extern void R_Sky_Init(void);
6980 extern void GL_Surf_Init(void);
6981 extern void R_Particles_Init(void);
6982 extern void R_Explosion_Init(void);
6983 extern void gl_backend_init(void);
6984 extern void Sbar_Init(void);
6985 extern void R_LightningBeams_Init(void);
6986 extern void Mod_RenderInit(void);
6987 extern void Font_Init(void);
6988
6989 void Render_Init(void)
6990 {
6991         gl_backend_init();
6992         R_Textures_Init();
6993         GL_Main_Init();
6994         Font_Init();
6995         GL_Draw_Init();
6996         R_Shadow_Init();
6997         R_Sky_Init();
6998         GL_Surf_Init();
6999         Sbar_Init();
7000         R_Particles_Init();
7001         R_Explosion_Init();
7002         R_LightningBeams_Init();
7003         Mod_RenderInit();
7004 }
7005
7006 /*
7007 ===============
7008 GL_Init
7009 ===============
7010 */
7011 extern char *ENGINE_EXTENSIONS;
7012 void GL_Init (void)
7013 {
7014         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7015         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7016         gl_version = (const char *)qglGetString(GL_VERSION);
7017         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7018
7019         if (!gl_extensions)
7020                 gl_extensions = "";
7021         if (!gl_platformextensions)
7022                 gl_platformextensions = "";
7023
7024         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7025         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7026         Con_Printf("GL_VERSION: %s\n", gl_version);
7027         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7028         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7029
7030         VID_CheckExtensions();
7031
7032         // LordHavoc: report supported extensions
7033         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7034
7035         // clear to black (loading plaque will be seen over this)
7036         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7037 }
7038
7039 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7040 {
7041         int i;
7042         mplane_t *p;
7043         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7044         {
7045                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7046                 if (i == 4)
7047                         continue;
7048                 p = r_refdef.view.frustum + i;
7049                 switch(p->signbits)
7050                 {
7051                 default:
7052                 case 0:
7053                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7054                                 return true;
7055                         break;
7056                 case 1:
7057                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7058                                 return true;
7059                         break;
7060                 case 2:
7061                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7062                                 return true;
7063                         break;
7064                 case 3:
7065                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7066                                 return true;
7067                         break;
7068                 case 4:
7069                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7070                                 return true;
7071                         break;
7072                 case 5:
7073                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7074                                 return true;
7075                         break;
7076                 case 6:
7077                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7078                                 return true;
7079                         break;
7080                 case 7:
7081                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7082                                 return true;
7083                         break;
7084                 }
7085         }
7086         return false;
7087 }
7088
7089 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7090 {
7091         int i;
7092         const mplane_t *p;
7093         for (i = 0;i < numplanes;i++)
7094         {
7095                 p = planes + i;
7096                 switch(p->signbits)
7097                 {
7098                 default:
7099                 case 0:
7100                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7101                                 return true;
7102                         break;
7103                 case 1:
7104                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7105                                 return true;
7106                         break;
7107                 case 2:
7108                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7109                                 return true;
7110                         break;
7111                 case 3:
7112                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7113                                 return true;
7114                         break;
7115                 case 4:
7116                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7117                                 return true;
7118                         break;
7119                 case 5:
7120                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7121                                 return true;
7122                         break;
7123                 case 6:
7124                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7125                                 return true;
7126                         break;
7127                 case 7:
7128                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7129                                 return true;
7130                         break;
7131                 }
7132         }
7133         return false;
7134 }
7135
7136 //==================================================================================
7137
7138 // LordHavoc: this stores temporary data used within the same frame
7139
7140 typedef struct r_framedata_mem_s
7141 {
7142         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7143         size_t size; // how much usable space
7144         size_t current; // how much space in use
7145         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7146         size_t wantedsize; // how much space was allocated
7147         unsigned char *data; // start of real data (16byte aligned)
7148 }
7149 r_framedata_mem_t;
7150
7151 static r_framedata_mem_t *r_framedata_mem;
7152
7153 void R_FrameData_Reset(void)
7154 {
7155         while (r_framedata_mem)
7156         {
7157                 r_framedata_mem_t *next = r_framedata_mem->purge;
7158                 Mem_Free(r_framedata_mem);
7159                 r_framedata_mem = next;
7160         }
7161 }
7162
7163 void R_FrameData_Resize(void)
7164 {
7165         size_t wantedsize;
7166         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7167         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7168         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7169         {
7170                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7171                 newmem->wantedsize = wantedsize;
7172                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7173                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7174                 newmem->current = 0;
7175                 newmem->mark = 0;
7176                 newmem->purge = r_framedata_mem;
7177                 r_framedata_mem = newmem;
7178         }
7179 }
7180
7181 void R_FrameData_NewFrame(void)
7182 {
7183         R_FrameData_Resize();
7184         if (!r_framedata_mem)
7185                 return;
7186         // if we ran out of space on the last frame, free the old memory now
7187         while (r_framedata_mem->purge)
7188         {
7189                 // repeatedly remove the second item in the list, leaving only head
7190                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7191                 Mem_Free(r_framedata_mem->purge);
7192                 r_framedata_mem->purge = next;
7193         }
7194         // reset the current mem pointer
7195         r_framedata_mem->current = 0;
7196         r_framedata_mem->mark = 0;
7197 }
7198
7199 void *R_FrameData_Alloc(size_t size)
7200 {
7201         void *data;
7202
7203         // align to 16 byte boundary - the data pointer is already aligned, so we
7204         // only need to ensure the size of every allocation is also aligned
7205         size = (size + 15) & ~15;
7206
7207         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7208         {
7209                 // emergency - we ran out of space, allocate more memory
7210                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7211                 R_FrameData_Resize();
7212         }
7213
7214         data = r_framedata_mem->data + r_framedata_mem->current;
7215         r_framedata_mem->current += size;
7216
7217         // count the usage for stats
7218         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7219         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7220
7221         return (void *)data;
7222 }
7223
7224 void *R_FrameData_Store(size_t size, void *data)
7225 {
7226         void *d = R_FrameData_Alloc(size);
7227         if (d && data)
7228                 memcpy(d, data, size);
7229         return d;
7230 }
7231
7232 void R_FrameData_SetMark(void)
7233 {
7234         if (!r_framedata_mem)
7235                 return;
7236         r_framedata_mem->mark = r_framedata_mem->current;
7237 }
7238
7239 void R_FrameData_ReturnToMark(void)
7240 {
7241         if (!r_framedata_mem)
7242                 return;
7243         r_framedata_mem->current = r_framedata_mem->mark;
7244 }
7245
7246 //==================================================================================
7247
7248 // LordHavoc: animcache originally written by Echon, rewritten since then
7249
7250 /**
7251  * Animation cache prevents re-generating mesh data for an animated model
7252  * multiple times in one frame for lighting, shadowing, reflections, etc.
7253  */
7254
7255 void R_AnimCache_Free(void)
7256 {
7257 }
7258
7259 void R_AnimCache_ClearCache(void)
7260 {
7261         int i;
7262         entity_render_t *ent;
7263
7264         for (i = 0;i < r_refdef.scene.numentities;i++)
7265         {
7266                 ent = r_refdef.scene.entities[i];
7267                 ent->animcache_vertex3f = NULL;
7268                 ent->animcache_normal3f = NULL;
7269                 ent->animcache_svector3f = NULL;
7270                 ent->animcache_tvector3f = NULL;
7271                 ent->animcache_vertexmesh = NULL;
7272                 ent->animcache_vertex3fbuffer = NULL;
7273                 ent->animcache_vertexmeshbuffer = NULL;
7274         }
7275 }
7276
7277 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7278 {
7279         int i;
7280
7281         // check if we need the meshbuffers
7282         if (!vid.useinterleavedarrays)
7283                 return;
7284
7285         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7286                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7287         // TODO: upload vertex3f buffer?
7288         if (ent->animcache_vertexmesh)
7289         {
7290                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7291                 for (i = 0;i < numvertices;i++)
7292                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7293                 if (ent->animcache_svector3f)
7294                         for (i = 0;i < numvertices;i++)
7295                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7296                 if (ent->animcache_tvector3f)
7297                         for (i = 0;i < numvertices;i++)
7298                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7299                 if (ent->animcache_normal3f)
7300                         for (i = 0;i < numvertices;i++)
7301                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7302                 // TODO: upload vertexmeshbuffer?
7303         }
7304 }
7305
7306 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7307 {
7308         dp_model_t *model = ent->model;
7309         int numvertices;
7310         // see if it's already cached this frame
7311         if (ent->animcache_vertex3f)
7312         {
7313                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7314                 if (wantnormals || wanttangents)
7315                 {
7316                         if (ent->animcache_normal3f)
7317                                 wantnormals = false;
7318                         if (ent->animcache_svector3f)
7319                                 wanttangents = false;
7320                         if (wantnormals || wanttangents)
7321                         {
7322                                 numvertices = model->surfmesh.num_vertices;
7323                                 if (wantnormals)
7324                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7325                                 if (wanttangents)
7326                                 {
7327                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7328                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7329                                 }
7330                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7331                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7332                         }
7333                 }
7334         }
7335         else
7336         {
7337                 // see if this ent is worth caching
7338                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7339                         return false;
7340                 // get some memory for this entity and generate mesh data
7341                 numvertices = model->surfmesh.num_vertices;
7342                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7343                 if (wantnormals)
7344                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7345                 if (wanttangents)
7346                 {
7347                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7348                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7349                 }
7350                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7351                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7352         }
7353         return true;
7354 }
7355
7356 void R_AnimCache_CacheVisibleEntities(void)
7357 {
7358         int i;
7359         qboolean wantnormals = true;
7360         qboolean wanttangents = !r_showsurfaces.integer;
7361
7362         switch(vid.renderpath)
7363         {
7364         case RENDERPATH_GL20:
7365         case RENDERPATH_D3D9:
7366         case RENDERPATH_D3D10:
7367         case RENDERPATH_D3D11:
7368         case RENDERPATH_GLES2:
7369                 break;
7370         case RENDERPATH_GL13:
7371         case RENDERPATH_GL11:
7372                 wanttangents = false;
7373                 break;
7374         case RENDERPATH_SOFT:
7375                 break;
7376         }
7377
7378         if (r_shownormals.integer)
7379                 wanttangents = wantnormals = true;
7380
7381         // TODO: thread this
7382         // NOTE: R_PrepareRTLights() also caches entities
7383
7384         for (i = 0;i < r_refdef.scene.numentities;i++)
7385                 if (r_refdef.viewcache.entityvisible[i])
7386                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7387 }
7388
7389 //==================================================================================
7390
7391 static void R_View_UpdateEntityLighting (void)
7392 {
7393         int i;
7394         entity_render_t *ent;
7395         vec3_t tempdiffusenormal, avg;
7396         vec_t f, fa, fd, fdd;
7397         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7398
7399         for (i = 0;i < r_refdef.scene.numentities;i++)
7400         {
7401                 ent = r_refdef.scene.entities[i];
7402
7403                 // skip unseen models
7404                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7405                         continue;
7406
7407                 // skip bsp models
7408                 if (ent->model && ent->model->brush.num_leafs)
7409                 {
7410                         // TODO: use modellight for r_ambient settings on world?
7411                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7412                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7413                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7414                         continue;
7415                 }
7416
7417                 // fetch the lighting from the worldmodel data
7418                 VectorClear(ent->modellight_ambient);
7419                 VectorClear(ent->modellight_diffuse);
7420                 VectorClear(tempdiffusenormal);
7421                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7422                 {
7423                         vec3_t org;
7424                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7425
7426                         // complete lightning for lit sprites
7427                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7428                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7429                         {
7430                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7431                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7432                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7433                         }
7434                         else
7435                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7436
7437                         if(ent->flags & RENDER_EQUALIZE)
7438                         {
7439                                 // first fix up ambient lighting...
7440                                 if(r_equalize_entities_minambient.value > 0)
7441                                 {
7442                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7443                                         if(fd > 0)
7444                                         {
7445                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7446                                                 if(fa < r_equalize_entities_minambient.value * fd)
7447                                                 {
7448                                                         // solve:
7449                                                         //   fa'/fd' = minambient
7450                                                         //   fa'+0.25*fd' = fa+0.25*fd
7451                                                         //   ...
7452                                                         //   fa' = fd' * minambient
7453                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7454                                                         //   ...
7455                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7456                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7457                                                         //   ...
7458                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7459                                                         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
7460                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7461                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7462                                                 }
7463                                         }
7464                                 }
7465
7466                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7467                                 {
7468                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7469                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7470                                         f = fa + 0.25 * fd;
7471                                         if(f > 0)
7472                                         {
7473                                                 // adjust brightness and saturation to target
7474                                                 avg[0] = avg[1] = avg[2] = fa / f;
7475                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7476                                                 avg[0] = avg[1] = avg[2] = fd / f;
7477                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7478                                         }
7479                                 }
7480                         }
7481                 }
7482                 else // highly rare
7483                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7484
7485                 // move the light direction into modelspace coordinates for lighting code
7486                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7487                 if(VectorLength2(ent->modellight_lightdir) == 0)
7488                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7489                 VectorNormalize(ent->modellight_lightdir);
7490         }
7491 }
7492
7493 #define MAX_LINEOFSIGHTTRACES 64
7494
7495 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7496 {
7497         int i;
7498         vec3_t boxmins, boxmaxs;
7499         vec3_t start;
7500         vec3_t end;
7501         dp_model_t *model = r_refdef.scene.worldmodel;
7502
7503         if (!model || !model->brush.TraceLineOfSight)
7504                 return true;
7505
7506         // expand the box a little
7507         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7508         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7509         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7510         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7511         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7512         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7513
7514         // return true if eye is inside enlarged box
7515         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7516                 return true;
7517
7518         // try center
7519         VectorCopy(eye, start);
7520         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7521         if (model->brush.TraceLineOfSight(model, start, end))
7522                 return true;
7523
7524         // try various random positions
7525         for (i = 0;i < numsamples;i++)
7526         {
7527                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7528                 if (model->brush.TraceLineOfSight(model, start, end))
7529                         return true;
7530         }
7531
7532         return false;
7533 }
7534
7535
7536 static void R_View_UpdateEntityVisible (void)
7537 {
7538         int i;
7539         int renderimask;
7540         int samples;
7541         entity_render_t *ent;
7542
7543         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7544                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7545                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7546                 :                                                          RENDER_EXTERIORMODEL;
7547         if (!r_drawviewmodel.integer)
7548                 renderimask |= RENDER_VIEWMODEL;
7549         if (!r_drawexteriormodel.integer)
7550                 renderimask |= RENDER_EXTERIORMODEL;
7551         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7552         {
7553                 // worldmodel can check visibility
7554                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7555                 for (i = 0;i < r_refdef.scene.numentities;i++)
7556                 {
7557                         ent = r_refdef.scene.entities[i];
7558                         if (!(ent->flags & renderimask))
7559                         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)))
7560                         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))
7561                                 r_refdef.viewcache.entityvisible[i] = true;
7562                 }
7563                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7564                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7565                 {
7566                         for (i = 0;i < r_refdef.scene.numentities;i++)
7567                         {
7568                                 ent = r_refdef.scene.entities[i];
7569                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7570                                 {
7571                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7572                                         if (samples < 0)
7573                                                 continue; // temp entities do pvs only
7574                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7575                                                 ent->last_trace_visibility = realtime;
7576                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7577                                                 r_refdef.viewcache.entityvisible[i] = 0;
7578                                 }
7579                         }
7580                 }
7581         }
7582         else
7583         {
7584                 // no worldmodel or it can't check visibility
7585                 for (i = 0;i < r_refdef.scene.numentities;i++)
7586                 {
7587                         ent = r_refdef.scene.entities[i];
7588                         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));
7589                 }
7590         }
7591 }
7592
7593 /// only used if skyrendermasked, and normally returns false
7594 int R_DrawBrushModelsSky (void)
7595 {
7596         int i, sky;
7597         entity_render_t *ent;
7598
7599         sky = false;
7600         for (i = 0;i < r_refdef.scene.numentities;i++)
7601         {
7602                 if (!r_refdef.viewcache.entityvisible[i])
7603                         continue;
7604                 ent = r_refdef.scene.entities[i];
7605                 if (!ent->model || !ent->model->DrawSky)
7606                         continue;
7607                 ent->model->DrawSky(ent);
7608                 sky = true;
7609         }
7610         return sky;
7611 }
7612
7613 static void R_DrawNoModel(entity_render_t *ent);
7614 static void R_DrawModels(void)
7615 {
7616         int i;
7617         entity_render_t *ent;
7618
7619         for (i = 0;i < r_refdef.scene.numentities;i++)
7620         {
7621                 if (!r_refdef.viewcache.entityvisible[i])
7622                         continue;
7623                 ent = r_refdef.scene.entities[i];
7624                 r_refdef.stats.entities++;
7625                 if (ent->model && ent->model->Draw != NULL)
7626                         ent->model->Draw(ent);
7627                 else
7628                         R_DrawNoModel(ent);
7629         }
7630 }
7631
7632 static void R_DrawModelsDepth(void)
7633 {
7634         int i;
7635         entity_render_t *ent;
7636
7637         for (i = 0;i < r_refdef.scene.numentities;i++)
7638         {
7639                 if (!r_refdef.viewcache.entityvisible[i])
7640                         continue;
7641                 ent = r_refdef.scene.entities[i];
7642                 if (ent->model && ent->model->DrawDepth != NULL)
7643                         ent->model->DrawDepth(ent);
7644         }
7645 }
7646
7647 static void R_DrawModelsDebug(void)
7648 {
7649         int i;
7650         entity_render_t *ent;
7651
7652         for (i = 0;i < r_refdef.scene.numentities;i++)
7653         {
7654                 if (!r_refdef.viewcache.entityvisible[i])
7655                         continue;
7656                 ent = r_refdef.scene.entities[i];
7657                 if (ent->model && ent->model->DrawDebug != NULL)
7658                         ent->model->DrawDebug(ent);
7659         }
7660 }
7661
7662 static void R_DrawModelsAddWaterPlanes(void)
7663 {
7664         int i;
7665         entity_render_t *ent;
7666
7667         for (i = 0;i < r_refdef.scene.numentities;i++)
7668         {
7669                 if (!r_refdef.viewcache.entityvisible[i])
7670                         continue;
7671                 ent = r_refdef.scene.entities[i];
7672                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7673                         ent->model->DrawAddWaterPlanes(ent);
7674         }
7675 }
7676
7677 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7678 {
7679         if (r_hdr_irisadaptation.integer)
7680         {
7681                 vec3_t ambient;
7682                 vec3_t diffuse;
7683                 vec3_t diffusenormal;
7684                 vec_t brightness;
7685                 vec_t goal;
7686                 vec_t adjust;
7687                 vec_t current;
7688                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7689                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7690                 brightness = max(0.0000001f, brightness);
7691                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7692                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7693                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7694                 current = r_hdr_irisadaptation_value.value;
7695                 if (current < goal)
7696                         current = min(current + adjust, goal);
7697                 else if (current > goal)
7698                         current = max(current - adjust, goal);
7699                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7700                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7701         }
7702         else if (r_hdr_irisadaptation_value.value != 1.0f)
7703                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7704 }
7705
7706 static void R_View_SetFrustum(const int *scissor)
7707 {
7708         int i;
7709         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7710         vec3_t forward, left, up, origin, v;
7711
7712         if(scissor)
7713         {
7714                 // flipped x coordinates (because x points left here)
7715                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7716                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7717
7718                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7719                 switch(vid.renderpath)
7720                 {
7721                         case RENDERPATH_D3D9:
7722                         case RENDERPATH_D3D10:
7723                         case RENDERPATH_D3D11:
7724                         case RENDERPATH_SOFT:
7725                                 // non-flipped y coordinates
7726                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7727                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7728                                 break;
7729                         case RENDERPATH_GL11:
7730                         case RENDERPATH_GL13:
7731                         case RENDERPATH_GL20:
7732                         case RENDERPATH_GLES2:
7733                                 // non-flipped y coordinates
7734                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7735                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7736                                 break;
7737                 }
7738         }
7739
7740         // we can't trust r_refdef.view.forward and friends in reflected scenes
7741         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7742
7743 #if 0
7744         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7745         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7746         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7747         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7748         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7749         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7750         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7751         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7752         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7753         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7754         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7755         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7756 #endif
7757
7758 #if 0
7759         zNear = r_refdef.nearclip;
7760         nudge = 1.0 - 1.0 / (1<<23);
7761         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7762         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7763         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7764         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7765         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7766         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7767         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7768         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7769 #endif
7770
7771
7772
7773 #if 0
7774         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7775         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7776         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7777         r_refdef.view.frustum[0].dist = m[15] - m[12];
7778
7779         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7780         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7781         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7782         r_refdef.view.frustum[1].dist = m[15] + m[12];
7783
7784         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7785         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7786         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7787         r_refdef.view.frustum[2].dist = m[15] - m[13];
7788
7789         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7790         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7791         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7792         r_refdef.view.frustum[3].dist = m[15] + m[13];
7793
7794         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7795         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7796         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7797         r_refdef.view.frustum[4].dist = m[15] - m[14];
7798
7799         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7800         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7801         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7802         r_refdef.view.frustum[5].dist = m[15] + m[14];
7803 #endif
7804
7805         if (r_refdef.view.useperspective)
7806         {
7807                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7808                 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]);
7809                 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]);
7810                 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]);
7811                 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]);
7812
7813                 // then the normals from the corners relative to origin
7814                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7815                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7816                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7817                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7818
7819                 // in a NORMAL view, forward cross left == up
7820                 // in a REFLECTED view, forward cross left == down
7821                 // so our cross products above need to be adjusted for a left handed coordinate system
7822                 CrossProduct(forward, left, v);
7823                 if(DotProduct(v, up) < 0)
7824                 {
7825                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7826                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7827                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7828                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7829                 }
7830
7831                 // Leaving those out was a mistake, those were in the old code, and they
7832                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7833                 // I couldn't reproduce it after adding those normalizations. --blub
7834                 VectorNormalize(r_refdef.view.frustum[0].normal);
7835                 VectorNormalize(r_refdef.view.frustum[1].normal);
7836                 VectorNormalize(r_refdef.view.frustum[2].normal);
7837                 VectorNormalize(r_refdef.view.frustum[3].normal);
7838
7839                 // make the corners absolute
7840                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7841                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7842                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7843                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7844
7845                 // one more normal
7846                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7847
7848                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7849                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7850                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7851                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7852                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7853         }
7854         else
7855         {
7856                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7857                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7858                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7859                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7860                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7861                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7862                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7863                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7864                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7865                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7866         }
7867         r_refdef.view.numfrustumplanes = 5;
7868
7869         if (r_refdef.view.useclipplane)
7870         {
7871                 r_refdef.view.numfrustumplanes = 6;
7872                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7873         }
7874
7875         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7876                 PlaneClassify(r_refdef.view.frustum + i);
7877
7878         // LordHavoc: note to all quake engine coders, Quake had a special case
7879         // for 90 degrees which assumed a square view (wrong), so I removed it,
7880         // Quake2 has it disabled as well.
7881
7882         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7883         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7884         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7885         //PlaneClassify(&frustum[0]);
7886
7887         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7888         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7889         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7890         //PlaneClassify(&frustum[1]);
7891
7892         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7893         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7894         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7895         //PlaneClassify(&frustum[2]);
7896
7897         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7898         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7899         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7900         //PlaneClassify(&frustum[3]);
7901
7902         // nearclip plane
7903         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7904         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7905         //PlaneClassify(&frustum[4]);
7906 }
7907
7908 void R_View_UpdateWithScissor(const int *myscissor)
7909 {
7910         R_Main_ResizeViewCache();
7911         R_View_SetFrustum(myscissor);
7912         R_View_WorldVisibility(r_refdef.view.useclipplane);
7913         R_View_UpdateEntityVisible();
7914         R_View_UpdateEntityLighting();
7915 }
7916
7917 void R_View_Update(void)
7918 {
7919         R_Main_ResizeViewCache();
7920         R_View_SetFrustum(NULL);
7921         R_View_WorldVisibility(r_refdef.view.useclipplane);
7922         R_View_UpdateEntityVisible();
7923         R_View_UpdateEntityLighting();
7924 }
7925
7926 void R_SetupView(qboolean allowwaterclippingplane)
7927 {
7928         const float *customclipplane = NULL;
7929         float plane[4];
7930         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7931         {
7932                 // LordHavoc: couldn't figure out how to make this approach the
7933                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7934                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7935                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7936                         dist = r_refdef.view.clipplane.dist;
7937                 plane[0] = r_refdef.view.clipplane.normal[0];
7938                 plane[1] = r_refdef.view.clipplane.normal[1];
7939                 plane[2] = r_refdef.view.clipplane.normal[2];
7940                 plane[3] = dist;
7941                 customclipplane = plane;
7942         }
7943
7944         if (!r_refdef.view.useperspective)
7945                 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);
7946         else if (vid.stencil && r_useinfinitefarclip.integer)
7947                 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);
7948         else
7949                 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);
7950         R_SetViewport(&r_refdef.view.viewport);
7951 }
7952
7953 void R_EntityMatrix(const matrix4x4_t *matrix)
7954 {
7955         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7956         {
7957                 gl_modelmatrixchanged = false;
7958                 gl_modelmatrix = *matrix;
7959                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7960                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7961                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7962                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7963                 CHECKGLERROR
7964                 switch(vid.renderpath)
7965                 {
7966                 case RENDERPATH_D3D9:
7967 #ifdef SUPPORTD3D
7968                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
7969                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
7970 #endif
7971                         break;
7972                 case RENDERPATH_D3D10:
7973                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
7974                         break;
7975                 case RENDERPATH_D3D11:
7976                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
7977                         break;
7978                 case RENDERPATH_GL13:
7979                 case RENDERPATH_GL11:
7980                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7981                         break;
7982                 case RENDERPATH_SOFT:
7983                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
7984                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
7985                         break;
7986                 case RENDERPATH_GL20:
7987                 case RENDERPATH_GLES2:
7988                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7989                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7990                         break;
7991                 }
7992         }
7993 }
7994
7995 void R_ResetViewRendering2D(void)
7996 {
7997         r_viewport_t viewport;
7998         DrawQ_Finish();
7999
8000         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8001         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);
8002         R_SetViewport(&viewport);
8003         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8004         GL_Color(1, 1, 1, 1);
8005         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8006         GL_BlendFunc(GL_ONE, GL_ZERO);
8007         GL_ScissorTest(false);
8008         GL_DepthMask(false);
8009         GL_DepthRange(0, 1);
8010         GL_DepthTest(false);
8011         GL_DepthFunc(GL_LEQUAL);
8012         R_EntityMatrix(&identitymatrix);
8013         R_Mesh_ResetTextureState();
8014         GL_PolygonOffset(0, 0);
8015         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8016         switch(vid.renderpath)
8017         {
8018         case RENDERPATH_GL11:
8019         case RENDERPATH_GL13:
8020         case RENDERPATH_GL20:
8021         case RENDERPATH_GLES2:
8022                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8023                 break;
8024         case RENDERPATH_D3D9:
8025         case RENDERPATH_D3D10:
8026         case RENDERPATH_D3D11:
8027         case RENDERPATH_SOFT:
8028                 break;
8029         }
8030         GL_CullFace(GL_NONE);
8031 }
8032
8033 void R_ResetViewRendering3D(void)
8034 {
8035         DrawQ_Finish();
8036
8037         R_SetupView(true);
8038         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8039         GL_Color(1, 1, 1, 1);
8040         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8041         GL_BlendFunc(GL_ONE, GL_ZERO);
8042         GL_ScissorTest(true);
8043         GL_DepthMask(true);
8044         GL_DepthRange(0, 1);
8045         GL_DepthTest(true);
8046         GL_DepthFunc(GL_LEQUAL);
8047         R_EntityMatrix(&identitymatrix);
8048         R_Mesh_ResetTextureState();
8049         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8050         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8051         switch(vid.renderpath)
8052         {
8053         case RENDERPATH_GL11:
8054         case RENDERPATH_GL13:
8055         case RENDERPATH_GL20:
8056         case RENDERPATH_GLES2:
8057                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8058                 break;
8059         case RENDERPATH_D3D9:
8060         case RENDERPATH_D3D10:
8061         case RENDERPATH_D3D11:
8062         case RENDERPATH_SOFT:
8063                 break;
8064         }
8065         GL_CullFace(r_refdef.view.cullface_back);
8066 }
8067
8068 /*
8069 ================
8070 R_RenderView_UpdateViewVectors
8071 ================
8072 */
8073 static void R_RenderView_UpdateViewVectors(void)
8074 {
8075         // break apart the view matrix into vectors for various purposes
8076         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8077         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8078         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8079         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8080         // make an inverted copy of the view matrix for tracking sprites
8081         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8082 }
8083
8084 void R_RenderScene(void);
8085 void R_RenderWaterPlanes(void);
8086
8087 static void R_Water_StartFrame(void)
8088 {
8089         int i;
8090         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8091         r_waterstate_waterplane_t *p;
8092
8093         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8094                 return;
8095
8096         switch(vid.renderpath)
8097         {
8098         case RENDERPATH_GL20:
8099         case RENDERPATH_D3D9:
8100         case RENDERPATH_D3D10:
8101         case RENDERPATH_D3D11:
8102         case RENDERPATH_SOFT:
8103         case RENDERPATH_GLES2:
8104                 break;
8105         case RENDERPATH_GL13:
8106         case RENDERPATH_GL11:
8107                 return;
8108         }
8109
8110         // set waterwidth and waterheight to the water resolution that will be
8111         // used (often less than the screen resolution for faster rendering)
8112         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8113         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8114
8115         // calculate desired texture sizes
8116         // can't use water if the card does not support the texture size
8117         if (!r_water.integer || r_showsurfaces.integer)
8118                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8119         else if (vid.support.arb_texture_non_power_of_two)
8120         {
8121                 texturewidth = waterwidth;
8122                 textureheight = waterheight;
8123                 camerawidth = waterwidth;
8124                 cameraheight = waterheight;
8125         }
8126         else
8127         {
8128                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8129                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8130                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8131                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8132         }
8133
8134         // allocate textures as needed
8135         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8136         {
8137                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8138                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8139                 {
8140                         if (p->texture_refraction)
8141                                 R_FreeTexture(p->texture_refraction);
8142                         p->texture_refraction = NULL;
8143                         if (p->texture_reflection)
8144                                 R_FreeTexture(p->texture_reflection);
8145                         p->texture_reflection = NULL;
8146                         if (p->texture_camera)
8147                                 R_FreeTexture(p->texture_camera);
8148                         p->texture_camera = NULL;
8149                 }
8150                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8151                 r_waterstate.texturewidth = texturewidth;
8152                 r_waterstate.textureheight = textureheight;
8153                 r_waterstate.camerawidth = camerawidth;
8154                 r_waterstate.cameraheight = cameraheight;
8155         }
8156
8157         if (r_waterstate.texturewidth)
8158         {
8159                 r_waterstate.enabled = true;
8160
8161                 // when doing a reduced render (HDR) we want to use a smaller area
8162                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8163                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8164
8165                 // set up variables that will be used in shader setup
8166                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8167                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8168                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8169                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8170         }
8171
8172         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8173         r_waterstate.numwaterplanes = 0;
8174 }
8175
8176 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8177 {
8178         int triangleindex, planeindex;
8179         const int *e;
8180         vec3_t vert[3];
8181         vec3_t normal;
8182         vec3_t center;
8183         mplane_t plane;
8184         r_waterstate_waterplane_t *p;
8185         texture_t *t = R_GetCurrentTexture(surface->texture);
8186
8187         // just use the first triangle with a valid normal for any decisions
8188         VectorClear(normal);
8189         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8190         {
8191                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8192                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8193                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8194                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8195                 if (VectorLength2(normal) >= 0.001)
8196                         break;
8197         }
8198
8199         VectorCopy(normal, plane.normal);
8200         VectorNormalize(plane.normal);
8201         plane.dist = DotProduct(vert[0], plane.normal);
8202         PlaneClassify(&plane);
8203         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8204         {
8205                 // skip backfaces (except if nocullface is set)
8206                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8207                         return;
8208                 VectorNegate(plane.normal, plane.normal);
8209                 plane.dist *= -1;
8210                 PlaneClassify(&plane);
8211         }
8212
8213
8214         // find a matching plane if there is one
8215         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8216                 if(p->camera_entity == t->camera_entity)
8217                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8218                                 break;
8219         if (planeindex >= r_waterstate.maxwaterplanes)
8220                 return; // nothing we can do, out of planes
8221
8222         // if this triangle does not fit any known plane rendered this frame, add one
8223         if (planeindex >= r_waterstate.numwaterplanes)
8224         {
8225                 // store the new plane
8226                 r_waterstate.numwaterplanes++;
8227                 p->plane = plane;
8228                 // clear materialflags and pvs
8229                 p->materialflags = 0;
8230                 p->pvsvalid = false;
8231                 p->camera_entity = t->camera_entity;
8232                 VectorCopy(surface->mins, p->mins);
8233                 VectorCopy(surface->maxs, p->maxs);
8234         }
8235         else
8236         {
8237                 // merge mins/maxs
8238                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8239                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8240                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8241                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8242                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8243                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8244         }
8245         // merge this surface's materialflags into the waterplane
8246         p->materialflags |= t->currentmaterialflags;
8247         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8248         {
8249                 // merge this surface's PVS into the waterplane
8250                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8251                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8252                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8253                 {
8254                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8255                         p->pvsvalid = true;
8256                 }
8257         }
8258 }
8259
8260 static void R_Water_ProcessPlanes(void)
8261 {
8262         int myscissor[4];
8263         r_refdef_view_t originalview;
8264         r_refdef_view_t myview;
8265         int planeindex;
8266         r_waterstate_waterplane_t *p;
8267         vec3_t visorigin;
8268
8269         originalview = r_refdef.view;
8270
8271         // make sure enough textures are allocated
8272         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8273         {
8274                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8275                 {
8276                         if (!p->texture_refraction)
8277                                 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);
8278                         if (!p->texture_refraction)
8279                                 goto error;
8280                 }
8281                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8282                 {
8283                         if (!p->texture_camera)
8284                                 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);
8285                         if (!p->texture_camera)
8286                                 goto error;
8287                 }
8288
8289                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8290                 {
8291                         if (!p->texture_reflection)
8292                                 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);
8293                         if (!p->texture_reflection)
8294                                 goto error;
8295                 }
8296         }
8297
8298         // render views
8299         r_refdef.view = originalview;
8300         r_refdef.view.showdebug = false;
8301         r_refdef.view.width = r_waterstate.waterwidth;
8302         r_refdef.view.height = r_waterstate.waterheight;
8303         r_refdef.view.useclipplane = true;
8304         myview = r_refdef.view;
8305         r_waterstate.renderingscene = true;
8306         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8307         {
8308                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8309                 {
8310                         r_refdef.view = myview;
8311                         if(r_water_scissormode.integer)
8312                         {
8313                                 R_SetupView(true);
8314                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8315                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8316                         }
8317
8318                         // render reflected scene and copy into texture
8319                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8320                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8321                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8322                         r_refdef.view.clipplane = p->plane;
8323
8324                         // reverse the cullface settings for this render
8325                         r_refdef.view.cullface_front = GL_FRONT;
8326                         r_refdef.view.cullface_back = GL_BACK;
8327                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8328                         {
8329                                 r_refdef.view.usecustompvs = true;
8330                                 if (p->pvsvalid)
8331                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8332                                 else
8333                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8334                         }
8335
8336                         R_ResetViewRendering3D();
8337                         R_ClearScreen(r_refdef.fogenabled);
8338                         if(r_water_scissormode.integer & 2)
8339                                 R_View_UpdateWithScissor(myscissor);
8340                         else
8341                                 R_View_Update();
8342                         if(r_water_scissormode.integer & 1)
8343                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8344                         R_RenderScene();
8345
8346                         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);
8347                 }
8348
8349                 // render the normal view scene and copy into texture
8350                 // (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)
8351                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8352                 {
8353                         r_refdef.view = myview;
8354                         if(r_water_scissormode.integer)
8355                         {
8356                                 R_SetupView(true);
8357                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8358                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8359                         }
8360
8361                         r_waterstate.renderingrefraction = true;
8362
8363                         r_refdef.view.clipplane = p->plane;
8364                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8365                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8366
8367                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8368                         {
8369                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8370                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8371                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8372                                 R_RenderView_UpdateViewVectors();
8373                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8374                                 {
8375                                         r_refdef.view.usecustompvs = true;
8376                                         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);
8377                                 }
8378                         }
8379
8380                         PlaneClassify(&r_refdef.view.clipplane);
8381
8382                         R_ResetViewRendering3D();
8383                         R_ClearScreen(r_refdef.fogenabled);
8384                         if(r_water_scissormode.integer & 2)
8385                                 R_View_UpdateWithScissor(myscissor);
8386                         else
8387                                 R_View_Update();
8388                         if(r_water_scissormode.integer & 1)
8389                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8390                         R_RenderScene();
8391
8392                         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);
8393                         r_waterstate.renderingrefraction = false;
8394                 }
8395                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8396                 {
8397                         r_refdef.view = myview;
8398
8399                         r_refdef.view.clipplane = p->plane;
8400                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8401                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8402
8403                         r_refdef.view.width = r_waterstate.camerawidth;
8404                         r_refdef.view.height = r_waterstate.cameraheight;
8405                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8406                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8407
8408                         if(p->camera_entity)
8409                         {
8410                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8411                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8412                         }
8413
8414                         // note: all of the view is used for displaying... so
8415                         // there is no use in scissoring
8416
8417                         // reverse the cullface settings for this render
8418                         r_refdef.view.cullface_front = GL_FRONT;
8419                         r_refdef.view.cullface_back = GL_BACK;
8420                         // also reverse the view matrix
8421                         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
8422                         R_RenderView_UpdateViewVectors();
8423                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8424                         {
8425                                 r_refdef.view.usecustompvs = true;
8426                                 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);
8427                         }
8428                         
8429                         // camera needs no clipplane
8430                         r_refdef.view.useclipplane = false;
8431
8432                         PlaneClassify(&r_refdef.view.clipplane);
8433
8434                         R_ResetViewRendering3D();
8435                         R_ClearScreen(r_refdef.fogenabled);
8436                         R_View_Update();
8437                         R_RenderScene();
8438
8439                         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);
8440                         r_waterstate.renderingrefraction = false;
8441                 }
8442
8443         }
8444         r_waterstate.renderingscene = false;
8445         r_refdef.view = originalview;
8446         R_ResetViewRendering3D();
8447         R_ClearScreen(r_refdef.fogenabled);
8448         R_View_Update();
8449         return;
8450 error:
8451         r_refdef.view = originalview;
8452         r_waterstate.renderingscene = false;
8453         Cvar_SetValueQuick(&r_water, 0);
8454         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8455         return;
8456 }
8457
8458 void R_Bloom_StartFrame(void)
8459 {
8460         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8461
8462         switch(vid.renderpath)
8463         {
8464         case RENDERPATH_GL20:
8465         case RENDERPATH_D3D9:
8466         case RENDERPATH_D3D10:
8467         case RENDERPATH_D3D11:
8468         case RENDERPATH_SOFT:
8469         case RENDERPATH_GLES2:
8470                 break;
8471         case RENDERPATH_GL13:
8472         case RENDERPATH_GL11:
8473                 return;
8474         }
8475
8476         // set bloomwidth and bloomheight to the bloom resolution that will be
8477         // used (often less than the screen resolution for faster rendering)
8478         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8479         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8480         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8481         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8482         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8483
8484         // calculate desired texture sizes
8485         if (vid.support.arb_texture_non_power_of_two)
8486         {
8487                 screentexturewidth = r_refdef.view.width;
8488                 screentextureheight = r_refdef.view.height;
8489                 bloomtexturewidth = r_bloomstate.bloomwidth;
8490                 bloomtextureheight = r_bloomstate.bloomheight;
8491         }
8492         else
8493         {
8494                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8495                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8496                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8497                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8498         }
8499
8500         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))
8501         {
8502                 Cvar_SetValueQuick(&r_hdr, 0);
8503                 Cvar_SetValueQuick(&r_bloom, 0);
8504                 Cvar_SetValueQuick(&r_motionblur, 0);
8505                 Cvar_SetValueQuick(&r_damageblur, 0);
8506         }
8507
8508         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)))
8509                 screentexturewidth = screentextureheight = 0;
8510         if (!r_hdr.integer && !r_bloom.integer)
8511                 bloomtexturewidth = bloomtextureheight = 0;
8512
8513         // allocate textures as needed
8514         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8515         {
8516                 if (r_bloomstate.texture_screen)
8517                         R_FreeTexture(r_bloomstate.texture_screen);
8518                 r_bloomstate.texture_screen = NULL;
8519                 r_bloomstate.screentexturewidth = screentexturewidth;
8520                 r_bloomstate.screentextureheight = screentextureheight;
8521                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8522                         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);
8523         }
8524         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8525         {
8526                 if (r_bloomstate.texture_bloom)
8527                         R_FreeTexture(r_bloomstate.texture_bloom);
8528                 r_bloomstate.texture_bloom = NULL;
8529                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8530                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8531                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8532                         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);
8533         }
8534
8535         // when doing a reduced render (HDR) we want to use a smaller area
8536         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8537         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8538         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8539         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8540         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8541
8542         // set up a texcoord array for the full resolution screen image
8543         // (we have to keep this around to copy back during final render)
8544         r_bloomstate.screentexcoord2f[0] = 0;
8545         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8546         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8547         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8548         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8549         r_bloomstate.screentexcoord2f[5] = 0;
8550         r_bloomstate.screentexcoord2f[6] = 0;
8551         r_bloomstate.screentexcoord2f[7] = 0;
8552
8553         // set up a texcoord array for the reduced resolution bloom image
8554         // (which will be additive blended over the screen image)
8555         r_bloomstate.bloomtexcoord2f[0] = 0;
8556         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8557         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8558         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8559         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8560         r_bloomstate.bloomtexcoord2f[5] = 0;
8561         r_bloomstate.bloomtexcoord2f[6] = 0;
8562         r_bloomstate.bloomtexcoord2f[7] = 0;
8563
8564         switch(vid.renderpath)
8565         {
8566         case RENDERPATH_GL11:
8567         case RENDERPATH_GL13:
8568         case RENDERPATH_GL20:
8569         case RENDERPATH_SOFT:
8570         case RENDERPATH_GLES2:
8571                 break;
8572         case RENDERPATH_D3D9:
8573         case RENDERPATH_D3D10:
8574         case RENDERPATH_D3D11:
8575                 {
8576                         int i;
8577                         for (i = 0;i < 4;i++)
8578                         {
8579                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8580                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8581                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8582                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8583                         }
8584                 }
8585                 break;
8586         }
8587
8588         if (r_hdr.integer || r_bloom.integer)
8589         {
8590                 r_bloomstate.enabled = true;
8591                 r_bloomstate.hdr = r_hdr.integer != 0;
8592         }
8593
8594         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);
8595 }
8596
8597 void R_Bloom_CopyBloomTexture(float colorscale)
8598 {
8599         r_refdef.stats.bloom++;
8600
8601         // scale down screen texture to the bloom texture size
8602         CHECKGLERROR
8603         R_SetViewport(&r_bloomstate.viewport);
8604         GL_BlendFunc(GL_ONE, GL_ZERO);
8605         GL_Color(colorscale, colorscale, colorscale, 1);
8606         // 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...
8607         switch(vid.renderpath)
8608         {
8609         case RENDERPATH_GL11:
8610         case RENDERPATH_GL13:
8611         case RENDERPATH_GL20:
8612         case RENDERPATH_SOFT:
8613         case RENDERPATH_GLES2:
8614                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8615                 break;
8616         case RENDERPATH_D3D9:
8617         case RENDERPATH_D3D10:
8618         case RENDERPATH_D3D11:
8619                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8620                 break;
8621         }
8622         // TODO: do boxfilter scale-down in shader?
8623         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8624         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8625         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8626
8627         // we now have a bloom image in the framebuffer
8628         // copy it into the bloom image texture for later processing
8629         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);
8630         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8631 }
8632
8633 void R_Bloom_CopyHDRTexture(void)
8634 {
8635         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);
8636         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8637 }
8638
8639 void R_Bloom_MakeTexture(void)
8640 {
8641         int x, range, dir;
8642         float xoffset, yoffset, r, brighten;
8643
8644         r_refdef.stats.bloom++;
8645
8646         R_ResetViewRendering2D();
8647
8648         // we have a bloom image in the framebuffer
8649         CHECKGLERROR
8650         R_SetViewport(&r_bloomstate.viewport);
8651
8652         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8653         {
8654                 x *= 2;
8655                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8656                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8657                 GL_Color(r,r,r,1);
8658                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8659                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8660                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8661                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8662
8663                 // copy the vertically blurred bloom view to a texture
8664                 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);
8665                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8666         }
8667
8668         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8669         brighten = r_bloom_brighten.value;
8670         if (r_hdr.integer)
8671                 brighten *= r_hdr_range.value;
8672         brighten = sqrt(brighten);
8673         if(range >= 1)
8674                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8675         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8676
8677         for (dir = 0;dir < 2;dir++)
8678         {
8679                 // blend on at multiple vertical offsets to achieve a vertical blur
8680                 // TODO: do offset blends using GLSL
8681                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8682                 GL_BlendFunc(GL_ONE, GL_ZERO);
8683                 for (x = -range;x <= range;x++)
8684                 {
8685                         if (!dir){xoffset = 0;yoffset = x;}
8686                         else {xoffset = x;yoffset = 0;}
8687                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8688                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8689                         // compute a texcoord array with the specified x and y offset
8690                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8691                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8692                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8693                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8694                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8695                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8696                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8697                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8698                         // this r value looks like a 'dot' particle, fading sharply to
8699                         // black at the edges
8700                         // (probably not realistic but looks good enough)
8701                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8702                         //r = brighten/(range*2+1);
8703                         r = brighten / (range * 2 + 1);
8704                         if(range >= 1)
8705                                 r *= (1 - x*x/(float)(range*range));
8706                         GL_Color(r, r, r, 1);
8707                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8708                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8709                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8710                         GL_BlendFunc(GL_ONE, GL_ONE);
8711                 }
8712
8713                 // copy the vertically blurred bloom view to a texture
8714                 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);
8715                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8716         }
8717 }
8718
8719 void R_HDR_RenderBloomTexture(void)
8720 {
8721         int oldwidth, oldheight;
8722         float oldcolorscale;
8723         qboolean oldwaterstate;
8724
8725         oldwaterstate = r_waterstate.enabled;
8726         oldcolorscale = r_refdef.view.colorscale;
8727         oldwidth = r_refdef.view.width;
8728         oldheight = r_refdef.view.height;
8729         r_refdef.view.width = r_bloomstate.bloomwidth;
8730         r_refdef.view.height = r_bloomstate.bloomheight;
8731
8732         if(r_hdr.integer < 2)
8733                 r_waterstate.enabled = false;
8734
8735         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8736         // TODO: add exposure compensation features
8737         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8738
8739         r_refdef.view.showdebug = false;
8740         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8741
8742         R_ResetViewRendering3D();
8743
8744         R_ClearScreen(r_refdef.fogenabled);
8745         if (r_timereport_active)
8746                 R_TimeReport("HDRclear");
8747
8748         R_View_Update();
8749         if (r_timereport_active)
8750                 R_TimeReport("visibility");
8751
8752         // only do secondary renders with HDR if r_hdr is 2 or higher
8753         r_waterstate.numwaterplanes = 0;
8754         if (r_waterstate.enabled)
8755                 R_RenderWaterPlanes();
8756
8757         r_refdef.view.showdebug = true;
8758         R_RenderScene();
8759         r_waterstate.numwaterplanes = 0;
8760
8761         R_ResetViewRendering2D();
8762
8763         R_Bloom_CopyHDRTexture();
8764         R_Bloom_MakeTexture();
8765
8766         // restore the view settings
8767         r_waterstate.enabled = oldwaterstate;
8768         r_refdef.view.width = oldwidth;
8769         r_refdef.view.height = oldheight;
8770         r_refdef.view.colorscale = oldcolorscale;
8771
8772         R_ResetViewRendering3D();
8773
8774         R_ClearScreen(r_refdef.fogenabled);
8775         if (r_timereport_active)
8776                 R_TimeReport("viewclear");
8777 }
8778
8779 static void R_BlendView(void)
8780 {
8781         unsigned int permutation;
8782         float uservecs[4][4];
8783
8784         switch (vid.renderpath)
8785         {
8786         case RENDERPATH_GL20:
8787         case RENDERPATH_D3D9:
8788         case RENDERPATH_D3D10:
8789         case RENDERPATH_D3D11:
8790         case RENDERPATH_SOFT:
8791         case RENDERPATH_GLES2:
8792                 permutation =
8793                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8794                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8795                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8796                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8797                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8798
8799                 if (r_bloomstate.texture_screen)
8800                 {
8801                         // make sure the buffer is available
8802                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8803
8804                         R_ResetViewRendering2D();
8805
8806                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8807                         {
8808                                 // declare variables
8809                                 float speed;
8810                                 static float avgspeed;
8811
8812                                 speed = VectorLength(cl.movement_velocity);
8813
8814                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8815                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8816
8817                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8818                                 speed = bound(0, speed, 1);
8819                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8820
8821                                 // calculate values into a standard alpha
8822                                 cl.motionbluralpha = 1 - exp(-
8823                                                 (
8824                                                  (r_motionblur.value * speed / 80)
8825                                                  +
8826                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8827                                                 )
8828                                                 /
8829                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8830                                            );
8831
8832                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8833                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8834                                 // apply the blur
8835                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8836                                 {
8837                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8838                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8839                                         switch(vid.renderpath)
8840                                         {
8841                                         case RENDERPATH_GL11:
8842                                         case RENDERPATH_GL13:
8843                                         case RENDERPATH_GL20:
8844                                         case RENDERPATH_SOFT:
8845                                         case RENDERPATH_GLES2:
8846                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8847                                                 break;
8848                                         case RENDERPATH_D3D9:
8849                                         case RENDERPATH_D3D10:
8850                                         case RENDERPATH_D3D11:
8851                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8852                                                 break;
8853                                         }
8854                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8855                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8856                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8857                                 }
8858                         }
8859
8860                         // copy view into the screen texture
8861                         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);
8862                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8863                 }
8864                 else if (!r_bloomstate.texture_bloom)
8865                 {
8866                         // we may still have to do view tint...
8867                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8868                         {
8869                                 // apply a color tint to the whole view
8870                                 R_ResetViewRendering2D();
8871                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8872                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8873                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8874                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8875                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8876                         }
8877                         break; // no screen processing, no bloom, skip it
8878                 }
8879
8880                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8881                 {
8882                         // render simple bloom effect
8883                         // copy the screen and shrink it and darken it for the bloom process
8884                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8885                         // make the bloom texture
8886                         R_Bloom_MakeTexture();
8887                 }
8888
8889 #if _MSC_VER >= 1400
8890 #define sscanf sscanf_s
8891 #endif
8892                 memset(uservecs, 0, sizeof(uservecs));
8893                 if (r_glsl_postprocess_uservec1_enable.integer)
8894                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8895                 if (r_glsl_postprocess_uservec2_enable.integer)
8896                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8897                 if (r_glsl_postprocess_uservec3_enable.integer)
8898                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8899                 if (r_glsl_postprocess_uservec4_enable.integer)
8900                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8901
8902                 R_ResetViewRendering2D();
8903                 GL_Color(1, 1, 1, 1);
8904                 GL_BlendFunc(GL_ONE, GL_ZERO);
8905
8906                 switch(vid.renderpath)
8907                 {
8908                 case RENDERPATH_GL20:
8909                 case RENDERPATH_GLES2:
8910                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8911                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8912                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
8913                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
8914                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
8915                         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]);
8916                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8917                         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]);
8918                         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]);
8919                         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]);
8920                         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]);
8921                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8922                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8923                         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);
8924                         break;
8925                 case RENDERPATH_D3D9:
8926 #ifdef SUPPORTD3D
8927                         // 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...
8928                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8929                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8930                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8931                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8932                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8933                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8934                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8935                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8936                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8937                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8938                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8939                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
8940                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8941                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8942 #endif
8943                         break;
8944                 case RENDERPATH_D3D10:
8945                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8946                         break;
8947                 case RENDERPATH_D3D11:
8948                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8949                         break;
8950                 case RENDERPATH_SOFT:
8951                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8952                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8953                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8954                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8955                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8956                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8957                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8958                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8959                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8960                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8961                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8962                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
8963                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8964                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8965                         break;
8966                 default:
8967                         break;
8968                 }
8969                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8970                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8971                 break;
8972         case RENDERPATH_GL13:
8973         case RENDERPATH_GL11:
8974                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8975                 {
8976                         // apply a color tint to the whole view
8977                         R_ResetViewRendering2D();
8978                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8979                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8980                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8981                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8982                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8983                 }
8984                 break;
8985         }
8986 }
8987
8988 matrix4x4_t r_waterscrollmatrix;
8989
8990 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8991 {
8992         if (r_refdef.fog_density)
8993         {
8994                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8995                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8996                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8997
8998                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8999                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9000                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9001                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9002
9003                 {
9004                         vec3_t fogvec;
9005                         VectorCopy(r_refdef.fogcolor, fogvec);
9006                         //   color.rgb *= ContrastBoost * SceneBrightness;
9007                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9008                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9009                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9010                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9011                 }
9012         }
9013 }
9014
9015 void R_UpdateVariables(void)
9016 {
9017         R_Textures_Frame();
9018
9019         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9020
9021         r_refdef.farclip = r_farclip_base.value;
9022         if (r_refdef.scene.worldmodel)
9023                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9024         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9025
9026         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9027                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9028         r_refdef.polygonfactor = 0;
9029         r_refdef.polygonoffset = 0;
9030         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9031         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9032
9033         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9034         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9035         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9036         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9037         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9038         if (FAKELIGHT_ENABLED)
9039         {
9040                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9041         }
9042         if (r_showsurfaces.integer)
9043         {
9044                 r_refdef.scene.rtworld = false;
9045                 r_refdef.scene.rtworldshadows = false;
9046                 r_refdef.scene.rtdlight = false;
9047                 r_refdef.scene.rtdlightshadows = false;
9048                 r_refdef.lightmapintensity = 0;
9049         }
9050
9051         if (gamemode == GAME_NEHAHRA)
9052         {
9053                 if (gl_fogenable.integer)
9054                 {
9055                         r_refdef.oldgl_fogenable = true;
9056                         r_refdef.fog_density = gl_fogdensity.value;
9057                         r_refdef.fog_red = gl_fogred.value;
9058                         r_refdef.fog_green = gl_foggreen.value;
9059                         r_refdef.fog_blue = gl_fogblue.value;
9060                         r_refdef.fog_alpha = 1;
9061                         r_refdef.fog_start = 0;
9062                         r_refdef.fog_end = gl_skyclip.value;
9063                         r_refdef.fog_height = 1<<30;
9064                         r_refdef.fog_fadedepth = 128;
9065                 }
9066                 else if (r_refdef.oldgl_fogenable)
9067                 {
9068                         r_refdef.oldgl_fogenable = false;
9069                         r_refdef.fog_density = 0;
9070                         r_refdef.fog_red = 0;
9071                         r_refdef.fog_green = 0;
9072                         r_refdef.fog_blue = 0;
9073                         r_refdef.fog_alpha = 0;
9074                         r_refdef.fog_start = 0;
9075                         r_refdef.fog_end = 0;
9076                         r_refdef.fog_height = 1<<30;
9077                         r_refdef.fog_fadedepth = 128;
9078                 }
9079         }
9080
9081         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9082         r_refdef.fog_start = max(0, r_refdef.fog_start);
9083         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9084
9085         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9086
9087         if (r_refdef.fog_density && r_drawfog.integer)
9088         {
9089                 r_refdef.fogenabled = true;
9090                 // this is the point where the fog reaches 0.9986 alpha, which we
9091                 // consider a good enough cutoff point for the texture
9092                 // (0.9986 * 256 == 255.6)
9093                 if (r_fog_exp2.integer)
9094                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9095                 else
9096                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9097                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9098                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9099                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9100                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9101                         R_BuildFogHeightTexture();
9102                 // fog color was already set
9103                 // update the fog texture
9104                 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)
9105                         R_BuildFogTexture();
9106                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9107                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9108         }
9109         else
9110                 r_refdef.fogenabled = false;
9111
9112         switch(vid.renderpath)
9113         {
9114         case RENDERPATH_GL20:
9115         case RENDERPATH_D3D9:
9116         case RENDERPATH_D3D10:
9117         case RENDERPATH_D3D11:
9118         case RENDERPATH_SOFT:
9119         case RENDERPATH_GLES2:
9120                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9121                 {
9122                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9123                         {
9124                                 // build GLSL gamma texture
9125 #define RAMPWIDTH 256
9126                                 unsigned short ramp[RAMPWIDTH * 3];
9127                                 unsigned char rampbgr[RAMPWIDTH][4];
9128                                 int i;
9129
9130                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9131
9132                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9133                                 for(i = 0; i < RAMPWIDTH; ++i)
9134                                 {
9135                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9136                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9137                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9138                                         rampbgr[i][3] = 0;
9139                                 }
9140                                 if (r_texture_gammaramps)
9141                                 {
9142                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, RAMPWIDTH, 1);
9143                                 }
9144                                 else
9145                                 {
9146                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9147                                 }
9148                         }
9149                 }
9150                 else
9151                 {
9152                         // remove GLSL gamma texture
9153                 }
9154                 break;
9155         case RENDERPATH_GL13:
9156         case RENDERPATH_GL11:
9157                 break;
9158         }
9159 }
9160
9161 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9162 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9163 /*
9164 ================
9165 R_SelectScene
9166 ================
9167 */
9168 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9169         if( scenetype != r_currentscenetype ) {
9170                 // store the old scenetype
9171                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9172                 r_currentscenetype = scenetype;
9173                 // move in the new scene
9174                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9175         }
9176 }
9177
9178 /*
9179 ================
9180 R_GetScenePointer
9181 ================
9182 */
9183 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9184 {
9185         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9186         if( scenetype == r_currentscenetype ) {
9187                 return &r_refdef.scene;
9188         } else {
9189                 return &r_scenes_store[ scenetype ];
9190         }
9191 }
9192
9193 /*
9194 ================
9195 R_RenderView
9196 ================
9197 */
9198 int dpsoftrast_test;
9199 void R_RenderView(void)
9200 {
9201         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9202
9203         dpsoftrast_test = r_test.integer;
9204
9205         if (r_timereport_active)
9206                 R_TimeReport("start");
9207         r_textureframe++; // used only by R_GetCurrentTexture
9208         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9209
9210         if(R_CompileShader_CheckStaticParms())
9211                 R_GLSL_Restart_f();
9212
9213         if (!r_drawentities.integer)
9214                 r_refdef.scene.numentities = 0;
9215
9216         R_AnimCache_ClearCache();
9217         R_FrameData_NewFrame();
9218
9219         /* adjust for stereo display */
9220         if(R_Stereo_Active())
9221         {
9222                 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);
9223                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9224         }
9225
9226         if (r_refdef.view.isoverlay)
9227         {
9228                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9229                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9230                 R_TimeReport("depthclear");
9231
9232                 r_refdef.view.showdebug = false;
9233
9234                 r_waterstate.enabled = false;
9235                 r_waterstate.numwaterplanes = 0;
9236
9237                 R_RenderScene();
9238
9239                 r_refdef.view.matrix = originalmatrix;
9240
9241                 CHECKGLERROR
9242                 return;
9243         }
9244
9245         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9246         {
9247                 r_refdef.view.matrix = originalmatrix;
9248                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9249         }
9250
9251         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9252
9253         R_RenderView_UpdateViewVectors();
9254
9255         R_Shadow_UpdateWorldLightSelection();
9256
9257         R_Bloom_StartFrame();
9258         R_Water_StartFrame();
9259
9260         CHECKGLERROR
9261         if (r_timereport_active)
9262                 R_TimeReport("viewsetup");
9263
9264         R_ResetViewRendering3D();
9265
9266         if (r_refdef.view.clear || r_refdef.fogenabled)
9267         {
9268                 R_ClearScreen(r_refdef.fogenabled);
9269                 if (r_timereport_active)
9270                         R_TimeReport("viewclear");
9271         }
9272         r_refdef.view.clear = true;
9273
9274         // this produces a bloom texture to be used in R_BlendView() later
9275         if (r_hdr.integer && r_bloomstate.bloomwidth)
9276         {
9277                 R_HDR_RenderBloomTexture();
9278                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9279                 r_textureframe++; // used only by R_GetCurrentTexture
9280         }
9281
9282         r_refdef.view.showdebug = true;
9283
9284         R_View_Update();
9285         if (r_timereport_active)
9286                 R_TimeReport("visibility");
9287
9288         r_waterstate.numwaterplanes = 0;
9289         if (r_waterstate.enabled)
9290                 R_RenderWaterPlanes();
9291
9292         R_RenderScene();
9293         r_waterstate.numwaterplanes = 0;
9294
9295         R_BlendView();
9296         if (r_timereport_active)
9297                 R_TimeReport("blendview");
9298
9299         GL_Scissor(0, 0, vid.width, vid.height);
9300         GL_ScissorTest(false);
9301
9302         r_refdef.view.matrix = originalmatrix;
9303
9304         CHECKGLERROR
9305 }
9306
9307 void R_RenderWaterPlanes(void)
9308 {
9309         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9310         {
9311                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9312                 if (r_timereport_active)
9313                         R_TimeReport("waterworld");
9314         }
9315
9316         // don't let sound skip if going slow
9317         if (r_refdef.scene.extraupdate)
9318                 S_ExtraUpdate ();
9319
9320         R_DrawModelsAddWaterPlanes();
9321         if (r_timereport_active)
9322                 R_TimeReport("watermodels");
9323
9324         if (r_waterstate.numwaterplanes)
9325         {
9326                 R_Water_ProcessPlanes();
9327                 if (r_timereport_active)
9328                         R_TimeReport("waterscenes");
9329         }
9330 }
9331
9332 extern void R_DrawLightningBeams (void);
9333 extern void VM_CL_AddPolygonsToMeshQueue (void);
9334 extern void R_DrawPortals (void);
9335 extern cvar_t cl_locs_show;
9336 static void R_DrawLocs(void);
9337 static void R_DrawEntityBBoxes(void);
9338 static void R_DrawModelDecals(void);
9339 extern void R_DrawModelShadows(void);
9340 extern void R_DrawModelShadowMaps(void);
9341 extern cvar_t cl_decals_newsystem;
9342 extern qboolean r_shadow_usingdeferredprepass;
9343 void R_RenderScene(void)
9344 {
9345         qboolean shadowmapping = false;
9346
9347         if (r_timereport_active)
9348                 R_TimeReport("beginscene");
9349
9350         r_refdef.stats.renders++;
9351
9352         R_UpdateFogColor();
9353
9354         // don't let sound skip if going slow
9355         if (r_refdef.scene.extraupdate)
9356                 S_ExtraUpdate ();
9357
9358         R_MeshQueue_BeginScene();
9359
9360         R_SkyStartFrame();
9361
9362         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);
9363
9364         if (r_timereport_active)
9365                 R_TimeReport("skystartframe");
9366
9367         if (cl.csqc_vidvars.drawworld)
9368         {
9369                 // don't let sound skip if going slow
9370                 if (r_refdef.scene.extraupdate)
9371                         S_ExtraUpdate ();
9372
9373                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9374                 {
9375                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9376                         if (r_timereport_active)
9377                                 R_TimeReport("worldsky");
9378                 }
9379
9380                 if (R_DrawBrushModelsSky() && r_timereport_active)
9381                         R_TimeReport("bmodelsky");
9382
9383                 if (skyrendermasked && skyrenderlater)
9384                 {
9385                         // we have to force off the water clipping plane while rendering sky
9386                         R_SetupView(false);
9387                         R_Sky();
9388                         R_SetupView(true);
9389                         if (r_timereport_active)
9390                                 R_TimeReport("sky");
9391                 }
9392         }
9393
9394         R_AnimCache_CacheVisibleEntities();
9395         if (r_timereport_active)
9396                 R_TimeReport("animation");
9397
9398         R_Shadow_PrepareLights();
9399         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9400                 R_Shadow_PrepareModelShadows();
9401         if (r_timereport_active)
9402                 R_TimeReport("preparelights");
9403
9404         if (R_Shadow_ShadowMappingEnabled())
9405                 shadowmapping = true;
9406
9407         if (r_shadow_usingdeferredprepass)
9408                 R_Shadow_DrawPrepass();
9409
9410         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9411         {
9412                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9413                 if (r_timereport_active)
9414                         R_TimeReport("worlddepth");
9415         }
9416         if (r_depthfirst.integer >= 2)
9417         {
9418                 R_DrawModelsDepth();
9419                 if (r_timereport_active)
9420                         R_TimeReport("modeldepth");
9421         }
9422
9423         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9424         {
9425                 R_DrawModelShadowMaps();
9426                 R_ResetViewRendering3D();
9427                 // don't let sound skip if going slow
9428                 if (r_refdef.scene.extraupdate)
9429                         S_ExtraUpdate ();
9430         }
9431
9432         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9433         {
9434                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9435                 if (r_timereport_active)
9436                         R_TimeReport("world");
9437         }
9438
9439         // don't let sound skip if going slow
9440         if (r_refdef.scene.extraupdate)
9441                 S_ExtraUpdate ();
9442
9443         R_DrawModels();
9444         if (r_timereport_active)
9445                 R_TimeReport("models");
9446
9447         // don't let sound skip if going slow
9448         if (r_refdef.scene.extraupdate)
9449                 S_ExtraUpdate ();
9450
9451         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9452         {
9453                 R_DrawModelShadows();
9454                 R_ResetViewRendering3D();
9455                 // don't let sound skip if going slow
9456                 if (r_refdef.scene.extraupdate)
9457                         S_ExtraUpdate ();
9458         }
9459
9460         if (!r_shadow_usingdeferredprepass)
9461         {
9462                 R_Shadow_DrawLights();
9463                 if (r_timereport_active)
9464                         R_TimeReport("rtlights");
9465         }
9466
9467         // don't let sound skip if going slow
9468         if (r_refdef.scene.extraupdate)
9469                 S_ExtraUpdate ();
9470
9471         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9472         {
9473                 R_DrawModelShadows();
9474                 R_ResetViewRendering3D();
9475                 // don't let sound skip if going slow
9476                 if (r_refdef.scene.extraupdate)
9477                         S_ExtraUpdate ();
9478         }
9479
9480         if (cl.csqc_vidvars.drawworld)
9481         {
9482                 if (cl_decals_newsystem.integer)
9483                 {
9484                         R_DrawModelDecals();
9485                         if (r_timereport_active)
9486                                 R_TimeReport("modeldecals");
9487                 }
9488                 else
9489                 {
9490                         R_DrawDecals();
9491                         if (r_timereport_active)
9492                                 R_TimeReport("decals");
9493                 }
9494
9495                 R_DrawParticles();
9496                 if (r_timereport_active)
9497                         R_TimeReport("particles");
9498
9499                 R_DrawExplosions();
9500                 if (r_timereport_active)
9501                         R_TimeReport("explosions");
9502
9503                 R_DrawLightningBeams();
9504                 if (r_timereport_active)
9505                         R_TimeReport("lightning");
9506         }
9507
9508         VM_CL_AddPolygonsToMeshQueue();
9509
9510         if (r_refdef.view.showdebug)
9511         {
9512                 if (cl_locs_show.integer)
9513                 {
9514                         R_DrawLocs();
9515                         if (r_timereport_active)
9516                                 R_TimeReport("showlocs");
9517                 }
9518
9519                 if (r_drawportals.integer)
9520                 {
9521                         R_DrawPortals();
9522                         if (r_timereport_active)
9523                                 R_TimeReport("portals");
9524                 }
9525
9526                 if (r_showbboxes.value > 0)
9527                 {
9528                         R_DrawEntityBBoxes();
9529                         if (r_timereport_active)
9530                                 R_TimeReport("bboxes");
9531                 }
9532         }
9533
9534         R_MeshQueue_RenderTransparent();
9535         if (r_timereport_active)
9536                 R_TimeReport("drawtrans");
9537
9538         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))
9539         {
9540                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9541                 if (r_timereport_active)
9542                         R_TimeReport("worlddebug");
9543                 R_DrawModelsDebug();
9544                 if (r_timereport_active)
9545                         R_TimeReport("modeldebug");
9546         }
9547
9548         if (cl.csqc_vidvars.drawworld)
9549         {
9550                 R_Shadow_DrawCoronas();
9551                 if (r_timereport_active)
9552                         R_TimeReport("coronas");
9553         }
9554
9555 #if 0
9556         {
9557                 GL_DepthTest(false);
9558                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9559                 GL_Color(1, 1, 1, 1);
9560                 qglBegin(GL_POLYGON);
9561                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9562                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9563                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9564                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9565                 qglEnd();
9566                 qglBegin(GL_POLYGON);
9567                 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]);
9568                 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]);
9569                 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]);
9570                 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]);
9571                 qglEnd();
9572                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9573         }
9574 #endif
9575
9576         // don't let sound skip if going slow
9577         if (r_refdef.scene.extraupdate)
9578                 S_ExtraUpdate ();
9579
9580         R_ResetViewRendering2D();
9581 }
9582
9583 static const unsigned short bboxelements[36] =
9584 {
9585         5, 1, 3, 5, 3, 7,
9586         6, 2, 0, 6, 0, 4,
9587         7, 3, 2, 7, 2, 6,
9588         4, 0, 1, 4, 1, 5,
9589         4, 5, 7, 4, 7, 6,
9590         1, 0, 2, 1, 2, 3,
9591 };
9592
9593 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9594 {
9595         int i;
9596         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9597
9598         RSurf_ActiveWorldEntity();
9599
9600         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9601         GL_DepthMask(false);
9602         GL_DepthRange(0, 1);
9603         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9604 //      R_Mesh_ResetTextureState();
9605
9606         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9607         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9608         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9609         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9610         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9611         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9612         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9613         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9614         R_FillColors(color4f, 8, cr, cg, cb, ca);
9615         if (r_refdef.fogenabled)
9616         {
9617                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9618                 {
9619                         f1 = RSurf_FogVertex(v);
9620                         f2 = 1 - f1;
9621                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9622                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9623                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9624                 }
9625         }
9626         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9627         R_Mesh_ResetTextureState();
9628         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9629         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9630 }
9631
9632 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9633 {
9634         int i;
9635         float color[4];
9636         prvm_edict_t *edict;
9637         prvm_prog_t *prog_save = prog;
9638
9639         // this function draws bounding boxes of server entities
9640         if (!sv.active)
9641                 return;
9642
9643         GL_CullFace(GL_NONE);
9644         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9645
9646         prog = 0;
9647         SV_VM_Begin();
9648         for (i = 0;i < numsurfaces;i++)
9649         {
9650                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9651                 switch ((int)edict->fields.server->solid)
9652                 {
9653                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9654                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9655                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9656                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9657                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9658                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9659                 }
9660                 color[3] *= r_showbboxes.value;
9661                 color[3] = bound(0, color[3], 1);
9662                 GL_DepthTest(!r_showdisabledepthtest.integer);
9663                 GL_CullFace(r_refdef.view.cullface_front);
9664                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9665         }
9666         SV_VM_End();
9667         prog = prog_save;
9668 }
9669
9670 static void R_DrawEntityBBoxes(void)
9671 {
9672         int i;
9673         prvm_edict_t *edict;
9674         vec3_t center;
9675         prvm_prog_t *prog_save = prog;
9676
9677         // this function draws bounding boxes of server entities
9678         if (!sv.active)
9679                 return;
9680
9681         prog = 0;
9682         SV_VM_Begin();
9683         for (i = 0;i < prog->num_edicts;i++)
9684         {
9685                 edict = PRVM_EDICT_NUM(i);
9686                 if (edict->priv.server->free)
9687                         continue;
9688                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9689                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9690                         continue;
9691                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9692                         continue;
9693                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9694                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9695         }
9696         SV_VM_End();
9697         prog = prog_save;
9698 }
9699
9700 static const int nomodelelement3i[24] =
9701 {
9702         5, 2, 0,
9703         5, 1, 2,
9704         5, 0, 3,
9705         5, 3, 1,
9706         0, 2, 4,
9707         2, 1, 4,
9708         3, 0, 4,
9709         1, 3, 4
9710 };
9711
9712 static const unsigned short nomodelelement3s[24] =
9713 {
9714         5, 2, 0,
9715         5, 1, 2,
9716         5, 0, 3,
9717         5, 3, 1,
9718         0, 2, 4,
9719         2, 1, 4,
9720         3, 0, 4,
9721         1, 3, 4
9722 };
9723
9724 static const float nomodelvertex3f[6*3] =
9725 {
9726         -16,   0,   0,
9727          16,   0,   0,
9728           0, -16,   0,
9729           0,  16,   0,
9730           0,   0, -16,
9731           0,   0,  16
9732 };
9733
9734 static const float nomodelcolor4f[6*4] =
9735 {
9736         0.0f, 0.0f, 0.5f, 1.0f,
9737         0.0f, 0.0f, 0.5f, 1.0f,
9738         0.0f, 0.5f, 0.0f, 1.0f,
9739         0.0f, 0.5f, 0.0f, 1.0f,
9740         0.5f, 0.0f, 0.0f, 1.0f,
9741         0.5f, 0.0f, 0.0f, 1.0f
9742 };
9743
9744 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9745 {
9746         int i;
9747         float f1, f2, *c;
9748         float color4f[6*4];
9749
9750         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);
9751
9752         // this is only called once per entity so numsurfaces is always 1, and
9753         // surfacelist is always {0}, so this code does not handle batches
9754
9755         if (rsurface.ent_flags & RENDER_ADDITIVE)
9756         {
9757                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9758                 GL_DepthMask(false);
9759         }
9760         else if (rsurface.colormod[3] < 1)
9761         {
9762                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9763                 GL_DepthMask(false);
9764         }
9765         else
9766         {
9767                 GL_BlendFunc(GL_ONE, GL_ZERO);
9768                 GL_DepthMask(true);
9769         }
9770         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9771         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9772         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9773         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9774         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9775         for (i = 0, c = color4f;i < 6;i++, c += 4)
9776         {
9777                 c[0] *= rsurface.colormod[0];
9778                 c[1] *= rsurface.colormod[1];
9779                 c[2] *= rsurface.colormod[2];
9780                 c[3] *= rsurface.colormod[3];
9781         }
9782         if (r_refdef.fogenabled)
9783         {
9784                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9785                 {
9786                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9787                         f2 = 1 - f1;
9788                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9789                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9790                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9791                 }
9792         }
9793 //      R_Mesh_ResetTextureState();
9794         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9795         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9796         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9797 }
9798
9799 void R_DrawNoModel(entity_render_t *ent)
9800 {
9801         vec3_t org;
9802         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9803         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9804                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9805         else
9806                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9807 }
9808
9809 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9810 {
9811         vec3_t right1, right2, diff, normal;
9812
9813         VectorSubtract (org2, org1, normal);
9814
9815         // calculate 'right' vector for start
9816         VectorSubtract (r_refdef.view.origin, org1, diff);
9817         CrossProduct (normal, diff, right1);
9818         VectorNormalize (right1);
9819
9820         // calculate 'right' vector for end
9821         VectorSubtract (r_refdef.view.origin, org2, diff);
9822         CrossProduct (normal, diff, right2);
9823         VectorNormalize (right2);
9824
9825         vert[ 0] = org1[0] + width * right1[0];
9826         vert[ 1] = org1[1] + width * right1[1];
9827         vert[ 2] = org1[2] + width * right1[2];
9828         vert[ 3] = org1[0] - width * right1[0];
9829         vert[ 4] = org1[1] - width * right1[1];
9830         vert[ 5] = org1[2] - width * right1[2];
9831         vert[ 6] = org2[0] - width * right2[0];
9832         vert[ 7] = org2[1] - width * right2[1];
9833         vert[ 8] = org2[2] - width * right2[2];
9834         vert[ 9] = org2[0] + width * right2[0];
9835         vert[10] = org2[1] + width * right2[1];
9836         vert[11] = org2[2] + width * right2[2];
9837 }
9838
9839 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)
9840 {
9841         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9842         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9843         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9844         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9845         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9846         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9847         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9848         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9849         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9850         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9851         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9852         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9853 }
9854
9855 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9856 {
9857         int i;
9858         float *vertex3f;
9859         float v[3];
9860         VectorSet(v, x, y, z);
9861         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9862                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9863                         break;
9864         if (i == mesh->numvertices)
9865         {
9866                 if (mesh->numvertices < mesh->maxvertices)
9867                 {
9868                         VectorCopy(v, vertex3f);
9869                         mesh->numvertices++;
9870                 }
9871                 return mesh->numvertices;
9872         }
9873         else
9874                 return i;
9875 }
9876
9877 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9878 {
9879         int i;
9880         int *e, element[3];
9881         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9882         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9883         e = mesh->element3i + mesh->numtriangles * 3;
9884         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9885         {
9886                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9887                 if (mesh->numtriangles < mesh->maxtriangles)
9888                 {
9889                         *e++ = element[0];
9890                         *e++ = element[1];
9891                         *e++ = element[2];
9892                         mesh->numtriangles++;
9893                 }
9894                 element[1] = element[2];
9895         }
9896 }
9897
9898 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9899 {
9900         int i;
9901         int *e, element[3];
9902         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9903         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9904         e = mesh->element3i + mesh->numtriangles * 3;
9905         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9906         {
9907                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9908                 if (mesh->numtriangles < mesh->maxtriangles)
9909                 {
9910                         *e++ = element[0];
9911                         *e++ = element[1];
9912                         *e++ = element[2];
9913                         mesh->numtriangles++;
9914                 }
9915                 element[1] = element[2];
9916         }
9917 }
9918
9919 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9920 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9921 {
9922         int planenum, planenum2;
9923         int w;
9924         int tempnumpoints;
9925         mplane_t *plane, *plane2;
9926         double maxdist;
9927         double temppoints[2][256*3];
9928         // figure out how large a bounding box we need to properly compute this brush
9929         maxdist = 0;
9930         for (w = 0;w < numplanes;w++)
9931                 maxdist = max(maxdist, fabs(planes[w].dist));
9932         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9933         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9934         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9935         {
9936                 w = 0;
9937                 tempnumpoints = 4;
9938                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9939                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9940                 {
9941                         if (planenum2 == planenum)
9942                                 continue;
9943                         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);
9944                         w = !w;
9945                 }
9946                 if (tempnumpoints < 3)
9947                         continue;
9948                 // generate elements forming a triangle fan for this polygon
9949                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9950         }
9951 }
9952
9953 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)
9954 {
9955         texturelayer_t *layer;
9956         layer = t->currentlayers + t->currentnumlayers++;
9957         layer->type = type;
9958         layer->depthmask = depthmask;
9959         layer->blendfunc1 = blendfunc1;
9960         layer->blendfunc2 = blendfunc2;
9961         layer->texture = texture;
9962         layer->texmatrix = *matrix;
9963         layer->color[0] = r;
9964         layer->color[1] = g;
9965         layer->color[2] = b;
9966         layer->color[3] = a;
9967 }
9968
9969 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9970 {
9971         if(parms[0] == 0 && parms[1] == 0)
9972                 return false;
9973         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9974                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9975                         return false;
9976         return true;
9977 }
9978
9979 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9980 {
9981         double index, f;
9982         index = parms[2] + r_refdef.scene.time * parms[3];
9983         index -= floor(index);
9984         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9985         {
9986         default:
9987         case Q3WAVEFUNC_NONE:
9988         case Q3WAVEFUNC_NOISE:
9989         case Q3WAVEFUNC_COUNT:
9990                 f = 0;
9991                 break;
9992         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9993         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9994         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9995         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9996         case Q3WAVEFUNC_TRIANGLE:
9997                 index *= 4;
9998                 f = index - floor(index);
9999                 if (index < 1)
10000                         f = f;
10001                 else if (index < 2)
10002                         f = 1 - f;
10003                 else if (index < 3)
10004                         f = -f;
10005                 else
10006                         f = -(1 - f);
10007                 break;
10008         }
10009         f = parms[0] + parms[1] * f;
10010         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10011                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10012         return (float) f;
10013 }
10014
10015 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10016 {
10017         int w, h, idx;
10018         float f;
10019         float tcmat[12];
10020         matrix4x4_t matrix, temp;
10021         switch(tcmod->tcmod)
10022         {
10023                 case Q3TCMOD_COUNT:
10024                 case Q3TCMOD_NONE:
10025                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10026                                 matrix = r_waterscrollmatrix;
10027                         else
10028                                 matrix = identitymatrix;
10029                         break;
10030                 case Q3TCMOD_ENTITYTRANSLATE:
10031                         // this is used in Q3 to allow the gamecode to control texcoord
10032                         // scrolling on the entity, which is not supported in darkplaces yet.
10033                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10034                         break;
10035                 case Q3TCMOD_ROTATE:
10036                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10037                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10038                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10039                         break;
10040                 case Q3TCMOD_SCALE:
10041                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10042                         break;
10043                 case Q3TCMOD_SCROLL:
10044                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10045                         break;
10046                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10047                         w = (int) tcmod->parms[0];
10048                         h = (int) tcmod->parms[1];
10049                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10050                         f = f - floor(f);
10051                         idx = (int) floor(f * w * h);
10052                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10053                         break;
10054                 case Q3TCMOD_STRETCH:
10055                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10056                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10057                         break;
10058                 case Q3TCMOD_TRANSFORM:
10059                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10060                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10061                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10062                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10063                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10064                         break;
10065                 case Q3TCMOD_TURBULENT:
10066                         // this is handled in the RSurf_PrepareVertices function
10067                         matrix = identitymatrix;
10068                         break;
10069         }
10070         temp = *texmatrix;
10071         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10072 }
10073
10074 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10075 {
10076         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10077         char name[MAX_QPATH];
10078         skinframe_t *skinframe;
10079         unsigned char pixels[296*194];
10080         strlcpy(cache->name, skinname, sizeof(cache->name));
10081         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10082         if (developer_loading.integer)
10083                 Con_Printf("loading %s\n", name);
10084         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10085         if (!skinframe || !skinframe->base)
10086         {
10087                 unsigned char *f;
10088                 fs_offset_t filesize;
10089                 skinframe = NULL;
10090                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10091                 if (f)
10092                 {
10093                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10094                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10095                         Mem_Free(f);
10096                 }
10097         }
10098         cache->skinframe = skinframe;
10099 }
10100
10101 texture_t *R_GetCurrentTexture(texture_t *t)
10102 {
10103         int i;
10104         const entity_render_t *ent = rsurface.entity;
10105         dp_model_t *model = ent->model;
10106         q3shaderinfo_layer_tcmod_t *tcmod;
10107
10108         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10109                 return t->currentframe;
10110         t->update_lastrenderframe = r_textureframe;
10111         t->update_lastrenderentity = (void *)ent;
10112
10113         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10114                 t->camera_entity = ent->entitynumber;
10115         else
10116                 t->camera_entity = 0;
10117
10118         // switch to an alternate material if this is a q1bsp animated material
10119         {
10120                 texture_t *texture = t;
10121                 int s = rsurface.ent_skinnum;
10122                 if ((unsigned int)s >= (unsigned int)model->numskins)
10123                         s = 0;
10124                 if (model->skinscenes)
10125                 {
10126                         if (model->skinscenes[s].framecount > 1)
10127                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10128                         else
10129                                 s = model->skinscenes[s].firstframe;
10130                 }
10131                 if (s > 0)
10132                         t = t + s * model->num_surfaces;
10133                 if (t->animated)
10134                 {
10135                         // use an alternate animation if the entity's frame is not 0,
10136                         // and only if the texture has an alternate animation
10137                         if (rsurface.ent_alttextures && t->anim_total[1])
10138                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10139                         else
10140                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10141                 }
10142                 texture->currentframe = t;
10143         }
10144
10145         // update currentskinframe to be a qw skin or animation frame
10146         if (rsurface.ent_qwskin >= 0)
10147         {
10148                 i = rsurface.ent_qwskin;
10149                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10150                 {
10151                         r_qwskincache_size = cl.maxclients;
10152                         if (r_qwskincache)
10153                                 Mem_Free(r_qwskincache);
10154                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10155                 }
10156                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10157                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10158                 t->currentskinframe = r_qwskincache[i].skinframe;
10159                 if (t->currentskinframe == NULL)
10160                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10161         }
10162         else if (t->numskinframes >= 2)
10163                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10164         if (t->backgroundnumskinframes >= 2)
10165                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10166
10167         t->currentmaterialflags = t->basematerialflags;
10168         t->currentalpha = rsurface.colormod[3];
10169         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10170                 t->currentalpha *= r_wateralpha.value;
10171         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10172                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10173         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10174                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10175         if (!(rsurface.ent_flags & RENDER_LIGHT))
10176                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10177         else if (FAKELIGHT_ENABLED)
10178         {
10179                         // no modellight if using fakelight for the map
10180         }
10181         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10182         {
10183                 // pick a model lighting mode
10184                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10185                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10186                 else
10187                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10188         }
10189         if (rsurface.ent_flags & RENDER_ADDITIVE)
10190                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10191         else if (t->currentalpha < 1)
10192                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10193         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10194                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10195         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10196                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10197         if (t->backgroundnumskinframes)
10198                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10199         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10200         {
10201                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10202                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10203         }
10204         else
10205                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10206         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10207                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10208
10209         // there is no tcmod
10210         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10211         {
10212                 t->currenttexmatrix = r_waterscrollmatrix;
10213                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10214         }
10215         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10216         {
10217                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10218                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10219         }
10220
10221         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10222                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10223         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10224                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10225
10226         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10227         if (t->currentskinframe->qpixels)
10228                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10229         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10230         if (!t->basetexture)
10231                 t->basetexture = r_texture_notexture;
10232         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10233         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10234         t->nmaptexture = t->currentskinframe->nmap;
10235         if (!t->nmaptexture)
10236                 t->nmaptexture = r_texture_blanknormalmap;
10237         t->glosstexture = r_texture_black;
10238         t->glowtexture = t->currentskinframe->glow;
10239         t->fogtexture = t->currentskinframe->fog;
10240         t->reflectmasktexture = t->currentskinframe->reflect;
10241         if (t->backgroundnumskinframes)
10242         {
10243                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10244                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10245                 t->backgroundglosstexture = r_texture_black;
10246                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10247                 if (!t->backgroundnmaptexture)
10248                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10249         }
10250         else
10251         {
10252                 t->backgroundbasetexture = r_texture_white;
10253                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10254                 t->backgroundglosstexture = r_texture_black;
10255                 t->backgroundglowtexture = NULL;
10256         }
10257         t->specularpower = r_shadow_glossexponent.value;
10258         // TODO: store reference values for these in the texture?
10259         t->specularscale = 0;
10260         if (r_shadow_gloss.integer > 0)
10261         {
10262                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10263                 {
10264                         if (r_shadow_glossintensity.value > 0)
10265                         {
10266                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10267                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10268                                 t->specularscale = r_shadow_glossintensity.value;
10269                         }
10270                 }
10271                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10272                 {
10273                         t->glosstexture = r_texture_white;
10274                         t->backgroundglosstexture = r_texture_white;
10275                         t->specularscale = r_shadow_gloss2intensity.value;
10276                         t->specularpower = r_shadow_gloss2exponent.value;
10277                 }
10278         }
10279         t->specularscale *= t->specularscalemod;
10280         t->specularpower *= t->specularpowermod;
10281
10282         // lightmaps mode looks bad with dlights using actual texturing, so turn
10283         // off the colormap and glossmap, but leave the normalmap on as it still
10284         // accurately represents the shading involved
10285         if (gl_lightmaps.integer)
10286         {
10287                 t->basetexture = r_texture_grey128;
10288                 t->pantstexture = r_texture_black;
10289                 t->shirttexture = r_texture_black;
10290                 t->nmaptexture = r_texture_blanknormalmap;
10291                 t->glosstexture = r_texture_black;
10292                 t->glowtexture = NULL;
10293                 t->fogtexture = NULL;
10294                 t->reflectmasktexture = NULL;
10295                 t->backgroundbasetexture = NULL;
10296                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10297                 t->backgroundglosstexture = r_texture_black;
10298                 t->backgroundglowtexture = NULL;
10299                 t->specularscale = 0;
10300                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10301         }
10302
10303         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10304         VectorClear(t->dlightcolor);
10305         t->currentnumlayers = 0;
10306         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10307         {
10308                 int blendfunc1, blendfunc2;
10309                 qboolean depthmask;
10310                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10311                 {
10312                         blendfunc1 = GL_SRC_ALPHA;
10313                         blendfunc2 = GL_ONE;
10314                 }
10315                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10316                 {
10317                         blendfunc1 = GL_SRC_ALPHA;
10318                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10319                 }
10320                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10321                 {
10322                         blendfunc1 = t->customblendfunc[0];
10323                         blendfunc2 = t->customblendfunc[1];
10324                 }
10325                 else
10326                 {
10327                         blendfunc1 = GL_ONE;
10328                         blendfunc2 = GL_ZERO;
10329                 }
10330                 // don't colormod evilblend textures
10331                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10332                         VectorSet(t->lightmapcolor, 1, 1, 1);
10333                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10334                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10335                 {
10336                         // fullbright is not affected by r_refdef.lightmapintensity
10337                         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]);
10338                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10339                                 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]);
10340                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10341                                 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]);
10342                 }
10343                 else
10344                 {
10345                         vec3_t ambientcolor;
10346                         float colorscale;
10347                         // set the color tint used for lights affecting this surface
10348                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10349                         colorscale = 2;
10350                         // q3bsp has no lightmap updates, so the lightstylevalue that
10351                         // would normally be baked into the lightmap must be
10352                         // applied to the color
10353                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10354                         if (model->type == mod_brushq3)
10355                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10356                         colorscale *= r_refdef.lightmapintensity;
10357                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10358                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10359                         // basic lit geometry
10360                         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]);
10361                         // add pants/shirt if needed
10362                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10363                                 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]);
10364                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10365                                 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]);
10366                         // now add ambient passes if needed
10367                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10368                         {
10369                                 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]);
10370                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10371                                         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]);
10372                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10373                                         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]);
10374                         }
10375                 }
10376                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10377                         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]);
10378                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10379                 {
10380                         // if this is opaque use alpha blend which will darken the earlier
10381                         // passes cheaply.
10382                         //
10383                         // if this is an alpha blended material, all the earlier passes
10384                         // were darkened by fog already, so we only need to add the fog
10385                         // color ontop through the fog mask texture
10386                         //
10387                         // if this is an additive blended material, all the earlier passes
10388                         // were darkened by fog already, and we should not add fog color
10389                         // (because the background was not darkened, there is no fog color
10390                         // that was lost behind it).
10391                         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]);
10392                 }
10393         }
10394
10395         return t->currentframe;
10396 }
10397
10398 rsurfacestate_t rsurface;
10399
10400 void RSurf_ActiveWorldEntity(void)
10401 {
10402         dp_model_t *model = r_refdef.scene.worldmodel;
10403         //if (rsurface.entity == r_refdef.scene.worldentity)
10404         //      return;
10405         rsurface.entity = r_refdef.scene.worldentity;
10406         rsurface.skeleton = NULL;
10407         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10408         rsurface.ent_skinnum = 0;
10409         rsurface.ent_qwskin = -1;
10410         rsurface.ent_shadertime = 0;
10411         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10412         rsurface.matrix = identitymatrix;
10413         rsurface.inversematrix = identitymatrix;
10414         rsurface.matrixscale = 1;
10415         rsurface.inversematrixscale = 1;
10416         R_EntityMatrix(&identitymatrix);
10417         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10418         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10419         rsurface.fograngerecip = r_refdef.fograngerecip;
10420         rsurface.fogheightfade = r_refdef.fogheightfade;
10421         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10422         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10423         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10424         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10425         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10426         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10427         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10428         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10429         rsurface.colormod[3] = 1;
10430         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);
10431         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10432         rsurface.frameblend[0].lerp = 1;
10433         rsurface.ent_alttextures = false;
10434         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10435         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10436         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10437         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10438         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10439         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10440         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10441         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10442         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10443         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10444         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10445         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10446         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10447         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10448         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10449         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10450         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10451         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10452         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10453         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10454         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10455         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10456         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10457         rsurface.modelelement3i = model->surfmesh.data_element3i;
10458         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10459         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10460         rsurface.modelelement3s = model->surfmesh.data_element3s;
10461         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10462         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10463         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10464         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10465         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10466         rsurface.modelsurfaces = model->data_surfaces;
10467         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10468         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10469         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10470         rsurface.modelgeneratedvertex = false;
10471         rsurface.batchgeneratedvertex = false;
10472         rsurface.batchfirstvertex = 0;
10473         rsurface.batchnumvertices = 0;
10474         rsurface.batchfirsttriangle = 0;
10475         rsurface.batchnumtriangles = 0;
10476         rsurface.batchvertex3f  = NULL;
10477         rsurface.batchvertex3f_vertexbuffer = NULL;
10478         rsurface.batchvertex3f_bufferoffset = 0;
10479         rsurface.batchsvector3f = NULL;
10480         rsurface.batchsvector3f_vertexbuffer = NULL;
10481         rsurface.batchsvector3f_bufferoffset = 0;
10482         rsurface.batchtvector3f = NULL;
10483         rsurface.batchtvector3f_vertexbuffer = NULL;
10484         rsurface.batchtvector3f_bufferoffset = 0;
10485         rsurface.batchnormal3f  = NULL;
10486         rsurface.batchnormal3f_vertexbuffer = NULL;
10487         rsurface.batchnormal3f_bufferoffset = 0;
10488         rsurface.batchlightmapcolor4f = NULL;
10489         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10490         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10491         rsurface.batchtexcoordtexture2f = NULL;
10492         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10493         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10494         rsurface.batchtexcoordlightmap2f = NULL;
10495         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10496         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10497         rsurface.batchvertexmesh = NULL;
10498         rsurface.batchvertexmeshbuffer = NULL;
10499         rsurface.batchvertex3fbuffer = NULL;
10500         rsurface.batchelement3i = NULL;
10501         rsurface.batchelement3i_indexbuffer = NULL;
10502         rsurface.batchelement3i_bufferoffset = 0;
10503         rsurface.batchelement3s = NULL;
10504         rsurface.batchelement3s_indexbuffer = NULL;
10505         rsurface.batchelement3s_bufferoffset = 0;
10506         rsurface.passcolor4f = NULL;
10507         rsurface.passcolor4f_vertexbuffer = NULL;
10508         rsurface.passcolor4f_bufferoffset = 0;
10509 }
10510
10511 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10512 {
10513         dp_model_t *model = ent->model;
10514         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10515         //      return;
10516         rsurface.entity = (entity_render_t *)ent;
10517         rsurface.skeleton = ent->skeleton;
10518         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10519         rsurface.ent_skinnum = ent->skinnum;
10520         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;
10521         rsurface.ent_shadertime = ent->shadertime;
10522         rsurface.ent_flags = ent->flags;
10523         rsurface.matrix = ent->matrix;
10524         rsurface.inversematrix = ent->inversematrix;
10525         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10526         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10527         R_EntityMatrix(&rsurface.matrix);
10528         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10529         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10530         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10531         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10532         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10533         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10534         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10535         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10536         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10537         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10538         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10539         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10540         rsurface.colormod[3] = ent->alpha;
10541         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10542         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10543         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10544         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10545         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10546         if (ent->model->brush.submodel && !prepass)
10547         {
10548                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10549                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10550         }
10551         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10552         {
10553                 if (ent->animcache_vertex3f)
10554                 {
10555                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10556                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10557                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10558                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10559                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10560                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10561                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10562                 }
10563                 else if (wanttangents)
10564                 {
10565                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10566                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10567                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10568                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10569                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10570                         rsurface.modelvertexmesh = NULL;
10571                         rsurface.modelvertexmeshbuffer = NULL;
10572                         rsurface.modelvertex3fbuffer = NULL;
10573                 }
10574                 else if (wantnormals)
10575                 {
10576                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10577                         rsurface.modelsvector3f = NULL;
10578                         rsurface.modeltvector3f = NULL;
10579                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10580                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10581                         rsurface.modelvertexmesh = NULL;
10582                         rsurface.modelvertexmeshbuffer = NULL;
10583                         rsurface.modelvertex3fbuffer = NULL;
10584                 }
10585                 else
10586                 {
10587                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10588                         rsurface.modelsvector3f = NULL;
10589                         rsurface.modeltvector3f = NULL;
10590                         rsurface.modelnormal3f = NULL;
10591                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10592                         rsurface.modelvertexmesh = NULL;
10593                         rsurface.modelvertexmeshbuffer = NULL;
10594                         rsurface.modelvertex3fbuffer = NULL;
10595                 }
10596                 rsurface.modelvertex3f_vertexbuffer = 0;
10597                 rsurface.modelvertex3f_bufferoffset = 0;
10598                 rsurface.modelsvector3f_vertexbuffer = 0;
10599                 rsurface.modelsvector3f_bufferoffset = 0;
10600                 rsurface.modeltvector3f_vertexbuffer = 0;
10601                 rsurface.modeltvector3f_bufferoffset = 0;
10602                 rsurface.modelnormal3f_vertexbuffer = 0;
10603                 rsurface.modelnormal3f_bufferoffset = 0;
10604                 rsurface.modelgeneratedvertex = true;
10605         }
10606         else
10607         {
10608                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10609                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10610                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10611                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10612                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10613                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10614                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10615                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10616                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10617                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10618                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10619                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10620                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10621                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10622                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10623                 rsurface.modelgeneratedvertex = false;
10624         }
10625         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10626         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10627         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10628         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10629         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10630         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10631         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10632         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10633         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10634         rsurface.modelelement3i = model->surfmesh.data_element3i;
10635         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10636         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10637         rsurface.modelelement3s = model->surfmesh.data_element3s;
10638         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10639         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10640         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10641         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10642         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10643         rsurface.modelsurfaces = model->data_surfaces;
10644         rsurface.batchgeneratedvertex = false;
10645         rsurface.batchfirstvertex = 0;
10646         rsurface.batchnumvertices = 0;
10647         rsurface.batchfirsttriangle = 0;
10648         rsurface.batchnumtriangles = 0;
10649         rsurface.batchvertex3f  = NULL;
10650         rsurface.batchvertex3f_vertexbuffer = NULL;
10651         rsurface.batchvertex3f_bufferoffset = 0;
10652         rsurface.batchsvector3f = NULL;
10653         rsurface.batchsvector3f_vertexbuffer = NULL;
10654         rsurface.batchsvector3f_bufferoffset = 0;
10655         rsurface.batchtvector3f = NULL;
10656         rsurface.batchtvector3f_vertexbuffer = NULL;
10657         rsurface.batchtvector3f_bufferoffset = 0;
10658         rsurface.batchnormal3f  = NULL;
10659         rsurface.batchnormal3f_vertexbuffer = NULL;
10660         rsurface.batchnormal3f_bufferoffset = 0;
10661         rsurface.batchlightmapcolor4f = NULL;
10662         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10663         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10664         rsurface.batchtexcoordtexture2f = NULL;
10665         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10666         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10667         rsurface.batchtexcoordlightmap2f = NULL;
10668         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10669         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10670         rsurface.batchvertexmesh = NULL;
10671         rsurface.batchvertexmeshbuffer = NULL;
10672         rsurface.batchvertex3fbuffer = NULL;
10673         rsurface.batchelement3i = NULL;
10674         rsurface.batchelement3i_indexbuffer = NULL;
10675         rsurface.batchelement3i_bufferoffset = 0;
10676         rsurface.batchelement3s = NULL;
10677         rsurface.batchelement3s_indexbuffer = NULL;
10678         rsurface.batchelement3s_bufferoffset = 0;
10679         rsurface.passcolor4f = NULL;
10680         rsurface.passcolor4f_vertexbuffer = NULL;
10681         rsurface.passcolor4f_bufferoffset = 0;
10682 }
10683
10684 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)
10685 {
10686         rsurface.entity = r_refdef.scene.worldentity;
10687         rsurface.skeleton = NULL;
10688         rsurface.ent_skinnum = 0;
10689         rsurface.ent_qwskin = -1;
10690         rsurface.ent_shadertime = shadertime;
10691         rsurface.ent_flags = entflags;
10692         rsurface.modelnumvertices = numvertices;
10693         rsurface.modelnumtriangles = numtriangles;
10694         rsurface.matrix = *matrix;
10695         rsurface.inversematrix = *inversematrix;
10696         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10697         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10698         R_EntityMatrix(&rsurface.matrix);
10699         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10700         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10701         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10702         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10703         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10704         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10705         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10706         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10707         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10708         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10709         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10710         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10711         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);
10712         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10713         rsurface.frameblend[0].lerp = 1;
10714         rsurface.ent_alttextures = false;
10715         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10716         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10717         if (wanttangents)
10718         {
10719                 rsurface.modelvertex3f = (float *)vertex3f;
10720                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10721                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10722                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10723         }
10724         else if (wantnormals)
10725         {
10726                 rsurface.modelvertex3f = (float *)vertex3f;
10727                 rsurface.modelsvector3f = NULL;
10728                 rsurface.modeltvector3f = NULL;
10729                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10730         }
10731         else
10732         {
10733                 rsurface.modelvertex3f = (float *)vertex3f;
10734                 rsurface.modelsvector3f = NULL;
10735                 rsurface.modeltvector3f = NULL;
10736                 rsurface.modelnormal3f = NULL;
10737         }
10738         rsurface.modelvertexmesh = NULL;
10739         rsurface.modelvertexmeshbuffer = NULL;
10740         rsurface.modelvertex3fbuffer = NULL;
10741         rsurface.modelvertex3f_vertexbuffer = 0;
10742         rsurface.modelvertex3f_bufferoffset = 0;
10743         rsurface.modelsvector3f_vertexbuffer = 0;
10744         rsurface.modelsvector3f_bufferoffset = 0;
10745         rsurface.modeltvector3f_vertexbuffer = 0;
10746         rsurface.modeltvector3f_bufferoffset = 0;
10747         rsurface.modelnormal3f_vertexbuffer = 0;
10748         rsurface.modelnormal3f_bufferoffset = 0;
10749         rsurface.modelgeneratedvertex = true;
10750         rsurface.modellightmapcolor4f  = (float *)color4f;
10751         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10752         rsurface.modellightmapcolor4f_bufferoffset = 0;
10753         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
10754         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10755         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10756         rsurface.modeltexcoordlightmap2f  = NULL;
10757         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10758         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10759         rsurface.modelelement3i = (int *)element3i;
10760         rsurface.modelelement3i_indexbuffer = NULL;
10761         rsurface.modelelement3i_bufferoffset = 0;
10762         rsurface.modelelement3s = (unsigned short *)element3s;
10763         rsurface.modelelement3s_indexbuffer = NULL;
10764         rsurface.modelelement3s_bufferoffset = 0;
10765         rsurface.modellightmapoffsets = NULL;
10766         rsurface.modelsurfaces = NULL;
10767         rsurface.batchgeneratedvertex = false;
10768         rsurface.batchfirstvertex = 0;
10769         rsurface.batchnumvertices = 0;
10770         rsurface.batchfirsttriangle = 0;
10771         rsurface.batchnumtriangles = 0;
10772         rsurface.batchvertex3f  = NULL;
10773         rsurface.batchvertex3f_vertexbuffer = NULL;
10774         rsurface.batchvertex3f_bufferoffset = 0;
10775         rsurface.batchsvector3f = NULL;
10776         rsurface.batchsvector3f_vertexbuffer = NULL;
10777         rsurface.batchsvector3f_bufferoffset = 0;
10778         rsurface.batchtvector3f = NULL;
10779         rsurface.batchtvector3f_vertexbuffer = NULL;
10780         rsurface.batchtvector3f_bufferoffset = 0;
10781         rsurface.batchnormal3f  = NULL;
10782         rsurface.batchnormal3f_vertexbuffer = NULL;
10783         rsurface.batchnormal3f_bufferoffset = 0;
10784         rsurface.batchlightmapcolor4f = NULL;
10785         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10786         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10787         rsurface.batchtexcoordtexture2f = NULL;
10788         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10789         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10790         rsurface.batchtexcoordlightmap2f = NULL;
10791         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10792         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10793         rsurface.batchvertexmesh = NULL;
10794         rsurface.batchvertexmeshbuffer = NULL;
10795         rsurface.batchvertex3fbuffer = NULL;
10796         rsurface.batchelement3i = NULL;
10797         rsurface.batchelement3i_indexbuffer = NULL;
10798         rsurface.batchelement3i_bufferoffset = 0;
10799         rsurface.batchelement3s = NULL;
10800         rsurface.batchelement3s_indexbuffer = NULL;
10801         rsurface.batchelement3s_bufferoffset = 0;
10802         rsurface.passcolor4f = NULL;
10803         rsurface.passcolor4f_vertexbuffer = NULL;
10804         rsurface.passcolor4f_bufferoffset = 0;
10805
10806         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10807         {
10808                 if ((wantnormals || wanttangents) && !normal3f)
10809                 {
10810                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10811                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10812                 }
10813                 if (wanttangents && !svector3f)
10814                 {
10815                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10816                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10817                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10818                 }
10819         }
10820 }
10821
10822 float RSurf_FogPoint(const float *v)
10823 {
10824         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10825         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10826         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10827         float FogHeightFade = r_refdef.fogheightfade;
10828         float fogfrac;
10829         unsigned int fogmasktableindex;
10830         if (r_refdef.fogplaneviewabove)
10831                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10832         else
10833                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10834         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10835         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10836 }
10837
10838 float RSurf_FogVertex(const float *v)
10839 {
10840         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10841         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10842         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10843         float FogHeightFade = rsurface.fogheightfade;
10844         float fogfrac;
10845         unsigned int fogmasktableindex;
10846         if (r_refdef.fogplaneviewabove)
10847                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10848         else
10849                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10850         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10851         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10852 }
10853
10854 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10855 {
10856         int i;
10857         for (i = 0;i < numelements;i++)
10858                 outelement3i[i] = inelement3i[i] + adjust;
10859 }
10860
10861 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10862 extern cvar_t gl_vbo;
10863 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10864 {
10865         int deformindex;
10866         int firsttriangle;
10867         int numtriangles;
10868         int firstvertex;
10869         int endvertex;
10870         int numvertices;
10871         int surfacefirsttriangle;
10872         int surfacenumtriangles;
10873         int surfacefirstvertex;
10874         int surfaceendvertex;
10875         int surfacenumvertices;
10876         int batchnumvertices;
10877         int batchnumtriangles;
10878         int needsupdate;
10879         int i, j;
10880         qboolean gaps;
10881         qboolean dynamicvertex;
10882         float amplitude;
10883         float animpos;
10884         float scale;
10885         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10886         float waveparms[4];
10887         q3shaderinfo_deform_t *deform;
10888         const msurface_t *surface, *firstsurface;
10889         r_vertexmesh_t *vertexmesh;
10890         if (!texturenumsurfaces)
10891                 return;
10892         // find vertex range of this surface batch
10893         gaps = false;
10894         firstsurface = texturesurfacelist[0];
10895         firsttriangle = firstsurface->num_firsttriangle;
10896         batchnumvertices = 0;
10897         batchnumtriangles = 0;
10898         firstvertex = endvertex = firstsurface->num_firstvertex;
10899         for (i = 0;i < texturenumsurfaces;i++)
10900         {
10901                 surface = texturesurfacelist[i];
10902                 if (surface != firstsurface + i)
10903                         gaps = true;
10904                 surfacefirstvertex = surface->num_firstvertex;
10905                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10906                 surfacenumvertices = surface->num_vertices;
10907                 surfacenumtriangles = surface->num_triangles;
10908                 if (firstvertex > surfacefirstvertex)
10909                         firstvertex = surfacefirstvertex;
10910                 if (endvertex < surfaceendvertex)
10911                         endvertex = surfaceendvertex;
10912                 batchnumvertices += surfacenumvertices;
10913                 batchnumtriangles += surfacenumtriangles;
10914         }
10915
10916         // we now know the vertex range used, and if there are any gaps in it
10917         rsurface.batchfirstvertex = firstvertex;
10918         rsurface.batchnumvertices = endvertex - firstvertex;
10919         rsurface.batchfirsttriangle = firsttriangle;
10920         rsurface.batchnumtriangles = batchnumtriangles;
10921
10922         // this variable holds flags for which properties have been updated that
10923         // may require regenerating vertexmesh array...
10924         needsupdate = 0;
10925
10926         // check if any dynamic vertex processing must occur
10927         dynamicvertex = false;
10928
10929         // if there is a chance of animated vertex colors, it's a dynamic batch
10930         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10931         {
10932                 dynamicvertex = true;
10933                 batchneed |= BATCHNEED_NOGAPS;
10934                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10935         }
10936
10937         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10938         {
10939                 switch (deform->deform)
10940                 {
10941                 default:
10942                 case Q3DEFORM_PROJECTIONSHADOW:
10943                 case Q3DEFORM_TEXT0:
10944                 case Q3DEFORM_TEXT1:
10945                 case Q3DEFORM_TEXT2:
10946                 case Q3DEFORM_TEXT3:
10947                 case Q3DEFORM_TEXT4:
10948                 case Q3DEFORM_TEXT5:
10949                 case Q3DEFORM_TEXT6:
10950                 case Q3DEFORM_TEXT7:
10951                 case Q3DEFORM_NONE:
10952                         break;
10953                 case Q3DEFORM_AUTOSPRITE:
10954                         dynamicvertex = true;
10955                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10956                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10957                         break;
10958                 case Q3DEFORM_AUTOSPRITE2:
10959                         dynamicvertex = true;
10960                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10961                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10962                         break;
10963                 case Q3DEFORM_NORMAL:
10964                         dynamicvertex = true;
10965                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10966                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10967                         break;
10968                 case Q3DEFORM_WAVE:
10969                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10970                                 break; // if wavefunc is a nop, ignore this transform
10971                         dynamicvertex = true;
10972                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10973                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10974                         break;
10975                 case Q3DEFORM_BULGE:
10976                         dynamicvertex = true;
10977                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10978                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10979                         break;
10980                 case Q3DEFORM_MOVE:
10981                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10982                                 break; // if wavefunc is a nop, ignore this transform
10983                         dynamicvertex = true;
10984                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10985                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
10986                         break;
10987                 }
10988         }
10989         switch(rsurface.texture->tcgen.tcgen)
10990         {
10991         default:
10992         case Q3TCGEN_TEXTURE:
10993                 break;
10994         case Q3TCGEN_LIGHTMAP:
10995                 dynamicvertex = true;
10996                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10997                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10998                 break;
10999         case Q3TCGEN_VECTOR:
11000                 dynamicvertex = true;
11001                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11002                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11003                 break;
11004         case Q3TCGEN_ENVIRONMENT:
11005                 dynamicvertex = true;
11006                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11007                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11008                 break;
11009         }
11010         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11011         {
11012                 dynamicvertex = true;
11013                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11014                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11015         }
11016
11017         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11018         {
11019                 dynamicvertex = true;
11020                 batchneed |= BATCHNEED_NOGAPS;
11021                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11022         }
11023
11024         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11025         {
11026                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11027                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11028                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11029                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11030                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11031                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11032                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11033         }
11034
11035         // when the model data has no vertex buffer (dynamic mesh), we need to
11036         // eliminate gaps
11037         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11038                 batchneed |= BATCHNEED_NOGAPS;
11039
11040         // if needsupdate, we have to do a dynamic vertex batch for sure
11041         if (needsupdate & batchneed)
11042                 dynamicvertex = true;
11043
11044         // see if we need to build vertexmesh from arrays
11045         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11046                 dynamicvertex = true;
11047
11048         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11049         // also some drivers strongly dislike firstvertex
11050         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11051                 dynamicvertex = true;
11052
11053         rsurface.batchvertex3f = rsurface.modelvertex3f;
11054         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11055         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11056         rsurface.batchsvector3f = rsurface.modelsvector3f;
11057         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11058         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11059         rsurface.batchtvector3f = rsurface.modeltvector3f;
11060         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11061         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11062         rsurface.batchnormal3f = rsurface.modelnormal3f;
11063         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11064         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11065         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11066         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11067         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11068         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11069         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11070         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11071         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11072         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11073         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11074         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11075         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11076         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11077         rsurface.batchelement3i = rsurface.modelelement3i;
11078         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11079         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11080         rsurface.batchelement3s = rsurface.modelelement3s;
11081         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11082         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11083
11084         // if any dynamic vertex processing has to occur in software, we copy the
11085         // entire surface list together before processing to rebase the vertices
11086         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11087         //
11088         // if any gaps exist and we do not have a static vertex buffer, we have to
11089         // copy the surface list together to avoid wasting upload bandwidth on the
11090         // vertices in the gaps.
11091         //
11092         // if gaps exist and we have a static vertex buffer, we still have to
11093         // combine the index buffer ranges into one dynamic index buffer.
11094         //
11095         // in all cases we end up with data that can be drawn in one call.
11096
11097         if (!dynamicvertex)
11098         {
11099                 // static vertex data, just set pointers...
11100                 rsurface.batchgeneratedvertex = false;
11101                 // if there are gaps, we want to build a combined index buffer,
11102                 // otherwise use the original static buffer with an appropriate offset
11103                 if (gaps)
11104                 {
11105                         // build a new triangle elements array for this batch
11106                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11107                         rsurface.batchfirsttriangle = 0;
11108                         numtriangles = 0;
11109                         for (i = 0;i < texturenumsurfaces;i++)
11110                         {
11111                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11112                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11113                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11114                                 numtriangles += surfacenumtriangles;
11115                         }
11116                         rsurface.batchelement3i_indexbuffer = NULL;
11117                         rsurface.batchelement3i_bufferoffset = 0;
11118                         rsurface.batchelement3s = NULL;
11119                         rsurface.batchelement3s_indexbuffer = NULL;
11120                         rsurface.batchelement3s_bufferoffset = 0;
11121                         if (endvertex <= 65536)
11122                         {
11123                                 // make a 16bit (unsigned short) index array if possible
11124                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11125                                 for (i = 0;i < numtriangles*3;i++)
11126                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11127                         }
11128                 }
11129                 return;
11130         }
11131
11132         // something needs software processing, do it for real...
11133         // we only directly handle separate array data in this case and then
11134         // generate interleaved data if needed...
11135         rsurface.batchgeneratedvertex = true;
11136
11137         // now copy the vertex data into a combined array and make an index array
11138         // (this is what Quake3 does all the time)
11139         //if (gaps || rsurface.batchfirstvertex)
11140         {
11141                 rsurface.batchvertex3fbuffer = NULL;
11142                 rsurface.batchvertexmesh = NULL;
11143                 rsurface.batchvertexmeshbuffer = NULL;
11144                 rsurface.batchvertex3f = NULL;
11145                 rsurface.batchvertex3f_vertexbuffer = NULL;
11146                 rsurface.batchvertex3f_bufferoffset = 0;
11147                 rsurface.batchsvector3f = NULL;
11148                 rsurface.batchsvector3f_vertexbuffer = NULL;
11149                 rsurface.batchsvector3f_bufferoffset = 0;
11150                 rsurface.batchtvector3f = NULL;
11151                 rsurface.batchtvector3f_vertexbuffer = NULL;
11152                 rsurface.batchtvector3f_bufferoffset = 0;
11153                 rsurface.batchnormal3f = NULL;
11154                 rsurface.batchnormal3f_vertexbuffer = NULL;
11155                 rsurface.batchnormal3f_bufferoffset = 0;
11156                 rsurface.batchlightmapcolor4f = NULL;
11157                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11158                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11159                 rsurface.batchtexcoordtexture2f = NULL;
11160                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11161                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11162                 rsurface.batchtexcoordlightmap2f = NULL;
11163                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11164                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11165                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11166                 rsurface.batchelement3i_indexbuffer = NULL;
11167                 rsurface.batchelement3i_bufferoffset = 0;
11168                 rsurface.batchelement3s = NULL;
11169                 rsurface.batchelement3s_indexbuffer = NULL;
11170                 rsurface.batchelement3s_bufferoffset = 0;
11171                 // we'll only be setting up certain arrays as needed
11172                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11173                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11174                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11175                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11176                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11177                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11178                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11179                 {
11180                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11181                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11182                 }
11183                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11184                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11185                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11186                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11187                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11188                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11189                 numvertices = 0;
11190                 numtriangles = 0;
11191                 for (i = 0;i < texturenumsurfaces;i++)
11192                 {
11193                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11194                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11195                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11196                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11197                         // copy only the data requested
11198                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11199                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11200                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11201                         {
11202                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11203                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11204                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11205                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11206                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11207                                 {
11208                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11209                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11210                                 }
11211                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11212                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11213                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11214                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11215                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11216                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11217                         }
11218                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11219                         numvertices += surfacenumvertices;
11220                         numtriangles += surfacenumtriangles;
11221                 }
11222
11223                 // generate a 16bit index array as well if possible
11224                 // (in general, dynamic batches fit)
11225                 if (numvertices <= 65536)
11226                 {
11227                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11228                         for (i = 0;i < numtriangles*3;i++)
11229                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11230                 }
11231
11232                 // since we've copied everything, the batch now starts at 0
11233                 rsurface.batchfirstvertex = 0;
11234                 rsurface.batchnumvertices = batchnumvertices;
11235                 rsurface.batchfirsttriangle = 0;
11236                 rsurface.batchnumtriangles = batchnumtriangles;
11237         }
11238
11239         // q1bsp surfaces rendered in vertex color mode have to have colors
11240         // calculated based on lightstyles
11241         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11242         {
11243                 // generate color arrays for the surfaces in this list
11244                 int c[4];
11245                 int scale;
11246                 int size3;
11247                 const int *offsets;
11248                 const unsigned char *lm;
11249                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11250                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11251                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11252                 numvertices = 0;
11253                 for (i = 0;i < texturenumsurfaces;i++)
11254                 {
11255                         surface = texturesurfacelist[i];
11256                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11257                         surfacenumvertices = surface->num_vertices;
11258                         if (surface->lightmapinfo->samples)
11259                         {
11260                                 for (j = 0;j < surfacenumvertices;j++)
11261                                 {
11262                                         lm = surface->lightmapinfo->samples + offsets[j];
11263                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11264                                         VectorScale(lm, scale, c);
11265                                         if (surface->lightmapinfo->styles[1] != 255)
11266                                         {
11267                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11268                                                 lm += size3;
11269                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11270                                                 VectorMA(c, scale, lm, c);
11271                                                 if (surface->lightmapinfo->styles[2] != 255)
11272                                                 {
11273                                                         lm += size3;
11274                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11275                                                         VectorMA(c, scale, lm, c);
11276                                                         if (surface->lightmapinfo->styles[3] != 255)
11277                                                         {
11278                                                                 lm += size3;
11279                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11280                                                                 VectorMA(c, scale, lm, c);
11281                                                         }
11282                                                 }
11283                                         }
11284                                         c[0] >>= 7;
11285                                         c[1] >>= 7;
11286                                         c[2] >>= 7;
11287                                         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);
11288                                         numvertices++;
11289                                 }
11290                         }
11291                         else
11292                         {
11293                                 for (j = 0;j < surfacenumvertices;j++)
11294                                 {
11295                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11296                                         numvertices++;
11297                                 }
11298                         }
11299                 }
11300         }
11301
11302         // if vertices are deformed (sprite flares and things in maps, possibly
11303         // water waves, bulges and other deformations), modify the copied vertices
11304         // in place
11305         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11306         {
11307                 switch (deform->deform)
11308                 {
11309                 default:
11310                 case Q3DEFORM_PROJECTIONSHADOW:
11311                 case Q3DEFORM_TEXT0:
11312                 case Q3DEFORM_TEXT1:
11313                 case Q3DEFORM_TEXT2:
11314                 case Q3DEFORM_TEXT3:
11315                 case Q3DEFORM_TEXT4:
11316                 case Q3DEFORM_TEXT5:
11317                 case Q3DEFORM_TEXT6:
11318                 case Q3DEFORM_TEXT7:
11319                 case Q3DEFORM_NONE:
11320                         break;
11321                 case Q3DEFORM_AUTOSPRITE:
11322                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11323                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11324                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11325                         VectorNormalize(newforward);
11326                         VectorNormalize(newright);
11327                         VectorNormalize(newup);
11328 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11329 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11330 //                      rsurface.batchvertex3f_bufferoffset = 0;
11331 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11332 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
11333 //                      rsurface.batchsvector3f_bufferoffset = 0;
11334 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11335 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
11336 //                      rsurface.batchtvector3f_bufferoffset = 0;
11337 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11338 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11339 //                      rsurface.batchnormal3f_bufferoffset = 0;
11340                         // a single autosprite surface can contain multiple sprites...
11341                         for (j = 0;j < batchnumvertices - 3;j += 4)
11342                         {
11343                                 VectorClear(center);
11344                                 for (i = 0;i < 4;i++)
11345                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11346                                 VectorScale(center, 0.25f, center);
11347                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11348                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11349                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11350                                 for (i = 0;i < 4;i++)
11351                                 {
11352                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11353                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11354                                 }
11355                         }
11356                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11357                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11358                         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);
11359                         break;
11360                 case Q3DEFORM_AUTOSPRITE2:
11361                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11362                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11363                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11364                         VectorNormalize(newforward);
11365                         VectorNormalize(newright);
11366                         VectorNormalize(newup);
11367 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11368 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11369 //                      rsurface.batchvertex3f_bufferoffset = 0;
11370                         {
11371                                 const float *v1, *v2;
11372                                 vec3_t start, end;
11373                                 float f, l;
11374                                 struct
11375                                 {
11376                                         float length2;
11377                                         const float *v1;
11378                                         const float *v2;
11379                                 }
11380                                 shortest[2];
11381                                 memset(shortest, 0, sizeof(shortest));
11382                                 // a single autosprite surface can contain multiple sprites...
11383                                 for (j = 0;j < batchnumvertices - 3;j += 4)
11384                                 {
11385                                         VectorClear(center);
11386                                         for (i = 0;i < 4;i++)
11387                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11388                                         VectorScale(center, 0.25f, center);
11389                                         // find the two shortest edges, then use them to define the
11390                                         // axis vectors for rotating around the central axis
11391                                         for (i = 0;i < 6;i++)
11392                                         {
11393                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11394                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11395                                                 l = VectorDistance2(v1, v2);
11396                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11397                                                 if (v1[2] != v2[2])
11398                                                         l += (1.0f / 1024.0f);
11399                                                 if (shortest[0].length2 > l || i == 0)
11400                                                 {
11401                                                         shortest[1] = shortest[0];
11402                                                         shortest[0].length2 = l;
11403                                                         shortest[0].v1 = v1;
11404                                                         shortest[0].v2 = v2;
11405                                                 }
11406                                                 else if (shortest[1].length2 > l || i == 1)
11407                                                 {
11408                                                         shortest[1].length2 = l;
11409                                                         shortest[1].v1 = v1;
11410                                                         shortest[1].v2 = v2;
11411                                                 }
11412                                         }
11413                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11414                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11415                                         // this calculates the right vector from the shortest edge
11416                                         // and the up vector from the edge midpoints
11417                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11418                                         VectorNormalize(right);
11419                                         VectorSubtract(end, start, up);
11420                                         VectorNormalize(up);
11421                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11422                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11423                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11424                                         VectorNegate(forward, forward);
11425                                         VectorReflect(forward, 0, up, forward);
11426                                         VectorNormalize(forward);
11427                                         CrossProduct(up, forward, newright);
11428                                         VectorNormalize(newright);
11429                                         // rotate the quad around the up axis vector, this is made
11430                                         // especially easy by the fact we know the quad is flat,
11431                                         // so we only have to subtract the center position and
11432                                         // measure distance along the right vector, and then
11433                                         // multiply that by the newright vector and add back the
11434                                         // center position
11435                                         // we also need to subtract the old position to undo the
11436                                         // displacement from the center, which we do with a
11437                                         // DotProduct, the subtraction/addition of center is also
11438                                         // optimized into DotProducts here
11439                                         l = DotProduct(right, center);
11440                                         for (i = 0;i < 4;i++)
11441                                         {
11442                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11443                                                 f = DotProduct(right, v1) - l;
11444                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11445                                         }
11446                                 }
11447                         }
11448                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11449                         {
11450 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11451 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
11452 //                              rsurface.batchnormal3f_bufferoffset = 0;
11453                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11454                         }
11455                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11456                         {
11457 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11458 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11459 //                              rsurface.batchsvector3f_bufferoffset = 0;
11460 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11461 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11462 //                              rsurface.batchtvector3f_bufferoffset = 0;
11463                                 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);
11464                         }
11465                         break;
11466                 case Q3DEFORM_NORMAL:
11467                         // deform the normals to make reflections wavey
11468                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11469                         rsurface.batchnormal3f_vertexbuffer = NULL;
11470                         rsurface.batchnormal3f_bufferoffset = 0;
11471                         for (j = 0;j < batchnumvertices;j++)
11472                         {
11473                                 float vertex[3];
11474                                 float *normal = rsurface.batchnormal3f + 3*j;
11475                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11476                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11477                                 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]);
11478                                 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]);
11479                                 VectorNormalize(normal);
11480                         }
11481                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11482                         {
11483 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11484 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11485 //                              rsurface.batchsvector3f_bufferoffset = 0;
11486 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11487 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11488 //                              rsurface.batchtvector3f_bufferoffset = 0;
11489                                 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);
11490                         }
11491                         break;
11492                 case Q3DEFORM_WAVE:
11493                         // deform vertex array to make wavey water and flags and such
11494                         waveparms[0] = deform->waveparms[0];
11495                         waveparms[1] = deform->waveparms[1];
11496                         waveparms[2] = deform->waveparms[2];
11497                         waveparms[3] = deform->waveparms[3];
11498                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11499                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11500                         // this is how a divisor of vertex influence on deformation
11501                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11502                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11503 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11504 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11505 //                      rsurface.batchvertex3f_bufferoffset = 0;
11506 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11507 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11508 //                      rsurface.batchnormal3f_bufferoffset = 0;
11509                         for (j = 0;j < batchnumvertices;j++)
11510                         {
11511                                 // if the wavefunc depends on time, evaluate it per-vertex
11512                                 if (waveparms[3])
11513                                 {
11514                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11515                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11516                                 }
11517                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11518                         }
11519                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11520                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11521                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11522                         {
11523 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11524 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11525 //                              rsurface.batchsvector3f_bufferoffset = 0;
11526 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11527 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11528 //                              rsurface.batchtvector3f_bufferoffset = 0;
11529                                 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);
11530                         }
11531                         break;
11532                 case Q3DEFORM_BULGE:
11533                         // deform vertex array to make the surface have moving bulges
11534 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11535 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11536 //                      rsurface.batchvertex3f_bufferoffset = 0;
11537 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11538 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11539 //                      rsurface.batchnormal3f_bufferoffset = 0;
11540                         for (j = 0;j < batchnumvertices;j++)
11541                         {
11542                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11543                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11544                         }
11545                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11546                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11547                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11548                         {
11549 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11550 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11551 //                              rsurface.batchsvector3f_bufferoffset = 0;
11552 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11553 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11554 //                              rsurface.batchtvector3f_bufferoffset = 0;
11555                                 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);
11556                         }
11557                         break;
11558                 case Q3DEFORM_MOVE:
11559                         // deform vertex array
11560                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11561                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11562                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11563                         VectorScale(deform->parms, scale, waveparms);
11564 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11565 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11566 //                      rsurface.batchvertex3f_bufferoffset = 0;
11567                         for (j = 0;j < batchnumvertices;j++)
11568                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11569                         break;
11570                 }
11571         }
11572
11573         // generate texcoords based on the chosen texcoord source
11574         switch(rsurface.texture->tcgen.tcgen)
11575         {
11576         default:
11577         case Q3TCGEN_TEXTURE:
11578                 break;
11579         case Q3TCGEN_LIGHTMAP:
11580 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11581 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11582 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11583                 if (rsurface.batchtexcoordlightmap2f)
11584                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11585                 break;
11586         case Q3TCGEN_VECTOR:
11587 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11588 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11589 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11590                 for (j = 0;j < batchnumvertices;j++)
11591                 {
11592                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11593                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11594                 }
11595                 break;
11596         case Q3TCGEN_ENVIRONMENT:
11597                 // make environment reflections using a spheremap
11598                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11599                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11600                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11601                 for (j = 0;j < batchnumvertices;j++)
11602                 {
11603                         // identical to Q3A's method, but executed in worldspace so
11604                         // carried models can be shiny too
11605
11606                         float viewer[3], d, reflected[3], worldreflected[3];
11607
11608                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11609                         // VectorNormalize(viewer);
11610
11611                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11612
11613                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11614                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11615                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11616                         // note: this is proportinal to viewer, so we can normalize later
11617
11618                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11619                         VectorNormalize(worldreflected);
11620
11621                         // note: this sphere map only uses world x and z!
11622                         // so positive and negative y will LOOK THE SAME.
11623                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11624                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11625                 }
11626                 break;
11627         }
11628         // the only tcmod that needs software vertex processing is turbulent, so
11629         // check for it here and apply the changes if needed
11630         // and we only support that as the first one
11631         // (handling a mixture of turbulent and other tcmods would be problematic
11632         //  without punting it entirely to a software path)
11633         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11634         {
11635                 amplitude = rsurface.texture->tcmods[0].parms[1];
11636                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11637 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11638 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11639 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11640                 for (j = 0;j < batchnumvertices;j++)
11641                 {
11642                         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);
11643                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11644                 }
11645         }
11646
11647         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11648         {
11649                 // convert the modified arrays to vertex structs
11650 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11651 //              rsurface.batchvertexmeshbuffer = NULL;
11652                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11653                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11654                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11655                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11656                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11657                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11658                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11659                 {
11660                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11661                         {
11662                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11663                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11664                         }
11665                 }
11666                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11667                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11668                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11669                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11670                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11671                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11672                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11673                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11674                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11675         }
11676 }
11677
11678 void RSurf_DrawBatch(void)
11679 {
11680         // sometimes a zero triangle surface (usually a degenerate patch) makes it
11681         // through the pipeline, killing it earlier in the pipeline would have
11682         // per-surface overhead rather than per-batch overhead, so it's best to
11683         // reject it here, before it hits glDraw.
11684         if (rsurface.batchnumtriangles == 0)
11685                 return;
11686 #if 0
11687         // batch debugging code
11688         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11689         {
11690                 int i;
11691                 int j;
11692                 int c;
11693                 const int *e;
11694                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11695                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11696                 {
11697                         c = e[i];
11698                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11699                         {
11700                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11701                                 {
11702                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11703                                                 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);
11704                                         break;
11705                                 }
11706                         }
11707                 }
11708         }
11709 #endif
11710         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);
11711 }
11712
11713 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11714 {
11715         // pick the closest matching water plane
11716         int planeindex, vertexindex, bestplaneindex = -1;
11717         float d, bestd;
11718         vec3_t vert;
11719         const float *v;
11720         r_waterstate_waterplane_t *p;
11721         qboolean prepared = false;
11722         bestd = 0;
11723         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11724         {
11725                 if(p->camera_entity != rsurface.texture->camera_entity)
11726                         continue;
11727                 d = 0;
11728                 if(!prepared)
11729                 {
11730                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11731                         prepared = true;
11732                         if(rsurface.batchnumvertices == 0)
11733                                 break;
11734                 }
11735                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11736                 {
11737                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11738                         d += fabs(PlaneDiff(vert, &p->plane));
11739                 }
11740                 if (bestd > d || bestplaneindex < 0)
11741                 {
11742                         bestd = d;
11743                         bestplaneindex = planeindex;
11744                 }
11745         }
11746         return bestplaneindex;
11747         // NOTE: this MAY return a totally unrelated water plane; we can ignore
11748         // this situation though, as it might be better to render single larger
11749         // batches with useless stuff (backface culled for example) than to
11750         // render multiple smaller batches
11751 }
11752
11753 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11754 {
11755         int i;
11756         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11757         rsurface.passcolor4f_vertexbuffer = 0;
11758         rsurface.passcolor4f_bufferoffset = 0;
11759         for (i = 0;i < rsurface.batchnumvertices;i++)
11760                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11761 }
11762
11763 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11764 {
11765         int i;
11766         float f;
11767         const float *v;
11768         const float *c;
11769         float *c2;
11770         if (rsurface.passcolor4f)
11771         {
11772                 // generate color arrays
11773                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11774                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11775                 rsurface.passcolor4f_vertexbuffer = 0;
11776                 rsurface.passcolor4f_bufferoffset = 0;
11777                 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)
11778                 {
11779                         f = RSurf_FogVertex(v);
11780                         c2[0] = c[0] * f;
11781                         c2[1] = c[1] * f;
11782                         c2[2] = c[2] * f;
11783                         c2[3] = c[3];
11784                 }
11785         }
11786         else
11787         {
11788                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11789                 rsurface.passcolor4f_vertexbuffer = 0;
11790                 rsurface.passcolor4f_bufferoffset = 0;
11791                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11792                 {
11793                         f = RSurf_FogVertex(v);
11794                         c2[0] = f;
11795                         c2[1] = f;
11796                         c2[2] = f;
11797                         c2[3] = 1;
11798                 }
11799         }
11800 }
11801
11802 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11803 {
11804         int i;
11805         float f;
11806         const float *v;
11807         const float *c;
11808         float *c2;
11809         if (!rsurface.passcolor4f)
11810                 return;
11811         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11812         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11813         rsurface.passcolor4f_vertexbuffer = 0;
11814         rsurface.passcolor4f_bufferoffset = 0;
11815         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)
11816         {
11817                 f = RSurf_FogVertex(v);
11818                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11819                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11820                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11821                 c2[3] = c[3];
11822         }
11823 }
11824
11825 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11826 {
11827         int i;
11828         const float *c;
11829         float *c2;
11830         if (!rsurface.passcolor4f)
11831                 return;
11832         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11833         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11834         rsurface.passcolor4f_vertexbuffer = 0;
11835         rsurface.passcolor4f_bufferoffset = 0;
11836         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11837         {
11838                 c2[0] = c[0] * r;
11839                 c2[1] = c[1] * g;
11840                 c2[2] = c[2] * b;
11841                 c2[3] = c[3] * a;
11842         }
11843 }
11844
11845 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11846 {
11847         int i;
11848         const float *c;
11849         float *c2;
11850         if (!rsurface.passcolor4f)
11851                 return;
11852         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11853         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11854         rsurface.passcolor4f_vertexbuffer = 0;
11855         rsurface.passcolor4f_bufferoffset = 0;
11856         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11857         {
11858                 c2[0] = c[0] + r_refdef.scene.ambient;
11859                 c2[1] = c[1] + r_refdef.scene.ambient;
11860                 c2[2] = c[2] + r_refdef.scene.ambient;
11861                 c2[3] = c[3];
11862         }
11863 }
11864
11865 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11866 {
11867         // TODO: optimize
11868         rsurface.passcolor4f = NULL;
11869         rsurface.passcolor4f_vertexbuffer = 0;
11870         rsurface.passcolor4f_bufferoffset = 0;
11871         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11872         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11873         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11874         GL_Color(r, g, b, a);
11875         R_Mesh_TexBind(0, rsurface.lightmaptexture);
11876         RSurf_DrawBatch();
11877 }
11878
11879 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11880 {
11881         // TODO: optimize applyfog && applycolor case
11882         // just apply fog if necessary, and tint the fog color array if necessary
11883         rsurface.passcolor4f = NULL;
11884         rsurface.passcolor4f_vertexbuffer = 0;
11885         rsurface.passcolor4f_bufferoffset = 0;
11886         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11887         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11888         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11889         GL_Color(r, g, b, a);
11890         RSurf_DrawBatch();
11891 }
11892
11893 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11894 {
11895         // TODO: optimize
11896         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11897         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11898         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11899         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11900         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11901         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11902         GL_Color(r, g, b, a);
11903         RSurf_DrawBatch();
11904 }
11905
11906 static void RSurf_DrawBatch_GL11_ClampColor(void)
11907 {
11908         int i;
11909         const float *c1;
11910         float *c2;
11911         if (!rsurface.passcolor4f)
11912                 return;
11913         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11914         {
11915                 c2[0] = bound(0.0f, c1[0], 1.0f);
11916                 c2[1] = bound(0.0f, c1[1], 1.0f);
11917                 c2[2] = bound(0.0f, c1[2], 1.0f);
11918                 c2[3] = bound(0.0f, c1[3], 1.0f);
11919         }
11920 }
11921
11922 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11923 {
11924         int i;
11925         float f;
11926         const float *v;
11927         const float *n;
11928         float *c;
11929         //vec3_t eyedir;
11930
11931         // fake shading
11932         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11933         rsurface.passcolor4f_vertexbuffer = 0;
11934         rsurface.passcolor4f_bufferoffset = 0;
11935         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)
11936         {
11937                 f = -DotProduct(r_refdef.view.forward, n);
11938                 f = max(0, f);
11939                 f = f * 0.85 + 0.15; // work around so stuff won't get black
11940                 f *= r_refdef.lightmapintensity;
11941                 Vector4Set(c, f, f, f, 1);
11942         }
11943 }
11944
11945 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11946 {
11947         RSurf_DrawBatch_GL11_ApplyFakeLight();
11948         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11949         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11950         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11951         GL_Color(r, g, b, a);
11952         RSurf_DrawBatch();
11953 }
11954
11955 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11956 {
11957         int i;
11958         float f;
11959         float alpha;
11960         const float *v;
11961         const float *n;
11962         float *c;
11963         vec3_t ambientcolor;
11964         vec3_t diffusecolor;
11965         vec3_t lightdir;
11966         // TODO: optimize
11967         // model lighting
11968         VectorCopy(rsurface.modellight_lightdir, lightdir);
11969         f = 0.5f * r_refdef.lightmapintensity;
11970         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11971         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11972         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11973         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11974         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11975         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11976         alpha = *a;
11977         if (VectorLength2(diffusecolor) > 0)
11978         {
11979                 // q3-style directional shading
11980                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11981                 rsurface.passcolor4f_vertexbuffer = 0;
11982                 rsurface.passcolor4f_bufferoffset = 0;
11983                 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)
11984                 {
11985                         if ((f = DotProduct(n, lightdir)) > 0)
11986                                 VectorMA(ambientcolor, f, diffusecolor, c);
11987                         else
11988                                 VectorCopy(ambientcolor, c);
11989                         c[3] = alpha;
11990                 }
11991                 *r = 1;
11992                 *g = 1;
11993                 *b = 1;
11994                 *a = 1;
11995                 *applycolor = false;
11996         }
11997         else
11998         {
11999                 *r = ambientcolor[0];
12000                 *g = ambientcolor[1];
12001                 *b = ambientcolor[2];
12002                 rsurface.passcolor4f = NULL;
12003                 rsurface.passcolor4f_vertexbuffer = 0;
12004                 rsurface.passcolor4f_bufferoffset = 0;
12005         }
12006 }
12007
12008 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12009 {
12010         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12011         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12012         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12013         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12014         GL_Color(r, g, b, a);
12015         RSurf_DrawBatch();
12016 }
12017
12018 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12019 {
12020         int i;
12021         float f;
12022         const float *v;
12023         float *c;
12024         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12025         {
12026                 f = 1 - RSurf_FogVertex(v);
12027                 c[0] = r;
12028                 c[1] = g;
12029                 c[2] = b;
12030                 c[3] = f * a;
12031         }
12032 }
12033
12034 void RSurf_SetupDepthAndCulling(void)
12035 {
12036         // submodels are biased to avoid z-fighting with world surfaces that they
12037         // may be exactly overlapping (avoids z-fighting artifacts on certain
12038         // doors and things in Quake maps)
12039         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12040         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12041         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12042         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12043 }
12044
12045 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12046 {
12047         // transparent sky would be ridiculous
12048         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12049                 return;
12050         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12051         skyrenderlater = true;
12052         RSurf_SetupDepthAndCulling();
12053         GL_DepthMask(true);
12054         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12055         // skymasking on them, and Quake3 never did sky masking (unlike
12056         // software Quake and software Quake2), so disable the sky masking
12057         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12058         // and skymasking also looks very bad when noclipping outside the
12059         // level, so don't use it then either.
12060         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12061         {
12062                 R_Mesh_ResetTextureState();
12063                 if (skyrendermasked)
12064                 {
12065                         R_SetupShader_DepthOrShadow();
12066                         // depth-only (masking)
12067                         GL_ColorMask(0,0,0,0);
12068                         // just to make sure that braindead drivers don't draw
12069                         // anything despite that colormask...
12070                         GL_BlendFunc(GL_ZERO, GL_ONE);
12071                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12072                         if (rsurface.batchvertex3fbuffer)
12073                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12074                         else
12075                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12076                 }
12077                 else
12078                 {
12079                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12080                         // fog sky
12081                         GL_BlendFunc(GL_ONE, GL_ZERO);
12082                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12083                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12084                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12085                 }
12086                 RSurf_DrawBatch();
12087                 if (skyrendermasked)
12088                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12089         }
12090         R_Mesh_ResetTextureState();
12091         GL_Color(1, 1, 1, 1);
12092 }
12093
12094 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12095 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12096 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12097 {
12098         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12099                 return;
12100         if (prepass)
12101         {
12102                 // render screenspace normalmap to texture
12103                 GL_DepthMask(true);
12104                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12105                 RSurf_DrawBatch();
12106                 return;
12107         }
12108
12109         // bind lightmap texture
12110
12111         // water/refraction/reflection/camera surfaces have to be handled specially
12112         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12113         {
12114                 int start, end, startplaneindex;
12115                 for (start = 0;start < texturenumsurfaces;start = end)
12116                 {
12117                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12118                         if(startplaneindex < 0)
12119                         {
12120                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12121                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12122                                 end = start + 1;
12123                                 continue;
12124                         }
12125                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12126                                 ;
12127                         // now that we have a batch using the same planeindex, render it
12128                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12129                         {
12130                                 // render water or distortion background
12131                                 GL_DepthMask(true);
12132                                 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));
12133                                 RSurf_DrawBatch();
12134                                 // blend surface on top
12135                                 GL_DepthMask(false);
12136                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12137                                 RSurf_DrawBatch();
12138                         }
12139                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12140                         {
12141                                 // render surface with reflection texture as input
12142                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12143                                 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));
12144                                 RSurf_DrawBatch();
12145                         }
12146                 }
12147                 return;
12148         }
12149
12150         // render surface batch normally
12151         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12152         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12153         RSurf_DrawBatch();
12154 }
12155
12156 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12157 {
12158         // OpenGL 1.3 path - anything not completely ancient
12159         qboolean applycolor;
12160         qboolean applyfog;
12161         int layerindex;
12162         const texturelayer_t *layer;
12163         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);
12164         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12165
12166         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12167         {
12168                 vec4_t layercolor;
12169                 int layertexrgbscale;
12170                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12171                 {
12172                         if (layerindex == 0)
12173                                 GL_AlphaTest(true);
12174                         else
12175                         {
12176                                 GL_AlphaTest(false);
12177                                 GL_DepthFunc(GL_EQUAL);
12178                         }
12179                 }
12180                 GL_DepthMask(layer->depthmask && writedepth);
12181                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12182                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12183                 {
12184                         layertexrgbscale = 4;
12185                         VectorScale(layer->color, 0.25f, layercolor);
12186                 }
12187                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12188                 {
12189                         layertexrgbscale = 2;
12190                         VectorScale(layer->color, 0.5f, layercolor);
12191                 }
12192                 else
12193                 {
12194                         layertexrgbscale = 1;
12195                         VectorScale(layer->color, 1.0f, layercolor);
12196                 }
12197                 layercolor[3] = layer->color[3];
12198                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12199                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12200                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12201                 switch (layer->type)
12202                 {
12203                 case TEXTURELAYERTYPE_LITTEXTURE:
12204                         // single-pass lightmapped texture with 2x rgbscale
12205                         R_Mesh_TexBind(0, r_texture_white);
12206                         R_Mesh_TexMatrix(0, NULL);
12207                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12208                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12209                         R_Mesh_TexBind(1, layer->texture);
12210                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12211                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12212                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12213                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12214                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12215                         else if (FAKELIGHT_ENABLED)
12216                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12217                         else if (rsurface.uselightmaptexture)
12218                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12219                         else
12220                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12221                         break;
12222                 case TEXTURELAYERTYPE_TEXTURE:
12223                         // singletexture unlit texture with transparency support
12224                         R_Mesh_TexBind(0, layer->texture);
12225                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12226                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12227                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12228                         R_Mesh_TexBind(1, 0);
12229                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12230                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12231                         break;
12232                 case TEXTURELAYERTYPE_FOG:
12233                         // singletexture fogging
12234                         if (layer->texture)
12235                         {
12236                                 R_Mesh_TexBind(0, layer->texture);
12237                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12238                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12239                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12240                         }
12241                         else
12242                         {
12243                                 R_Mesh_TexBind(0, 0);
12244                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12245                         }
12246                         R_Mesh_TexBind(1, 0);
12247                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12248                         // generate a color array for the fog pass
12249                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12250                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12251                         RSurf_DrawBatch();
12252                         break;
12253                 default:
12254                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12255                 }
12256         }
12257         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12258         {
12259                 GL_DepthFunc(GL_LEQUAL);
12260                 GL_AlphaTest(false);
12261         }
12262 }
12263
12264 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12265 {
12266         // OpenGL 1.1 - crusty old voodoo path
12267         qboolean applyfog;
12268         int layerindex;
12269         const texturelayer_t *layer;
12270         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);
12271         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12272
12273         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12274         {
12275                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12276                 {
12277                         if (layerindex == 0)
12278                                 GL_AlphaTest(true);
12279                         else
12280                         {
12281                                 GL_AlphaTest(false);
12282                                 GL_DepthFunc(GL_EQUAL);
12283                         }
12284                 }
12285                 GL_DepthMask(layer->depthmask && writedepth);
12286                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12287                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12288                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12289                 switch (layer->type)
12290                 {
12291                 case TEXTURELAYERTYPE_LITTEXTURE:
12292                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12293                         {
12294                                 // two-pass lit texture with 2x rgbscale
12295                                 // first the lightmap pass
12296                                 R_Mesh_TexBind(0, r_texture_white);
12297                                 R_Mesh_TexMatrix(0, NULL);
12298                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12299                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12300                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12301                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12302                                 else if (FAKELIGHT_ENABLED)
12303                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12304                                 else if (rsurface.uselightmaptexture)
12305                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12306                                 else
12307                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12308                                 // then apply the texture to it
12309                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12310                                 R_Mesh_TexBind(0, layer->texture);
12311                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12312                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12313                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12314                                 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);
12315                         }
12316                         else
12317                         {
12318                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12319                                 R_Mesh_TexBind(0, layer->texture);
12320                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12321                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12322                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12323                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12324                                         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);
12325                                 else
12326                                         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);
12327                         }
12328                         break;
12329                 case TEXTURELAYERTYPE_TEXTURE:
12330                         // singletexture unlit texture with transparency support
12331                         R_Mesh_TexBind(0, layer->texture);
12332                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12333                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12334                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12335                         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);
12336                         break;
12337                 case TEXTURELAYERTYPE_FOG:
12338                         // singletexture fogging
12339                         if (layer->texture)
12340                         {
12341                                 R_Mesh_TexBind(0, layer->texture);
12342                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12343                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12344                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12345                         }
12346                         else
12347                         {
12348                                 R_Mesh_TexBind(0, 0);
12349                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12350                         }
12351                         // generate a color array for the fog pass
12352                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12353                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12354                         RSurf_DrawBatch();
12355                         break;
12356                 default:
12357                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12358                 }
12359         }
12360         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12361         {
12362                 GL_DepthFunc(GL_LEQUAL);
12363                 GL_AlphaTest(false);
12364         }
12365 }
12366
12367 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12368 {
12369         int vi;
12370         int j;
12371         r_vertexgeneric_t *batchvertex;
12372         float c[4];
12373
12374 //      R_Mesh_ResetTextureState();
12375         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12376
12377         if(rsurface.texture && rsurface.texture->currentskinframe)
12378         {
12379                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12380                 c[3] *= rsurface.texture->currentalpha;
12381         }
12382         else
12383         {
12384                 c[0] = 1;
12385                 c[1] = 0;
12386                 c[2] = 1;
12387                 c[3] = 1;
12388         }
12389
12390         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12391         {
12392                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12393                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12394                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12395         }
12396
12397         // brighten it up (as texture value 127 means "unlit")
12398         c[0] *= 2 * r_refdef.view.colorscale;
12399         c[1] *= 2 * r_refdef.view.colorscale;
12400         c[2] *= 2 * r_refdef.view.colorscale;
12401
12402         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12403                 c[3] *= r_wateralpha.value;
12404
12405         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12406         {
12407                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12408                 GL_DepthMask(false);
12409         }
12410         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12411         {
12412                 GL_BlendFunc(GL_ONE, GL_ONE);
12413                 GL_DepthMask(false);
12414         }
12415         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12416         {
12417                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12418                 GL_DepthMask(false);
12419         }
12420         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12421         {
12422                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12423                 GL_DepthMask(false);
12424         }
12425         else
12426         {
12427                 GL_BlendFunc(GL_ONE, GL_ZERO);
12428                 GL_DepthMask(writedepth);
12429         }
12430
12431         if (r_showsurfaces.integer == 3)
12432         {
12433                 rsurface.passcolor4f = NULL;
12434
12435                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12436                 {
12437                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12438
12439                         rsurface.passcolor4f = NULL;
12440                         rsurface.passcolor4f_vertexbuffer = 0;
12441                         rsurface.passcolor4f_bufferoffset = 0;
12442                 }
12443                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12444                 {
12445                         qboolean applycolor = true;
12446                         float one = 1.0;
12447
12448                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12449
12450                         r_refdef.lightmapintensity = 1;
12451                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12452                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12453                 }
12454                 else if (FAKELIGHT_ENABLED)
12455                 {
12456                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12457
12458                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12459                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12460                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12461                 }
12462                 else
12463                 {
12464                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12465
12466                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12467                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12468                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12469                 }
12470
12471                 if(!rsurface.passcolor4f)
12472                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12473
12474                 RSurf_DrawBatch_GL11_ApplyAmbient();
12475                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12476                 if(r_refdef.fogenabled)
12477                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12478                 RSurf_DrawBatch_GL11_ClampColor();
12479
12480                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12481                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12482                 RSurf_DrawBatch();
12483         }
12484         else if (!r_refdef.view.showdebug)
12485         {
12486                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12487                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12488                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12489                 {
12490                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12491                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12492                 }
12493                 R_Mesh_PrepareVertices_Generic_Unlock();
12494                 RSurf_DrawBatch();
12495         }
12496         else if (r_showsurfaces.integer == 4)
12497         {
12498                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12499                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12500                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12501                 {
12502                         unsigned char c = vi << 3;
12503                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12504                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12505                 }
12506                 R_Mesh_PrepareVertices_Generic_Unlock();
12507                 RSurf_DrawBatch();
12508         }
12509         else if (r_showsurfaces.integer == 2)
12510         {
12511                 const int *e;
12512                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12513                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12514                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12515                 {
12516                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12517                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12518                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12519                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12520                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12521                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12522                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12523                 }
12524                 R_Mesh_PrepareVertices_Generic_Unlock();
12525                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12526         }
12527         else
12528         {
12529                 int texturesurfaceindex;
12530                 int k;
12531                 const msurface_t *surface;
12532                 unsigned char surfacecolor4ub[4];
12533                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12534                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12535                 vi = 0;
12536                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12537                 {
12538                         surface = texturesurfacelist[texturesurfaceindex];
12539                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12540                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12541                         for (j = 0;j < surface->num_vertices;j++)
12542                         {
12543                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12544                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12545                                 vi++;
12546                         }
12547                 }
12548                 R_Mesh_PrepareVertices_Generic_Unlock();
12549                 RSurf_DrawBatch();
12550         }
12551 }
12552
12553 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12554 {
12555         CHECKGLERROR
12556         RSurf_SetupDepthAndCulling();
12557         if (r_showsurfaces.integer)
12558         {
12559                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12560                 return;
12561         }
12562         switch (vid.renderpath)
12563         {
12564         case RENDERPATH_GL20:
12565         case RENDERPATH_D3D9:
12566         case RENDERPATH_D3D10:
12567         case RENDERPATH_D3D11:
12568         case RENDERPATH_SOFT:
12569         case RENDERPATH_GLES2:
12570                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12571                 break;
12572         case RENDERPATH_GL13:
12573                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12574                 break;
12575         case RENDERPATH_GL11:
12576                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12577                 break;
12578         }
12579         CHECKGLERROR
12580 }
12581
12582 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12583 {
12584         CHECKGLERROR
12585         RSurf_SetupDepthAndCulling();
12586         if (r_showsurfaces.integer)
12587         {
12588                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12589                 return;
12590         }
12591         switch (vid.renderpath)
12592         {
12593         case RENDERPATH_GL20:
12594         case RENDERPATH_D3D9:
12595         case RENDERPATH_D3D10:
12596         case RENDERPATH_D3D11:
12597         case RENDERPATH_SOFT:
12598         case RENDERPATH_GLES2:
12599                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12600                 break;
12601         case RENDERPATH_GL13:
12602                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12603                 break;
12604         case RENDERPATH_GL11:
12605                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12606                 break;
12607         }
12608         CHECKGLERROR
12609 }
12610
12611 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12612 {
12613         int i, j;
12614         int texturenumsurfaces, endsurface;
12615         texture_t *texture;
12616         const msurface_t *surface;
12617 #define MAXBATCH_TRANSPARENTSURFACES 256
12618         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12619
12620         // if the model is static it doesn't matter what value we give for
12621         // wantnormals and wanttangents, so this logic uses only rules applicable
12622         // to a model, knowing that they are meaningless otherwise
12623         if (ent == r_refdef.scene.worldentity)
12624                 RSurf_ActiveWorldEntity();
12625         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12626                 RSurf_ActiveModelEntity(ent, false, false, false);
12627         else
12628         {
12629                 switch (vid.renderpath)
12630                 {
12631                 case RENDERPATH_GL20:
12632                 case RENDERPATH_D3D9:
12633                 case RENDERPATH_D3D10:
12634                 case RENDERPATH_D3D11:
12635                 case RENDERPATH_SOFT:
12636                 case RENDERPATH_GLES2:
12637                         RSurf_ActiveModelEntity(ent, true, true, false);
12638                         break;
12639                 case RENDERPATH_GL13:
12640                 case RENDERPATH_GL11:
12641                         RSurf_ActiveModelEntity(ent, true, false, false);
12642                         break;
12643                 }
12644         }
12645
12646         if (r_transparentdepthmasking.integer)
12647         {
12648                 qboolean setup = false;
12649                 for (i = 0;i < numsurfaces;i = j)
12650                 {
12651                         j = i + 1;
12652                         surface = rsurface.modelsurfaces + surfacelist[i];
12653                         texture = surface->texture;
12654                         rsurface.texture = R_GetCurrentTexture(texture);
12655                         rsurface.lightmaptexture = NULL;
12656                         rsurface.deluxemaptexture = NULL;
12657                         rsurface.uselightmaptexture = false;
12658                         // scan ahead until we find a different texture
12659                         endsurface = min(i + 1024, numsurfaces);
12660                         texturenumsurfaces = 0;
12661                         texturesurfacelist[texturenumsurfaces++] = surface;
12662                         for (;j < endsurface;j++)
12663                         {
12664                                 surface = rsurface.modelsurfaces + surfacelist[j];
12665                                 if (texture != surface->texture)
12666                                         break;
12667                                 texturesurfacelist[texturenumsurfaces++] = surface;
12668                         }
12669                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12670                                 continue;
12671                         // render the range of surfaces as depth
12672                         if (!setup)
12673                         {
12674                                 setup = true;
12675                                 GL_ColorMask(0,0,0,0);
12676                                 GL_Color(1,1,1,1);
12677                                 GL_DepthTest(true);
12678                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12679                                 GL_DepthMask(true);
12680 //                              R_Mesh_ResetTextureState();
12681                                 R_SetupShader_DepthOrShadow();
12682                         }
12683                         RSurf_SetupDepthAndCulling();
12684                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12685                         if (rsurface.batchvertex3fbuffer)
12686                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12687                         else
12688                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12689                         RSurf_DrawBatch();
12690                 }
12691                 if (setup)
12692                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12693         }
12694
12695         for (i = 0;i < numsurfaces;i = j)
12696         {
12697                 j = i + 1;
12698                 surface = rsurface.modelsurfaces + surfacelist[i];
12699                 texture = surface->texture;
12700                 rsurface.texture = R_GetCurrentTexture(texture);
12701                 // scan ahead until we find a different texture
12702                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12703                 texturenumsurfaces = 0;
12704                 texturesurfacelist[texturenumsurfaces++] = surface;
12705                 if(FAKELIGHT_ENABLED)
12706                 {
12707                         rsurface.lightmaptexture = NULL;
12708                         rsurface.deluxemaptexture = NULL;
12709                         rsurface.uselightmaptexture = false;
12710                         for (;j < endsurface;j++)
12711                         {
12712                                 surface = rsurface.modelsurfaces + surfacelist[j];
12713                                 if (texture != surface->texture)
12714                                         break;
12715                                 texturesurfacelist[texturenumsurfaces++] = surface;
12716                         }
12717                 }
12718                 else
12719                 {
12720                         rsurface.lightmaptexture = surface->lightmaptexture;
12721                         rsurface.deluxemaptexture = surface->deluxemaptexture;
12722                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12723                         for (;j < endsurface;j++)
12724                         {
12725                                 surface = rsurface.modelsurfaces + surfacelist[j];
12726                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12727                                         break;
12728                                 texturesurfacelist[texturenumsurfaces++] = surface;
12729                         }
12730                 }
12731                 // render the range of surfaces
12732                 if (ent == r_refdef.scene.worldentity)
12733                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12734                 else
12735                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12736         }
12737         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12738 }
12739
12740 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12741 {
12742         // transparent surfaces get pushed off into the transparent queue
12743         int surfacelistindex;
12744         const msurface_t *surface;
12745         vec3_t tempcenter, center;
12746         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12747         {
12748                 surface = texturesurfacelist[surfacelistindex];
12749                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12750                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12751                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12752                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12753                 if (queueentity->transparent_offset) // transparent offset
12754                 {
12755                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12756                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12757                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12758                 }
12759                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12760         }
12761 }
12762
12763 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12764 {
12765         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12766                 return;
12767         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12768                 return;
12769         RSurf_SetupDepthAndCulling();
12770         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12771         if (rsurface.batchvertex3fbuffer)
12772                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12773         else
12774                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12775         RSurf_DrawBatch();
12776 }
12777
12778 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12779 {
12780         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12781         CHECKGLERROR
12782         if (depthonly)
12783                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12784         else if (prepass)
12785         {
12786                 if (!rsurface.texture->currentnumlayers)
12787                         return;
12788                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12789                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12790                 else
12791                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12792         }
12793         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12794                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12795         else if (!rsurface.texture->currentnumlayers)
12796                 return;
12797         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12798         {
12799                 // in the deferred case, transparent surfaces were queued during prepass
12800                 if (!r_shadow_usingdeferredprepass)
12801                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12802         }
12803         else
12804         {
12805                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12806                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12807         }
12808         CHECKGLERROR
12809 }
12810
12811 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12812 {
12813         int i, j;
12814         texture_t *texture;
12815         R_FrameData_SetMark();
12816         // break the surface list down into batches by texture and use of lightmapping
12817         for (i = 0;i < numsurfaces;i = j)
12818         {
12819                 j = i + 1;
12820                 // texture is the base texture pointer, rsurface.texture is the
12821                 // current frame/skin the texture is directing us to use (for example
12822                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12823                 // use skin 1 instead)
12824                 texture = surfacelist[i]->texture;
12825                 rsurface.texture = R_GetCurrentTexture(texture);
12826                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12827                 {
12828                         // if this texture is not the kind we want, skip ahead to the next one
12829                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12830                                 ;
12831                         continue;
12832                 }
12833                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12834                 {
12835                         rsurface.lightmaptexture = NULL;
12836                         rsurface.deluxemaptexture = NULL;
12837                         rsurface.uselightmaptexture = false;
12838                         // simply scan ahead until we find a different texture or lightmap state
12839                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12840                                 ;
12841                 }
12842                 else
12843                 {
12844                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12845                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12846                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12847                         // simply scan ahead until we find a different texture or lightmap state
12848                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12849                                 ;
12850                 }
12851                 // render the range of surfaces
12852                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12853         }
12854         R_FrameData_ReturnToMark();
12855 }
12856
12857 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12858 {
12859         CHECKGLERROR
12860         if (depthonly)
12861                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12862         else if (prepass)
12863         {
12864                 if (!rsurface.texture->currentnumlayers)
12865                         return;
12866                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12867                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12868                 else
12869                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12870         }
12871         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12872                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12873         else if (!rsurface.texture->currentnumlayers)
12874                 return;
12875         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12876         {
12877                 // in the deferred case, transparent surfaces were queued during prepass
12878                 if (!r_shadow_usingdeferredprepass)
12879                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12880         }
12881         else
12882         {
12883                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12884                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12885         }
12886         CHECKGLERROR
12887 }
12888
12889 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12890 {
12891         int i, j;
12892         texture_t *texture;
12893         R_FrameData_SetMark();
12894         // break the surface list down into batches by texture and use of lightmapping
12895         for (i = 0;i < numsurfaces;i = j)
12896         {
12897                 j = i + 1;
12898                 // texture is the base texture pointer, rsurface.texture is the
12899                 // current frame/skin the texture is directing us to use (for example
12900                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12901                 // use skin 1 instead)
12902                 texture = surfacelist[i]->texture;
12903                 rsurface.texture = R_GetCurrentTexture(texture);
12904                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12905                 {
12906                         // if this texture is not the kind we want, skip ahead to the next one
12907                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12908                                 ;
12909                         continue;
12910                 }
12911                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12912                 {
12913                         rsurface.lightmaptexture = NULL;
12914                         rsurface.deluxemaptexture = NULL;
12915                         rsurface.uselightmaptexture = false;
12916                         // simply scan ahead until we find a different texture or lightmap state
12917                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12918                                 ;
12919                 }
12920                 else
12921                 {
12922                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12923                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12924                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12925                         // simply scan ahead until we find a different texture or lightmap state
12926                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12927                                 ;
12928                 }
12929                 // render the range of surfaces
12930                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12931         }
12932         R_FrameData_ReturnToMark();
12933 }
12934
12935 float locboxvertex3f[6*4*3] =
12936 {
12937         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12938         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12939         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12940         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12941         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12942         1,0,0, 0,0,0, 0,1,0, 1,1,0
12943 };
12944
12945 unsigned short locboxelements[6*2*3] =
12946 {
12947          0, 1, 2, 0, 2, 3,
12948          4, 5, 6, 4, 6, 7,
12949          8, 9,10, 8,10,11,
12950         12,13,14, 12,14,15,
12951         16,17,18, 16,18,19,
12952         20,21,22, 20,22,23
12953 };
12954
12955 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12956 {
12957         int i, j;
12958         cl_locnode_t *loc = (cl_locnode_t *)ent;
12959         vec3_t mins, size;
12960         float vertex3f[6*4*3];
12961         CHECKGLERROR
12962         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12963         GL_DepthMask(false);
12964         GL_DepthRange(0, 1);
12965         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12966         GL_DepthTest(true);
12967         GL_CullFace(GL_NONE);
12968         R_EntityMatrix(&identitymatrix);
12969
12970 //      R_Mesh_ResetTextureState();
12971
12972         i = surfacelist[0];
12973         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12974                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12975                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12976                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12977
12978         if (VectorCompare(loc->mins, loc->maxs))
12979         {
12980                 VectorSet(size, 2, 2, 2);
12981                 VectorMA(loc->mins, -0.5f, size, mins);
12982         }
12983         else
12984         {
12985                 VectorCopy(loc->mins, mins);
12986                 VectorSubtract(loc->maxs, loc->mins, size);
12987         }
12988
12989         for (i = 0;i < 6*4*3;)
12990                 for (j = 0;j < 3;j++, i++)
12991                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12992
12993         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12994         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12995         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12996 }
12997
12998 void R_DrawLocs(void)
12999 {
13000         int index;
13001         cl_locnode_t *loc, *nearestloc;
13002         vec3_t center;
13003         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13004         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13005         {
13006                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13007                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13008         }
13009 }
13010
13011 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13012 {
13013         if (decalsystem->decals)
13014                 Mem_Free(decalsystem->decals);
13015         memset(decalsystem, 0, sizeof(*decalsystem));
13016 }
13017
13018 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)
13019 {
13020         tridecal_t *decal;
13021         tridecal_t *decals;
13022         int i;
13023
13024         // expand or initialize the system
13025         if (decalsystem->maxdecals <= decalsystem->numdecals)
13026         {
13027                 decalsystem_t old = *decalsystem;
13028                 qboolean useshortelements;
13029                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13030                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13031                 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)));
13032                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13033                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13034                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13035                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13036                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13037                 if (decalsystem->numdecals)
13038                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13039                 if (old.decals)
13040                         Mem_Free(old.decals);
13041                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13042                         decalsystem->element3i[i] = i;
13043                 if (useshortelements)
13044                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13045                                 decalsystem->element3s[i] = i;
13046         }
13047
13048         // grab a decal and search for another free slot for the next one
13049         decals = decalsystem->decals;
13050         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13051         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13052                 ;
13053         decalsystem->freedecal = i;
13054         if (decalsystem->numdecals <= i)
13055                 decalsystem->numdecals = i + 1;
13056
13057         // initialize the decal
13058         decal->lived = 0;
13059         decal->triangleindex = triangleindex;
13060         decal->surfaceindex = surfaceindex;
13061         decal->decalsequence = decalsequence;
13062         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13063         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13064         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13065         decal->color4ub[0][3] = 255;
13066         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13067         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13068         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13069         decal->color4ub[1][3] = 255;
13070         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13071         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13072         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13073         decal->color4ub[2][3] = 255;
13074         decal->vertex3f[0][0] = v0[0];
13075         decal->vertex3f[0][1] = v0[1];
13076         decal->vertex3f[0][2] = v0[2];
13077         decal->vertex3f[1][0] = v1[0];
13078         decal->vertex3f[1][1] = v1[1];
13079         decal->vertex3f[1][2] = v1[2];
13080         decal->vertex3f[2][0] = v2[0];
13081         decal->vertex3f[2][1] = v2[1];
13082         decal->vertex3f[2][2] = v2[2];
13083         decal->texcoord2f[0][0] = t0[0];
13084         decal->texcoord2f[0][1] = t0[1];
13085         decal->texcoord2f[1][0] = t1[0];
13086         decal->texcoord2f[1][1] = t1[1];
13087         decal->texcoord2f[2][0] = t2[0];
13088         decal->texcoord2f[2][1] = t2[1];
13089 }
13090
13091 extern cvar_t cl_decals_bias;
13092 extern cvar_t cl_decals_models;
13093 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13094 // baseparms, parms, temps
13095 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)
13096 {
13097         int cornerindex;
13098         int index;
13099         float v[9][3];
13100         const float *vertex3f;
13101         int numpoints;
13102         float points[2][9][3];
13103         float temp[3];
13104         float tc[9][2];
13105         float f;
13106         float c[9][4];
13107         const int *e;
13108
13109         e = rsurface.modelelement3i + 3*triangleindex;
13110
13111         vertex3f = rsurface.modelvertex3f;
13112
13113         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13114         {
13115                 index = 3*e[cornerindex];
13116                 VectorCopy(vertex3f + index, v[cornerindex]);
13117         }
13118         // cull backfaces
13119         //TriangleNormal(v[0], v[1], v[2], normal);
13120         //if (DotProduct(normal, localnormal) < 0.0f)
13121         //      continue;
13122         // clip by each of the box planes formed from the projection matrix
13123         // if anything survives, we emit the decal
13124         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]);
13125         if (numpoints < 3)
13126                 return;
13127         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]);
13128         if (numpoints < 3)
13129                 return;
13130         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]);
13131         if (numpoints < 3)
13132                 return;
13133         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]);
13134         if (numpoints < 3)
13135                 return;
13136         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]);
13137         if (numpoints < 3)
13138                 return;
13139         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]);
13140         if (numpoints < 3)
13141                 return;
13142         // some part of the triangle survived, so we have to accept it...
13143         if (dynamic)
13144         {
13145                 // dynamic always uses the original triangle
13146                 numpoints = 3;
13147                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13148                 {
13149                         index = 3*e[cornerindex];
13150                         VectorCopy(vertex3f + index, v[cornerindex]);
13151                 }
13152         }
13153         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13154         {
13155                 // convert vertex positions to texcoords
13156                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13157                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13158                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13159                 // calculate distance fade from the projection origin
13160                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13161                 f = bound(0.0f, f, 1.0f);
13162                 c[cornerindex][0] = r * f;
13163                 c[cornerindex][1] = g * f;
13164                 c[cornerindex][2] = b * f;
13165                 c[cornerindex][3] = 1.0f;
13166                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13167         }
13168         if (dynamic)
13169                 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);
13170         else
13171                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13172                         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);
13173 }
13174 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)
13175 {
13176         matrix4x4_t projection;
13177         decalsystem_t *decalsystem;
13178         qboolean dynamic;
13179         dp_model_t *model;
13180         const msurface_t *surface;
13181         const msurface_t *surfaces;
13182         const int *surfacelist;
13183         const texture_t *texture;
13184         int numtriangles;
13185         int numsurfacelist;
13186         int surfacelistindex;
13187         int surfaceindex;
13188         int triangleindex;
13189         float localorigin[3];
13190         float localnormal[3];
13191         float localmins[3];
13192         float localmaxs[3];
13193         float localsize;
13194         //float normal[3];
13195         float planes[6][4];
13196         float angles[3];
13197         bih_t *bih;
13198         int bih_triangles_count;
13199         int bih_triangles[256];
13200         int bih_surfaces[256];
13201
13202         decalsystem = &ent->decalsystem;
13203         model = ent->model;
13204         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13205         {
13206                 R_DecalSystem_Reset(&ent->decalsystem);
13207                 return;
13208         }
13209
13210         if (!model->brush.data_leafs && !cl_decals_models.integer)
13211         {
13212                 if (decalsystem->model)
13213                         R_DecalSystem_Reset(decalsystem);
13214                 return;
13215         }
13216
13217         if (decalsystem->model != model)
13218                 R_DecalSystem_Reset(decalsystem);
13219         decalsystem->model = model;
13220
13221         RSurf_ActiveModelEntity(ent, false, false, false);
13222
13223         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13224         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13225         VectorNormalize(localnormal);
13226         localsize = worldsize*rsurface.inversematrixscale;
13227         localmins[0] = localorigin[0] - localsize;
13228         localmins[1] = localorigin[1] - localsize;
13229         localmins[2] = localorigin[2] - localsize;
13230         localmaxs[0] = localorigin[0] + localsize;
13231         localmaxs[1] = localorigin[1] + localsize;
13232         localmaxs[2] = localorigin[2] + localsize;
13233
13234         //VectorCopy(localnormal, planes[4]);
13235         //VectorVectors(planes[4], planes[2], planes[0]);
13236         AnglesFromVectors(angles, localnormal, NULL, false);
13237         AngleVectors(angles, planes[0], planes[2], planes[4]);
13238         VectorNegate(planes[0], planes[1]);
13239         VectorNegate(planes[2], planes[3]);
13240         VectorNegate(planes[4], planes[5]);
13241         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13242         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13243         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13244         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13245         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13246         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13247
13248 #if 1
13249 // works
13250 {
13251         matrix4x4_t forwardprojection;
13252         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13253         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13254 }
13255 #else
13256 // broken
13257 {
13258         float projectionvector[4][3];
13259         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13260         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13261         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13262         projectionvector[0][0] = planes[0][0] * ilocalsize;
13263         projectionvector[0][1] = planes[1][0] * ilocalsize;
13264         projectionvector[0][2] = planes[2][0] * ilocalsize;
13265         projectionvector[1][0] = planes[0][1] * ilocalsize;
13266         projectionvector[1][1] = planes[1][1] * ilocalsize;
13267         projectionvector[1][2] = planes[2][1] * ilocalsize;
13268         projectionvector[2][0] = planes[0][2] * ilocalsize;
13269         projectionvector[2][1] = planes[1][2] * ilocalsize;
13270         projectionvector[2][2] = planes[2][2] * ilocalsize;
13271         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13272         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13273         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13274         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13275 }
13276 #endif
13277
13278         dynamic = model->surfmesh.isanimated;
13279         numsurfacelist = model->nummodelsurfaces;
13280         surfacelist = model->sortedmodelsurfaces;
13281         surfaces = model->data_surfaces;
13282
13283         bih = NULL;
13284         bih_triangles_count = -1;
13285         if(!dynamic)
13286         {
13287                 if(model->render_bih.numleafs)
13288                         bih = &model->render_bih;
13289                 else if(model->collision_bih.numleafs)
13290                         bih = &model->collision_bih;
13291         }
13292         if(bih)
13293                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13294         if(bih_triangles_count == 0)
13295                 return;
13296         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13297                 return;
13298         if(bih_triangles_count > 0)
13299         {
13300                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13301                 {
13302                         surfaceindex = bih_surfaces[triangleindex];
13303                         surface = surfaces + surfaceindex;
13304                         texture = surface->texture;
13305                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13306                                 continue;
13307                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13308                                 continue;
13309                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13310                 }
13311         }
13312         else
13313         {
13314                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13315                 {
13316                         surfaceindex = surfacelist[surfacelistindex];
13317                         surface = surfaces + surfaceindex;
13318                         // check cull box first because it rejects more than any other check
13319                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13320                                 continue;
13321                         // skip transparent surfaces
13322                         texture = surface->texture;
13323                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13324                                 continue;
13325                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13326                                 continue;
13327                         numtriangles = surface->num_triangles;
13328                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13329                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13330                 }
13331         }
13332 }
13333
13334 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13335 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)
13336 {
13337         int renderentityindex;
13338         float worldmins[3];
13339         float worldmaxs[3];
13340         entity_render_t *ent;
13341
13342         if (!cl_decals_newsystem.integer)
13343                 return;
13344
13345         worldmins[0] = worldorigin[0] - worldsize;
13346         worldmins[1] = worldorigin[1] - worldsize;
13347         worldmins[2] = worldorigin[2] - worldsize;
13348         worldmaxs[0] = worldorigin[0] + worldsize;
13349         worldmaxs[1] = worldorigin[1] + worldsize;
13350         worldmaxs[2] = worldorigin[2] + worldsize;
13351
13352         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13353
13354         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13355         {
13356                 ent = r_refdef.scene.entities[renderentityindex];
13357                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13358                         continue;
13359
13360                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13361         }
13362 }
13363
13364 typedef struct r_decalsystem_splatqueue_s
13365 {
13366         vec3_t worldorigin;
13367         vec3_t worldnormal;
13368         float color[4];
13369         float tcrange[4];
13370         float worldsize;
13371         int decalsequence;
13372 }
13373 r_decalsystem_splatqueue_t;
13374
13375 int r_decalsystem_numqueued = 0;
13376 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13377
13378 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)
13379 {
13380         r_decalsystem_splatqueue_t *queue;
13381
13382         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13383                 return;
13384
13385         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13386         VectorCopy(worldorigin, queue->worldorigin);
13387         VectorCopy(worldnormal, queue->worldnormal);
13388         Vector4Set(queue->color, r, g, b, a);
13389         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13390         queue->worldsize = worldsize;
13391         queue->decalsequence = cl.decalsequence++;
13392 }
13393
13394 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13395 {
13396         int i;
13397         r_decalsystem_splatqueue_t *queue;
13398
13399         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13400                 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);
13401         r_decalsystem_numqueued = 0;
13402 }
13403
13404 extern cvar_t cl_decals_max;
13405 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13406 {
13407         int i;
13408         decalsystem_t *decalsystem = &ent->decalsystem;
13409         int numdecals;
13410         int killsequence;
13411         tridecal_t *decal;
13412         float frametime;
13413         float lifetime;
13414
13415         if (!decalsystem->numdecals)
13416                 return;
13417
13418         if (r_showsurfaces.integer)
13419                 return;
13420
13421         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13422         {
13423                 R_DecalSystem_Reset(decalsystem);
13424                 return;
13425         }
13426
13427         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13428         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13429
13430         if (decalsystem->lastupdatetime)
13431                 frametime = (cl.time - decalsystem->lastupdatetime);
13432         else
13433                 frametime = 0;
13434         decalsystem->lastupdatetime = cl.time;
13435         decal = decalsystem->decals;
13436         numdecals = decalsystem->numdecals;
13437
13438         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13439         {
13440                 if (decal->color4ub[0][3])
13441                 {
13442                         decal->lived += frametime;
13443                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13444                         {
13445                                 memset(decal, 0, sizeof(*decal));
13446                                 if (decalsystem->freedecal > i)
13447                                         decalsystem->freedecal = i;
13448                         }
13449                 }
13450         }
13451         decal = decalsystem->decals;
13452         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13453                 numdecals--;
13454
13455         // collapse the array by shuffling the tail decals into the gaps
13456         for (;;)
13457         {
13458                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13459                         decalsystem->freedecal++;
13460                 if (decalsystem->freedecal == numdecals)
13461                         break;
13462                 decal[decalsystem->freedecal] = decal[--numdecals];
13463         }
13464
13465         decalsystem->numdecals = numdecals;
13466
13467         if (numdecals <= 0)
13468         {
13469                 // if there are no decals left, reset decalsystem
13470                 R_DecalSystem_Reset(decalsystem);
13471         }
13472 }
13473
13474 extern skinframe_t *decalskinframe;
13475 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13476 {
13477         int i;
13478         decalsystem_t *decalsystem = &ent->decalsystem;
13479         int numdecals;
13480         tridecal_t *decal;
13481         float faderate;
13482         float alpha;
13483         float *v3f;
13484         float *c4f;
13485         float *t2f;
13486         const int *e;
13487         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13488         int numtris = 0;
13489
13490         numdecals = decalsystem->numdecals;
13491         if (!numdecals)
13492                 return;
13493
13494         if (r_showsurfaces.integer)
13495                 return;
13496
13497         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13498         {
13499                 R_DecalSystem_Reset(decalsystem);
13500                 return;
13501         }
13502
13503         // if the model is static it doesn't matter what value we give for
13504         // wantnormals and wanttangents, so this logic uses only rules applicable
13505         // to a model, knowing that they are meaningless otherwise
13506         if (ent == r_refdef.scene.worldentity)
13507                 RSurf_ActiveWorldEntity();
13508         else
13509                 RSurf_ActiveModelEntity(ent, false, false, false);
13510
13511         decalsystem->lastupdatetime = cl.time;
13512         decal = decalsystem->decals;
13513
13514         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13515
13516         // update vertex positions for animated models
13517         v3f = decalsystem->vertex3f;
13518         c4f = decalsystem->color4f;
13519         t2f = decalsystem->texcoord2f;
13520         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13521         {
13522                 if (!decal->color4ub[0][3])
13523                         continue;
13524
13525                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13526                         continue;
13527
13528                 // update color values for fading decals
13529                 if (decal->lived >= cl_decals_time.value)
13530                 {
13531                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13532                         alpha *= (1.0f/255.0f);
13533                 }
13534                 else
13535                         alpha = 1.0f/255.0f;
13536
13537                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13538                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13539                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13540                 c4f[ 3] = 1;
13541                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13542                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13543                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13544                 c4f[ 7] = 1;
13545                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13546                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13547                 c4f[10] = decal->color4ub[2][2] * alpha;
13548                 c4f[11] = 1;
13549
13550                 t2f[0] = decal->texcoord2f[0][0];
13551                 t2f[1] = decal->texcoord2f[0][1];
13552                 t2f[2] = decal->texcoord2f[1][0];
13553                 t2f[3] = decal->texcoord2f[1][1];
13554                 t2f[4] = decal->texcoord2f[2][0];
13555                 t2f[5] = decal->texcoord2f[2][1];
13556
13557                 // update vertex positions for animated models
13558                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13559                 {
13560                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13561                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13562                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13563                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13564                 }
13565                 else
13566                 {
13567                         VectorCopy(decal->vertex3f[0], v3f);
13568                         VectorCopy(decal->vertex3f[1], v3f + 3);
13569                         VectorCopy(decal->vertex3f[2], v3f + 6);
13570                 }
13571
13572                 if (r_refdef.fogenabled)
13573                 {
13574                         alpha = RSurf_FogVertex(v3f);
13575                         VectorScale(c4f, alpha, c4f);
13576                         alpha = RSurf_FogVertex(v3f + 3);
13577                         VectorScale(c4f + 4, alpha, c4f + 4);
13578                         alpha = RSurf_FogVertex(v3f + 6);
13579                         VectorScale(c4f + 8, alpha, c4f + 8);
13580                 }
13581
13582                 v3f += 9;
13583                 c4f += 12;
13584                 t2f += 6;
13585                 numtris++;
13586         }
13587
13588         if (numtris > 0)
13589         {
13590                 r_refdef.stats.drawndecals += numtris;
13591
13592                 // now render the decals all at once
13593                 // (this assumes they all use one particle font texture!)
13594                 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);
13595 //              R_Mesh_ResetTextureState();
13596                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13597                 GL_DepthMask(false);
13598                 GL_DepthRange(0, 1);
13599                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13600                 GL_DepthTest(true);
13601                 GL_CullFace(GL_NONE);
13602                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13603                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13604                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13605         }
13606 }
13607
13608 static void R_DrawModelDecals(void)
13609 {
13610         int i, numdecals;
13611
13612         // fade faster when there are too many decals
13613         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13614         for (i = 0;i < r_refdef.scene.numentities;i++)
13615                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13616
13617         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13618         for (i = 0;i < r_refdef.scene.numentities;i++)
13619                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13620                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13621
13622         R_DecalSystem_ApplySplatEntitiesQueue();
13623
13624         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13625         for (i = 0;i < r_refdef.scene.numentities;i++)
13626                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13627
13628         r_refdef.stats.totaldecals += numdecals;
13629
13630         if (r_showsurfaces.integer)
13631                 return;
13632
13633         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13634
13635         for (i = 0;i < r_refdef.scene.numentities;i++)
13636         {
13637                 if (!r_refdef.viewcache.entityvisible[i])
13638                         continue;
13639                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13640                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13641         }
13642 }
13643
13644 extern cvar_t mod_collision_bih;
13645 void R_DrawDebugModel(void)
13646 {
13647         entity_render_t *ent = rsurface.entity;
13648         int i, j, k, l, flagsmask;
13649         const msurface_t *surface;
13650         dp_model_t *model = ent->model;
13651         vec3_t v;
13652
13653         switch(vid.renderpath)
13654         {
13655         case RENDERPATH_GL11:
13656         case RENDERPATH_GL13:
13657         case RENDERPATH_GL20:
13658                 break;
13659         case RENDERPATH_D3D9:
13660                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13661                 return;
13662         case RENDERPATH_D3D10:
13663                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13664                 return;
13665         case RENDERPATH_D3D11:
13666                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13667                 return;
13668         case RENDERPATH_SOFT:
13669                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13670                 return;
13671         case RENDERPATH_GLES2:
13672                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13673                 return;
13674         }
13675
13676         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13677
13678 //      R_Mesh_ResetTextureState();
13679         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13680         GL_DepthRange(0, 1);
13681         GL_DepthTest(!r_showdisabledepthtest.integer);
13682         GL_DepthMask(false);
13683         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13684
13685         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13686         {
13687                 int triangleindex;
13688                 int bihleafindex;
13689                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13690                 const q3mbrush_t *brush;
13691                 const bih_t *bih = &model->collision_bih;
13692                 const bih_leaf_t *bihleaf;
13693                 float vertex3f[3][3];
13694                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13695                 cullbox = false;
13696                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13697                 {
13698                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13699                                 continue;
13700                         switch (bihleaf->type)
13701                         {
13702                         case BIH_BRUSH:
13703                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13704                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13705                                 {
13706                                         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);
13707                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13708                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13709                                 }
13710                                 break;
13711                         case BIH_COLLISIONTRIANGLE:
13712                                 triangleindex = bihleaf->itemindex;
13713                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13714                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13715                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13716                                 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);
13717                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13718                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13719                                 break;
13720                         case BIH_RENDERTRIANGLE:
13721                                 triangleindex = bihleaf->itemindex;
13722                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13723                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13724                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13725                                 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);
13726                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13727                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13728                                 break;
13729                         }
13730                 }
13731         }
13732
13733         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13734
13735         if (r_showtris.integer || (r_shownormals.value != 0))
13736         {
13737                 if (r_showdisabledepthtest.integer)
13738                 {
13739                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13740                         GL_DepthMask(false);
13741                 }
13742                 else
13743                 {
13744                         GL_BlendFunc(GL_ONE, GL_ZERO);
13745                         GL_DepthMask(true);
13746                 }
13747                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13748                 {
13749                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13750                                 continue;
13751                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13752                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13753                         {
13754                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13755                                 if (r_showtris.value > 0)
13756                                 {
13757                                         if (!rsurface.texture->currentlayers->depthmask)
13758                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13759                                         else if (ent == r_refdef.scene.worldentity)
13760                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13761                                         else
13762                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13763                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13764                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13765                                         RSurf_DrawBatch();
13766                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13767                                         CHECKGLERROR
13768                                 }
13769                                 if (r_shownormals.value < 0)
13770                                 {
13771                                         qglBegin(GL_LINES);
13772                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13773                                         {
13774                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13775                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13776                                                 qglVertex3f(v[0], v[1], v[2]);
13777                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13778                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13779                                                 qglVertex3f(v[0], v[1], v[2]);
13780                                         }
13781                                         qglEnd();
13782                                         CHECKGLERROR
13783                                 }
13784                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13785                                 {
13786                                         qglBegin(GL_LINES);
13787                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13788                                         {
13789                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13790                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13791                                                 qglVertex3f(v[0], v[1], v[2]);
13792                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13793                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13794                                                 qglVertex3f(v[0], v[1], v[2]);
13795                                         }
13796                                         qglEnd();
13797                                         CHECKGLERROR
13798                                         qglBegin(GL_LINES);
13799                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13800                                         {
13801                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13802                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13803                                                 qglVertex3f(v[0], v[1], v[2]);
13804                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13805                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13806                                                 qglVertex3f(v[0], v[1], v[2]);
13807                                         }
13808                                         qglEnd();
13809                                         CHECKGLERROR
13810                                         qglBegin(GL_LINES);
13811                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13812                                         {
13813                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13814                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13815                                                 qglVertex3f(v[0], v[1], v[2]);
13816                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13817                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13818                                                 qglVertex3f(v[0], v[1], v[2]);
13819                                         }
13820                                         qglEnd();
13821                                         CHECKGLERROR
13822                                 }
13823                         }
13824                 }
13825                 rsurface.texture = NULL;
13826         }
13827 }
13828
13829 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13830 int r_maxsurfacelist = 0;
13831 const msurface_t **r_surfacelist = NULL;
13832 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13833 {
13834         int i, j, endj, flagsmask;
13835         dp_model_t *model = r_refdef.scene.worldmodel;
13836         msurface_t *surfaces;
13837         unsigned char *update;
13838         int numsurfacelist = 0;
13839         if (model == NULL)
13840                 return;
13841
13842         if (r_maxsurfacelist < model->num_surfaces)
13843         {
13844                 r_maxsurfacelist = model->num_surfaces;
13845                 if (r_surfacelist)
13846                         Mem_Free((msurface_t**)r_surfacelist);
13847                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13848         }
13849
13850         RSurf_ActiveWorldEntity();
13851
13852         surfaces = model->data_surfaces;
13853         update = model->brushq1.lightmapupdateflags;
13854
13855         // update light styles on this submodel
13856         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13857         {
13858                 model_brush_lightstyleinfo_t *style;
13859                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13860                 {
13861                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13862                         {
13863                                 int *list = style->surfacelist;
13864                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13865                                 for (j = 0;j < style->numsurfaces;j++)
13866                                         update[list[j]] = true;
13867                         }
13868                 }
13869         }
13870
13871         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13872
13873         if (debug)
13874         {
13875                 R_DrawDebugModel();
13876                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13877                 return;
13878         }
13879
13880         rsurface.lightmaptexture = NULL;
13881         rsurface.deluxemaptexture = NULL;
13882         rsurface.uselightmaptexture = false;
13883         rsurface.texture = NULL;
13884         rsurface.rtlight = NULL;
13885         numsurfacelist = 0;
13886         // add visible surfaces to draw list
13887         for (i = 0;i < model->nummodelsurfaces;i++)
13888         {
13889                 j = model->sortedmodelsurfaces[i];
13890                 if (r_refdef.viewcache.world_surfacevisible[j])
13891                         r_surfacelist[numsurfacelist++] = surfaces + j;
13892         }
13893         // update lightmaps if needed
13894         if (model->brushq1.firstrender)
13895         {
13896                 model->brushq1.firstrender = false;
13897                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13898                         if (update[j])
13899                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13900         }
13901         else if (update)
13902         {
13903                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13904                         if (r_refdef.viewcache.world_surfacevisible[j])
13905                                 if (update[j])
13906                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13907         }
13908         // don't do anything if there were no surfaces
13909         if (!numsurfacelist)
13910         {
13911                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13912                 return;
13913         }
13914         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13915
13916         // add to stats if desired
13917         if (r_speeds.integer && !skysurfaces && !depthonly)
13918         {
13919                 r_refdef.stats.world_surfaces += numsurfacelist;
13920                 for (j = 0;j < numsurfacelist;j++)
13921                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13922         }
13923
13924         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13925 }
13926
13927 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13928 {
13929         int i, j, endj, flagsmask;
13930         dp_model_t *model = ent->model;
13931         msurface_t *surfaces;
13932         unsigned char *update;
13933         int numsurfacelist = 0;
13934         if (model == NULL)
13935                 return;
13936
13937         if (r_maxsurfacelist < model->num_surfaces)
13938         {
13939                 r_maxsurfacelist = model->num_surfaces;
13940                 if (r_surfacelist)
13941                         Mem_Free((msurface_t **)r_surfacelist);
13942                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13943         }
13944
13945         // if the model is static it doesn't matter what value we give for
13946         // wantnormals and wanttangents, so this logic uses only rules applicable
13947         // to a model, knowing that they are meaningless otherwise
13948         if (ent == r_refdef.scene.worldentity)
13949                 RSurf_ActiveWorldEntity();
13950         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13951                 RSurf_ActiveModelEntity(ent, false, false, false);
13952         else if (prepass)
13953                 RSurf_ActiveModelEntity(ent, true, true, true);
13954         else if (depthonly)
13955         {
13956                 switch (vid.renderpath)
13957                 {
13958                 case RENDERPATH_GL20:
13959                 case RENDERPATH_D3D9:
13960                 case RENDERPATH_D3D10:
13961                 case RENDERPATH_D3D11:
13962                 case RENDERPATH_SOFT:
13963                 case RENDERPATH_GLES2:
13964                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13965                         break;
13966                 case RENDERPATH_GL13:
13967                 case RENDERPATH_GL11:
13968                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13969                         break;
13970                 }
13971         }
13972         else
13973         {
13974                 switch (vid.renderpath)
13975                 {
13976                 case RENDERPATH_GL20:
13977                 case RENDERPATH_D3D9:
13978                 case RENDERPATH_D3D10:
13979                 case RENDERPATH_D3D11:
13980                 case RENDERPATH_SOFT:
13981                 case RENDERPATH_GLES2:
13982                         RSurf_ActiveModelEntity(ent, true, true, false);
13983                         break;
13984                 case RENDERPATH_GL13:
13985                 case RENDERPATH_GL11:
13986                         RSurf_ActiveModelEntity(ent, true, false, false);
13987                         break;
13988                 }
13989         }
13990
13991         surfaces = model->data_surfaces;
13992         update = model->brushq1.lightmapupdateflags;
13993
13994         // update light styles
13995         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13996         {
13997                 model_brush_lightstyleinfo_t *style;
13998                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13999                 {
14000                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14001                         {
14002                                 int *list = style->surfacelist;
14003                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14004                                 for (j = 0;j < style->numsurfaces;j++)
14005                                         update[list[j]] = true;
14006                         }
14007                 }
14008         }
14009
14010         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14011
14012         if (debug)
14013         {
14014                 R_DrawDebugModel();
14015                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14016                 return;
14017         }
14018
14019         rsurface.lightmaptexture = NULL;
14020         rsurface.deluxemaptexture = NULL;
14021         rsurface.uselightmaptexture = false;
14022         rsurface.texture = NULL;
14023         rsurface.rtlight = NULL;
14024         numsurfacelist = 0;
14025         // add visible surfaces to draw list
14026         for (i = 0;i < model->nummodelsurfaces;i++)
14027                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14028         // don't do anything if there were no surfaces
14029         if (!numsurfacelist)
14030         {
14031                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14032                 return;
14033         }
14034         // update lightmaps if needed
14035         if (update)
14036         {
14037                 int updated = 0;
14038                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14039                 {
14040                         if (update[j])
14041                         {
14042                                 updated++;
14043                                 R_BuildLightMap(ent, surfaces + j);
14044                         }
14045                 }
14046         }
14047         if (update)
14048                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14049                         if (update[j])
14050                                 R_BuildLightMap(ent, surfaces + j);
14051         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14052
14053         // add to stats if desired
14054         if (r_speeds.integer && !skysurfaces && !depthonly)
14055         {
14056                 r_refdef.stats.entities_surfaces += numsurfacelist;
14057                 for (j = 0;j < numsurfacelist;j++)
14058                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14059         }
14060
14061         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14062 }
14063
14064 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14065 {
14066         static texture_t texture;
14067         static msurface_t surface;
14068         const msurface_t *surfacelist = &surface;
14069
14070         // fake enough texture and surface state to render this geometry
14071
14072         texture.update_lastrenderframe = -1; // regenerate this texture
14073         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14074         texture.currentskinframe = skinframe;
14075         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14076         texture.offsetmapping = OFFSETMAPPING_OFF;
14077         texture.offsetscale = 1;
14078         texture.specularscalemod = 1;
14079         texture.specularpowermod = 1;
14080
14081         surface.texture = &texture;
14082         surface.num_triangles = numtriangles;
14083         surface.num_firsttriangle = firsttriangle;
14084         surface.num_vertices = numvertices;
14085         surface.num_firstvertex = firstvertex;
14086
14087         // now render it
14088         rsurface.texture = R_GetCurrentTexture(surface.texture);
14089         rsurface.lightmaptexture = NULL;
14090         rsurface.deluxemaptexture = NULL;
14091         rsurface.uselightmaptexture = false;
14092         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14093 }
14094
14095 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)
14096 {
14097         static msurface_t surface;
14098         const msurface_t *surfacelist = &surface;
14099
14100         // fake enough texture and surface state to render this geometry
14101         surface.texture = texture;
14102         surface.num_triangles = numtriangles;
14103         surface.num_firsttriangle = firsttriangle;
14104         surface.num_vertices = numvertices;
14105         surface.num_firstvertex = firstvertex;
14106
14107         // now render it
14108         rsurface.texture = R_GetCurrentTexture(surface.texture);
14109         rsurface.lightmaptexture = NULL;
14110         rsurface.deluxemaptexture = NULL;
14111         rsurface.uselightmaptexture = false;
14112         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14113 }