]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
8c5fc54b7429748397338046573d14b01a85f972
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
74 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
75 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
76 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
77 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
78 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
79 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
80 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
81 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
82 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
83 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
84 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
85 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
86 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
87 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
88 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
89 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
90 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
91 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
92 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
93 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
94 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
95 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
96
97 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
98 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
99 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
100
101 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
102 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
103 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
104 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
105 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
106 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
107 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
108 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
109 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
110 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
111 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
112 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
113 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
114 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
115 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
116 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
117 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
118 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
119 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
120
121 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
122 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
123 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
124 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
125 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
126 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
127 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
128 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
129
130 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
131 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
132
133 cvar_t r_texture_convertsRGB_2d = {0, "r_texture_convertsRGB_2d", "0", "load textures as sRGB and convert to linear for proper shading"};
134 cvar_t r_texture_convertsRGB_skin = {0, "r_texture_convertsRGB_skin", "0", "load textures as sRGB and convert to linear for proper shading"};
135 cvar_t r_texture_convertsRGB_cubemap = {0, "r_texture_convertsRGB_cubemap", "0", "load textures as sRGB and convert to linear for proper shading"};
136 cvar_t r_texture_convertsRGB_skybox = {0, "r_texture_convertsRGB_skybox", "0", "load textures as sRGB and convert to linear for proper shading"};
137 cvar_t r_texture_convertsRGB_particles = {0, "r_texture_convertsRGB_particles", "0", "load textures as sRGB and convert to linear for proper shading"};
138
139 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
140 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
141 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
142
143 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
144 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
145 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
146 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
147 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
148 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
149 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
150 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
151 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
152 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
153 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
154 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
155 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
156
157 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
158 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
159 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
160 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
161 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
162 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
163
164 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
165 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
166 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
167 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
168
169 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
170 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
171 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
172 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
173 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
174 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
175 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
176
177 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
178 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
179 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
180 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
181 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
182 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
183 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
184 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
185 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
186 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
187
188 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
189
190 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
191
192 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
193
194 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
195 cvar_t r_track_sprites = {CVAR_SAVE, "r_track_sprites", "1", "track SPR_LABEL* sprites by putting them as indicator at the screen border to rotate to"};
196 cvar_t r_track_sprites_flags = {CVAR_SAVE, "r_track_sprites_flags", "1", "1: Rotate sprites accordingly, 2: Make it a continuous rotation"};
197 cvar_t r_track_sprites_scalew = {CVAR_SAVE, "r_track_sprites_scalew", "1", "width scaling of tracked sprites"};
198 cvar_t r_track_sprites_scaleh = {CVAR_SAVE, "r_track_sprites_scaleh", "1", "height scaling of tracked sprites"};
199 cvar_t r_overheadsprites_perspective = {CVAR_SAVE, "r_overheadsprites_perspective", "5", "fake perspective effect for SPR_OVERHEAD sprites"};
200 cvar_t r_overheadsprites_pushback = {CVAR_SAVE, "r_overheadsprites_pushback", "15", "how far to pull the SPR_OVERHEAD sprites toward the eye (used to avoid intersections with 3D models)"};
201 cvar_t r_overheadsprites_scalex = {CVAR_SAVE, "r_overheadsprites_scalex", "1", "additional scale for overhead sprites for x axis"};
202 cvar_t r_overheadsprites_scaley = {CVAR_SAVE, "r_overheadsprites_scaley", "1", "additional scale for overhead sprites for y axis"};
203
204 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
205 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
206
207 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
208
209 extern cvar_t v_glslgamma;
210
211 extern qboolean v_flipped_state;
212
213 static struct r_bloomstate_s
214 {
215         qboolean enabled;
216         qboolean hdr;
217
218         int bloomwidth, bloomheight;
219
220         int screentexturewidth, screentextureheight;
221         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
222
223         int bloomtexturewidth, bloomtextureheight;
224         rtexture_t *texture_bloom;
225
226         // arrays for rendering the screen passes
227         float screentexcoord2f[8];
228         float bloomtexcoord2f[8];
229         float offsettexcoord2f[8];
230
231         r_viewport_t viewport;
232 }
233 r_bloomstate;
234
235 r_waterstate_t r_waterstate;
236
237 /// shadow volume bsp struct with automatically growing nodes buffer
238 svbsp_t r_svbsp;
239
240 rtexture_t *r_texture_blanknormalmap;
241 rtexture_t *r_texture_white;
242 rtexture_t *r_texture_grey128;
243 rtexture_t *r_texture_black;
244 rtexture_t *r_texture_notexture;
245 rtexture_t *r_texture_whitecube;
246 rtexture_t *r_texture_normalizationcube;
247 rtexture_t *r_texture_fogattenuation;
248 rtexture_t *r_texture_fogheighttexture;
249 rtexture_t *r_texture_gammaramps;
250 unsigned int r_texture_gammaramps_serial;
251 //rtexture_t *r_texture_fogintensity;
252 rtexture_t *r_texture_reflectcube;
253
254 // TODO: hash lookups?
255 typedef struct cubemapinfo_s
256 {
257         char basename[64];
258         rtexture_t *texture;
259 }
260 cubemapinfo_t;
261
262 int r_texture_numcubemaps;
263 cubemapinfo_t r_texture_cubemaps[MAX_CUBEMAPS];
264
265 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
266 unsigned int r_numqueries;
267 unsigned int r_maxqueries;
268
269 typedef struct r_qwskincache_s
270 {
271         char name[MAX_QPATH];
272         skinframe_t *skinframe;
273 }
274 r_qwskincache_t;
275
276 static r_qwskincache_t *r_qwskincache;
277 static int r_qwskincache_size;
278
279 /// vertex coordinates for a quad that covers the screen exactly
280 extern const float r_screenvertex3f[12];
281 extern const float r_d3dscreenvertex3f[12];
282 const float r_screenvertex3f[12] =
283 {
284         0, 0, 0,
285         1, 0, 0,
286         1, 1, 0,
287         0, 1, 0
288 };
289 const float r_d3dscreenvertex3f[12] =
290 {
291         0, 1, 0,
292         1, 1, 0,
293         1, 0, 0,
294         0, 0, 0
295 };
296
297 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
298 {
299         int i;
300         for (i = 0;i < verts;i++)
301         {
302                 out[0] = in[0] * r;
303                 out[1] = in[1] * g;
304                 out[2] = in[2] * b;
305                 out[3] = in[3];
306                 in += 4;
307                 out += 4;
308         }
309 }
310
311 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
312 {
313         int i;
314         for (i = 0;i < verts;i++)
315         {
316                 out[0] = r;
317                 out[1] = g;
318                 out[2] = b;
319                 out[3] = a;
320                 out += 4;
321         }
322 }
323
324 // FIXME: move this to client?
325 void FOG_clear(void)
326 {
327         if (gamemode == GAME_NEHAHRA)
328         {
329                 Cvar_Set("gl_fogenable", "0");
330                 Cvar_Set("gl_fogdensity", "0.2");
331                 Cvar_Set("gl_fogred", "0.3");
332                 Cvar_Set("gl_foggreen", "0.3");
333                 Cvar_Set("gl_fogblue", "0.3");
334         }
335         r_refdef.fog_density = 0;
336         r_refdef.fog_red = 0;
337         r_refdef.fog_green = 0;
338         r_refdef.fog_blue = 0;
339         r_refdef.fog_alpha = 1;
340         r_refdef.fog_start = 0;
341         r_refdef.fog_end = 16384;
342         r_refdef.fog_height = 1<<30;
343         r_refdef.fog_fadedepth = 128;
344         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
345 }
346
347 static void R_BuildBlankTextures(void)
348 {
349         unsigned char data[4];
350         data[2] = 128; // normal X
351         data[1] = 128; // normal Y
352         data[0] = 255; // normal Z
353         data[3] = 128; // height
354         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
355         data[0] = 255;
356         data[1] = 255;
357         data[2] = 255;
358         data[3] = 255;
359         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
360         data[0] = 128;
361         data[1] = 128;
362         data[2] = 128;
363         data[3] = 255;
364         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
365         data[0] = 0;
366         data[1] = 0;
367         data[2] = 0;
368         data[3] = 255;
369         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370 }
371
372 static void R_BuildNoTexture(void)
373 {
374         int x, y;
375         unsigned char pix[16][16][4];
376         // this makes a light grey/dark grey checkerboard texture
377         for (y = 0;y < 16;y++)
378         {
379                 for (x = 0;x < 16;x++)
380                 {
381                         if ((y < 8) ^ (x < 8))
382                         {
383                                 pix[y][x][0] = 128;
384                                 pix[y][x][1] = 128;
385                                 pix[y][x][2] = 128;
386                                 pix[y][x][3] = 255;
387                         }
388                         else
389                         {
390                                 pix[y][x][0] = 64;
391                                 pix[y][x][1] = 64;
392                                 pix[y][x][2] = 64;
393                                 pix[y][x][3] = 255;
394                         }
395                 }
396         }
397         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
398 }
399
400 static void R_BuildWhiteCube(void)
401 {
402         unsigned char data[6*1*1*4];
403         memset(data, 255, sizeof(data));
404         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
405 }
406
407 static void R_BuildNormalizationCube(void)
408 {
409         int x, y, side;
410         vec3_t v;
411         vec_t s, t, intensity;
412 #define NORMSIZE 64
413         unsigned char *data;
414         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
415         for (side = 0;side < 6;side++)
416         {
417                 for (y = 0;y < NORMSIZE;y++)
418                 {
419                         for (x = 0;x < NORMSIZE;x++)
420                         {
421                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423                                 switch(side)
424                                 {
425                                 default:
426                                 case 0:
427                                         v[0] = 1;
428                                         v[1] = -t;
429                                         v[2] = -s;
430                                         break;
431                                 case 1:
432                                         v[0] = -1;
433                                         v[1] = -t;
434                                         v[2] = s;
435                                         break;
436                                 case 2:
437                                         v[0] = s;
438                                         v[1] = 1;
439                                         v[2] = t;
440                                         break;
441                                 case 3:
442                                         v[0] = s;
443                                         v[1] = -1;
444                                         v[2] = -t;
445                                         break;
446                                 case 4:
447                                         v[0] = s;
448                                         v[1] = -t;
449                                         v[2] = 1;
450                                         break;
451                                 case 5:
452                                         v[0] = -s;
453                                         v[1] = -t;
454                                         v[2] = -1;
455                                         break;
456                                 }
457                                 intensity = 127.0f / sqrt(DotProduct(v, v));
458                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
459                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
460                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
461                                 data[((side*64+y)*64+x)*4+3] = 255;
462                         }
463                 }
464         }
465         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
466         Mem_Free(data);
467 }
468
469 static void R_BuildFogTexture(void)
470 {
471         int x, b;
472 #define FOGWIDTH 256
473         unsigned char data1[FOGWIDTH][4];
474         //unsigned char data2[FOGWIDTH][4];
475         double d, r, alpha;
476
477         r_refdef.fogmasktable_start = r_refdef.fog_start;
478         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
479         r_refdef.fogmasktable_range = r_refdef.fogrange;
480         r_refdef.fogmasktable_density = r_refdef.fog_density;
481
482         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
483         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
484         {
485                 d = (x * r - r_refdef.fogmasktable_start);
486                 if(developer_extra.integer)
487                         Con_DPrintf("%f ", d);
488                 d = max(0, d);
489                 if (r_fog_exp2.integer)
490                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
491                 else
492                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
493                 if(developer_extra.integer)
494                         Con_DPrintf(" : %f ", alpha);
495                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
496                 if(developer_extra.integer)
497                         Con_DPrintf(" = %f\n", alpha);
498                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
499         }
500
501         for (x = 0;x < FOGWIDTH;x++)
502         {
503                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
504                 data1[x][0] = b;
505                 data1[x][1] = b;
506                 data1[x][2] = b;
507                 data1[x][3] = 255;
508                 //data2[x][0] = 255 - b;
509                 //data2[x][1] = 255 - b;
510                 //data2[x][2] = 255 - b;
511                 //data2[x][3] = 255;
512         }
513         if (r_texture_fogattenuation)
514         {
515                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
517         }
518         else
519         {
520                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
521                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
522         }
523 }
524
525 static void R_BuildFogHeightTexture(void)
526 {
527         unsigned char *inpixels;
528         int size;
529         int x;
530         int y;
531         int j;
532         float c[4];
533         float f;
534         inpixels = NULL;
535         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
536         if (r_refdef.fogheighttexturename[0])
537                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
538         if (!inpixels)
539         {
540                 r_refdef.fog_height_tablesize = 0;
541                 if (r_texture_fogheighttexture)
542                         R_FreeTexture(r_texture_fogheighttexture);
543                 r_texture_fogheighttexture = NULL;
544                 if (r_refdef.fog_height_table2d)
545                         Mem_Free(r_refdef.fog_height_table2d);
546                 r_refdef.fog_height_table2d = NULL;
547                 if (r_refdef.fog_height_table1d)
548                         Mem_Free(r_refdef.fog_height_table1d);
549                 r_refdef.fog_height_table1d = NULL;
550                 return;
551         }
552         size = image_width;
553         r_refdef.fog_height_tablesize = size;
554         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
555         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
556         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
557         Mem_Free(inpixels);
558         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
559         // average fog color table accounting for every fog layer between a point
560         // and the camera.  (Note: attenuation is handled separately!)
561         for (y = 0;y < size;y++)
562         {
563                 for (x = 0;x < size;x++)
564                 {
565                         Vector4Clear(c);
566                         f = 0;
567                         if (x < y)
568                         {
569                                 for (j = x;j <= y;j++)
570                                 {
571                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
572                                         f++;
573                                 }
574                         }
575                         else
576                         {
577                                 for (j = x;j >= y;j--)
578                                 {
579                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
580                                         f++;
581                                 }
582                         }
583                         f = 1.0f / f;
584                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
586                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
588                 }
589         }
590         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
591 }
592
593 //=======================================================================================================================================================
594
595 static const char *builtinshaderstring =
596 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
597 "// written by Forest 'LordHavoc' Hale\n"
598 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
599 "\n"
600 "// GL ES shaders use precision modifiers, standard GL does not\n"
601 "#ifndef GL_ES\n"
602 "#define lowp\n"
603 "#define mediump\n"
604 "#define highp\n"
605 "#endif\n"
606 "\n"
607 "#ifdef VERTEX_SHADER\n"
608 "attribute vec4 Attrib_Position;  // vertex\n"
609 "attribute vec4 Attrib_Color;     // color\n"
610 "attribute vec4 Attrib_TexCoord0; // material texcoords\n"
611 "attribute vec3 Attrib_TexCoord1; // svector\n"
612 "attribute vec3 Attrib_TexCoord2; // tvector\n"
613 "attribute vec3 Attrib_TexCoord3; // normal\n"
614 "attribute vec4 Attrib_TexCoord4; // lightmap texcoords\n"
615 "#endif\n"
616 "varying lowp vec4 VertexColor;\n"
617 "\n"
618 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
619 "# define USEFOG\n"
620 "#endif\n"
621 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
622 "#define USELIGHTMAP\n"
623 "#endif\n"
624 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
625 "#define USEEYEVECTOR\n"
626 "#endif\n"
627 "\n"
628 "#ifdef USESHADOWMAP2D\n"
629 "# ifdef GL_EXT_gpu_shader4\n"
630 "#   extension GL_EXT_gpu_shader4 : enable\n"
631 "# endif\n"
632 "# ifdef GL_ARB_texture_gather\n"
633 "#   extension GL_ARB_texture_gather : enable\n"
634 "# else\n"
635 "#   ifdef GL_AMD_texture_texture4\n"
636 "#     extension GL_AMD_texture_texture4 : enable\n"
637 "#   endif\n"
638 "# endif\n"
639 "#endif\n"
640 "\n"
641 "//#ifdef USESHADOWSAMPLER\n"
642 "//# extension GL_ARB_shadow : enable\n"
643 "//#endif\n"
644 "\n"
645 "//#ifdef __GLSL_CG_DATA_TYPES\n"
646 "//# define myhalf half\n"
647 "//# define myhalf2 half2\n"
648 "//# define myhalf3 half3\n"
649 "//# define myhalf4 half4\n"
650 "//#else\n"
651 "# define myhalf mediump float\n"
652 "# define myhalf2 mediump vec2\n"
653 "# define myhalf3 mediump vec3\n"
654 "# define myhalf4 mediump vec4\n"
655 "//#endif\n"
656 "\n"
657 "#ifdef VERTEX_SHADER\n"
658 "uniform highp mat4 ModelViewProjectionMatrix;\n"
659 "#endif\n"
660 "\n"
661 "#ifdef MODE_DEPTH_OR_SHADOW\n"
662 "#ifdef VERTEX_SHADER\n"
663 "void main(void)\n"
664 "{\n"
665 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
666 "}\n"
667 "#endif\n"
668 "#else // !MODE_DEPTH_ORSHADOW\n"
669 "\n"
670 "\n"
671 "\n"
672 "\n"
673 "#ifdef MODE_SHOWDEPTH\n"
674 "#ifdef VERTEX_SHADER\n"
675 "void main(void)\n"
676 "{\n"
677 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
678 "       VertexColor = vec4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
679 "}\n"
680 "#endif\n"
681 "\n"
682 "#ifdef FRAGMENT_SHADER\n"
683 "void main(void)\n"
684 "{\n"
685 "       gl_FragColor = VertexColor;\n"
686 "}\n"
687 "#endif\n"
688 "#else // !MODE_SHOWDEPTH\n"
689 "\n"
690 "\n"
691 "\n"
692 "\n"
693 "#ifdef MODE_POSTPROCESS\n"
694 "varying mediump vec2 TexCoord1;\n"
695 "varying mediump vec2 TexCoord2;\n"
696 "\n"
697 "#ifdef VERTEX_SHADER\n"
698 "void main(void)\n"
699 "{\n"
700 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
701 "       TexCoord1 = Attrib_TexCoord0.xy;\n"
702 "#ifdef USEBLOOM\n"
703 "       TexCoord2 = Attrib_TexCoord4.xy;\n"
704 "#endif\n"
705 "}\n"
706 "#endif\n"
707 "\n"
708 "#ifdef FRAGMENT_SHADER\n"
709 "uniform sampler2D Texture_First;\n"
710 "#ifdef USEBLOOM\n"
711 "uniform sampler2D Texture_Second;\n"
712 "uniform lowp vec4 BloomColorSubtract;\n"
713 "#endif\n"
714 "#ifdef USEGAMMARAMPS\n"
715 "uniform sampler2D Texture_GammaRamps;\n"
716 "#endif\n"
717 "#ifdef USESATURATION\n"
718 "uniform lowp float Saturation;\n"
719 "#endif\n"
720 "#ifdef USEVIEWTINT\n"
721 "uniform lowp vec4 ViewTintColor;\n"
722 "#endif\n"
723 "//uncomment these if you want to use them:\n"
724 "uniform mediump vec4 UserVec1;\n"
725 "uniform mediump vec4 UserVec2;\n"
726 "// uniform mediump vec4 UserVec3;\n"
727 "// uniform mediump vec4 UserVec4;\n"
728 "// uniform highp float ClientTime;\n"
729 "uniform mediump vec2 PixelSize;\n"
730 "void main(void)\n"
731 "{\n"
732 "       gl_FragColor = texture2D(Texture_First, TexCoord1);\n"
733 "#ifdef USEBLOOM\n"
734 "       gl_FragColor += max(vec4(0,0,0,0), texture2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
735 "#endif\n"
736 "#ifdef USEVIEWTINT\n"
737 "       gl_FragColor = mix(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
738 "#endif\n"
739 "\n"
740 "#ifdef USEPOSTPROCESSING\n"
741 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
742 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
743 "       float sobel = 1.0;\n"
744 "       // vec2 ts = textureSize(Texture_First, 0);\n"
745 "       // vec2 px = vec2(1/ts.x, 1/ts.y);\n"
746 "       vec2 px = PixelSize;\n"
747 "       vec3 x1 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
748 "       vec3 x2 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,  0.0)).rgb;\n"
749 "       vec3 x3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
750 "       vec3 x4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
751 "       vec3 x5 = texture2D(Texture_First, TexCoord1 + vec2( px.x,  0.0)).rgb;\n"
752 "       vec3 x6 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
753 "       vec3 y1 = texture2D(Texture_First, TexCoord1 + vec2( px.x,-px.y)).rgb;\n"
754 "       vec3 y2 = texture2D(Texture_First, TexCoord1 + vec2(  0.0,-px.y)).rgb;\n"
755 "       vec3 y3 = texture2D(Texture_First, TexCoord1 + vec2(-px.x,-px.y)).rgb;\n"
756 "       vec3 y4 = texture2D(Texture_First, TexCoord1 + vec2( px.x, px.y)).rgb;\n"
757 "       vec3 y5 = texture2D(Texture_First, TexCoord1 + vec2(  0.0, px.y)).rgb;\n"
758 "       vec3 y6 = texture2D(Texture_First, TexCoord1 + vec2(-px.x, px.y)).rgb;\n"
759 "       float px1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x1);\n"
760 "       float px2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), x2);\n"
761 "       float px3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), x3);\n"
762 "       float px4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x4);\n"
763 "       float px5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), x5);\n"
764 "       float px6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), x6);\n"
765 "       float py1 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y1);\n"
766 "       float py2 = -2.0 * dot(vec3(0.3, 0.59, 0.11), y2);\n"
767 "       float py3 = -1.0 * dot(vec3(0.3, 0.59, 0.11), y3);\n"
768 "       float py4 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y4);\n"
769 "       float py5 =  2.0 * dot(vec3(0.3, 0.59, 0.11), y5);\n"
770 "       float py6 =  1.0 * dot(vec3(0.3, 0.59, 0.11), y6);\n"
771 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
772 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.987688, -0.156434)) * UserVec1.y;\n"
773 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.156434, -0.891007)) * UserVec1.y;\n"
774 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.891007, -0.453990)) * UserVec1.y;\n"
775 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2( 0.707107,  0.707107)) * UserVec1.y;\n"
776 "       gl_FragColor += texture2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*vec2(-0.453990,  0.891007)) * UserVec1.y;\n"
777 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
778 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + vec3(max(0.0, sobel - UserVec2.z))*UserVec2.y;\n"
779 "#endif\n"
780 "\n"
781 "#ifdef USESATURATION\n"
782 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
783 "       float y = dot(gl_FragColor.rgb, vec3(0.299, 0.587, 0.114));\n"
784 "       // 'vampire sight' effect, wheres red is compensated\n"
785 "       #ifdef SATURATION_REDCOMPENSATE\n"
786 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
787 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
788 "               gl_FragColor.r += rboost;\n"
789 "       #else\n"
790 "               // normal desaturation\n"
791 "               //gl_FragColor = vec3(y) + (gl_FragColor.rgb - vec3(y)) * Saturation;\n"
792 "               gl_FragColor.rgb = mix(vec3(y), gl_FragColor.rgb, Saturation);\n"
793 "       #endif\n"
794 "#endif\n"
795 "\n"
796 "#ifdef USEGAMMARAMPS\n"
797 "       gl_FragColor.r = texture2D(Texture_GammaRamps, vec2(gl_FragColor.r, 0)).r;\n"
798 "       gl_FragColor.g = texture2D(Texture_GammaRamps, vec2(gl_FragColor.g, 0)).g;\n"
799 "       gl_FragColor.b = texture2D(Texture_GammaRamps, vec2(gl_FragColor.b, 0)).b;\n"
800 "#endif\n"
801 "}\n"
802 "#endif\n"
803 "#else // !MODE_POSTPROCESS\n"
804 "\n"
805 "\n"
806 "\n"
807 "\n"
808 "#ifdef MODE_GENERIC\n"
809 "#ifdef USEDIFFUSE\n"
810 "varying mediump vec2 TexCoord1;\n"
811 "#endif\n"
812 "#ifdef USESPECULAR\n"
813 "varying mediump vec2 TexCoord2;\n"
814 "#endif\n"
815 "#ifdef VERTEX_SHADER\n"
816 "void main(void)\n"
817 "{\n"
818 "       VertexColor = Attrib_Color;\n"
819 "#ifdef USEDIFFUSE\n"
820 "       TexCoord1 = Attrib_TexCoord0.xy;\n"
821 "#endif\n"
822 "#ifdef USESPECULAR\n"
823 "       TexCoord2 = Attrib_TexCoord1.xy;\n"
824 "#endif\n"
825 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
826 "}\n"
827 "#endif\n"
828 "\n"
829 "#ifdef FRAGMENT_SHADER\n"
830 "#ifdef USEDIFFUSE\n"
831 "uniform sampler2D Texture_First;\n"
832 "#endif\n"
833 "#ifdef USESPECULAR\n"
834 "uniform sampler2D Texture_Second;\n"
835 "#endif\n"
836 "\n"
837 "void main(void)\n"
838 "{\n"
839 "#ifdef USEVIEWTINT\n"
840 "       gl_FragColor = VertexColor;\n"
841 "#else\n"
842 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
843 "#endif\n"
844 "#ifdef USEDIFFUSE\n"
845 "       gl_FragColor *= texture2D(Texture_First, TexCoord1);\n"
846 "#endif\n"
847 "\n"
848 "#ifdef USESPECULAR\n"
849 "       vec4 tex2 = texture2D(Texture_Second, TexCoord2);\n"
850 "# ifdef USECOLORMAPPING\n"
851 "       gl_FragColor *= tex2;\n"
852 "# endif\n"
853 "# ifdef USEGLOW\n"
854 "       gl_FragColor += tex2;\n"
855 "# endif\n"
856 "# ifdef USEVERTEXTEXTUREBLEND\n"
857 "       gl_FragColor = mix(gl_FragColor, tex2, tex2.a);\n"
858 "# endif\n"
859 "#endif\n"
860 "}\n"
861 "#endif\n"
862 "#else // !MODE_GENERIC\n"
863 "\n"
864 "\n"
865 "\n"
866 "\n"
867 "#ifdef MODE_BLOOMBLUR\n"
868 "varying mediump vec2 TexCoord;\n"
869 "#ifdef VERTEX_SHADER\n"
870 "void main(void)\n"
871 "{\n"
872 "       VertexColor = Attrib_Color;\n"
873 "       TexCoord = Attrib_TexCoord0.xy;\n"
874 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
875 "}\n"
876 "#endif\n"
877 "\n"
878 "#ifdef FRAGMENT_SHADER\n"
879 "uniform sampler2D Texture_First;\n"
880 "uniform mediump vec4 BloomBlur_Parameters;\n"
881 "\n"
882 "void main(void)\n"
883 "{\n"
884 "       int i;\n"
885 "       vec2 tc = TexCoord;\n"
886 "       vec3 color = texture2D(Texture_First, tc).rgb;\n"
887 "       tc += BloomBlur_Parameters.xy;\n"
888 "       for (i = 1;i < SAMPLES;i++)\n"
889 "       {\n"
890 "               color += texture2D(Texture_First, tc).rgb;\n"
891 "               tc += BloomBlur_Parameters.xy;\n"
892 "       }\n"
893 "       gl_FragColor = vec4(color * BloomBlur_Parameters.z + vec3(BloomBlur_Parameters.w), 1);\n"
894 "}\n"
895 "#endif\n"
896 "#else // !MODE_BLOOMBLUR\n"
897 "#ifdef MODE_REFRACTION\n"
898 "varying mediump vec2 TexCoord;\n"
899 "varying highp vec4 ModelViewProjectionPosition;\n"
900 "uniform highp mat4 TexMatrix;\n"
901 "#ifdef VERTEX_SHADER\n"
902 "\n"
903 "void main(void)\n"
904 "{\n"
905 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
906 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
907 "       ModelViewProjectionPosition = gl_Position;\n"
908 "}\n"
909 "#endif\n"
910 "\n"
911 "#ifdef FRAGMENT_SHADER\n"
912 "uniform sampler2D Texture_Normal;\n"
913 "uniform sampler2D Texture_Refraction;\n"
914 "uniform sampler2D Texture_Reflection;\n"
915 "\n"
916 "uniform mediump vec4 DistortScaleRefractReflect;\n"
917 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
918 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
919 "uniform lowp vec4 RefractColor;\n"
920 "uniform lowp vec4 ReflectColor;\n"
921 "uniform mediump float ReflectFactor;\n"
922 "uniform mediump float ReflectOffset;\n"
923 "\n"
924 "void main(void)\n"
925 "{\n"
926 "       vec2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
927 "       //vec2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
928 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
929 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xy * DistortScaleRefractReflect.xy;\n"
930 "       // FIXME temporary hack to detect the case that the reflection\n"
931 "       // gets blackened at edges due to leaving the area that contains actual\n"
932 "       // content.\n"
933 "       // Remove this 'ack once we have a better way to stop this thing from\n"
934 "       // 'appening.\n"
935 "       float f = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
936 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
937 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
938 "       f      *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
939 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
940 "       gl_FragColor = vec4(texture2D(Texture_Refraction, ScreenTexCoord).rgb, 1.0) * RefractColor;\n"
941 "}\n"
942 "#endif\n"
943 "#else // !MODE_REFRACTION\n"
944 "\n"
945 "\n"
946 "\n"
947 "\n"
948 "#ifdef MODE_WATER\n"
949 "varying mediump vec2 TexCoord;\n"
950 "varying highp vec3 EyeVector;\n"
951 "varying highp vec4 ModelViewProjectionPosition;\n"
952 "#ifdef VERTEX_SHADER\n"
953 "uniform highp vec3 EyePosition;\n"
954 "uniform highp mat4 TexMatrix;\n"
955 "\n"
956 "void main(void)\n"
957 "{\n"
958 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
959 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
960 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
961 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
962 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
963 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
964 "       ModelViewProjectionPosition = gl_Position;\n"
965 "}\n"
966 "#endif\n"
967 "\n"
968 "#ifdef FRAGMENT_SHADER\n"
969 "uniform sampler2D Texture_Normal;\n"
970 "uniform sampler2D Texture_Refraction;\n"
971 "uniform sampler2D Texture_Reflection;\n"
972 "\n"
973 "uniform mediump vec4 DistortScaleRefractReflect;\n"
974 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
975 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
976 "uniform lowp vec4 RefractColor;\n"
977 "uniform lowp vec4 ReflectColor;\n"
978 "uniform mediump float ReflectFactor;\n"
979 "uniform mediump float ReflectOffset;\n"
980 "uniform highp float ClientTime;\n"
981 "#ifdef USENORMALMAPSCROLLBLEND\n"
982 "uniform highp vec2 NormalmapScrollBlend;\n"
983 "#endif\n"
984 "\n"
985 "void main(void)\n"
986 "{\n"
987 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
988 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
989 "       vec4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
990 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * vec4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
991 "       // slight water animation via 2 layer scrolling (todo: tweak)\n"
992 "       #ifdef USENORMALMAPSCROLLBLEND\n"
993 "               vec3 normal = texture2D(Texture_Normal, (TexCoord + vec2(0.08, 0.08)*ClientTime*NormalmapScrollBlend.x*0.5)*NormalmapScrollBlend.y).rgb - vec3(1.0);\n"
994 "               normal += texture2D(Texture_Normal, (TexCoord + vec2(-0.06, -0.09)*ClientTime*NormalmapScrollBlend.x)*NormalmapScrollBlend.y*0.75).rgb;\n"
995 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(normal) + vec3(0.15)).xyxy * DistortScaleRefractReflect;\n"
996 "       #else\n"
997 "               vec4 ScreenTexCoord = SafeScreenTexCoord + vec2(normalize(vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5))).xyxy * DistortScaleRefractReflect;\n"
998 "       #endif\n"
999 "       // FIXME temporary hack to detect the case that the reflection\n"
1000 "       // gets blackened at edges due to leaving the area that contains actual\n"
1001 "       // content.\n"
1002 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1003 "       // 'appening.\n"
1004 "       float f  = min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, 0.01)).rgb) / 0.002);\n"
1005 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(0.005, -0.01)).rgb) / 0.002);\n"
1006 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, 0.01)).rgb) / 0.002);\n"
1007 "       f       *= min(1.0, length(texture2D(Texture_Refraction, ScreenTexCoord.xy + vec2(-0.005, -0.01)).rgb) / 0.002);\n"
1008 "       ScreenTexCoord.xy = mix(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
1009 "       f  = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, 0.005)).rgb) / 0.002);\n"
1010 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(0.005, -0.005)).rgb) / 0.002);\n"
1011 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, 0.005)).rgb) / 0.002);\n"
1012 "       f *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord.zw + vec2(-0.005, -0.005)).rgb) / 0.002);\n"
1013 "       ScreenTexCoord.zw = mix(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
1014 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
1015 "       gl_FragColor = mix(vec4(texture2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, vec4(texture2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
1016 "}\n"
1017 "#endif\n"
1018 "#else // !MODE_WATER\n"
1019 "\n"
1020 "\n"
1021 "\n"
1022 "\n"
1023 "// common definitions between vertex shader and fragment shader:\n"
1024 "\n"
1025 "varying mediump vec2 TexCoord;\n"
1026 "#ifdef USEVERTEXTEXTUREBLEND\n"
1027 "varying mediump vec2 TexCoord2;\n"
1028 "#endif\n"
1029 "#ifdef USELIGHTMAP\n"
1030 "varying mediump vec2 TexCoordLightmap;\n"
1031 "#endif\n"
1032 "\n"
1033 "#ifdef MODE_LIGHTSOURCE\n"
1034 "varying mediump vec3 CubeVector;\n"
1035 "#endif\n"
1036 "\n"
1037 "#if (defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)) && defined(USEDIFFUSE)\n"
1038 "varying mediump vec3 LightVector;\n"
1039 "#endif\n"
1040 "\n"
1041 "#ifdef USEEYEVECTOR\n"
1042 "varying highp vec3 EyeVector;\n"
1043 "#endif\n"
1044 "#ifdef USEFOG\n"
1045 "varying highp vec4 EyeVectorModelSpaceFogPlaneVertexDist;\n"
1046 "#endif\n"
1047 "\n"
1048 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
1049 "varying lowp vec3 VectorS; // direction of S texcoord (sometimes crudely called tangent)\n"
1050 "varying lowp vec3 VectorT; // direction of T texcoord (sometimes crudely called binormal)\n"
1051 "varying lowp vec3 VectorR; // direction of R texcoord (surface normal)\n"
1052 "#endif\n"
1053 "\n"
1054 "#ifdef USEREFLECTION\n"
1055 "varying highp vec4 ModelViewProjectionPosition;\n"
1056 "#endif\n"
1057 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1058 "uniform highp vec3 LightPosition;\n"
1059 "varying highp vec4 ModelViewPosition;\n"
1060 "#endif\n"
1061 "\n"
1062 "#ifdef MODE_LIGHTSOURCE\n"
1063 "uniform highp vec3 LightPosition;\n"
1064 "#endif\n"
1065 "uniform highp vec3 EyePosition;\n"
1066 "#ifdef MODE_LIGHTDIRECTION\n"
1067 "uniform highp vec3 LightDir;\n"
1068 "#endif\n"
1069 "uniform highp vec4 FogPlane;\n"
1070 "\n"
1071 "#ifdef USESHADOWMAPORTHO\n"
1072 "varying mediump vec3 ShadowMapTC;\n"
1073 "#endif\n"
1074 "\n"
1075 "#ifdef USEBOUNCEGRID\n"
1076 "varying mediump vec3 BounceGridTexCoord;\n"
1077 "#endif\n"
1078 "\n"
1079 "\n"
1080 "\n"
1081 "\n"
1082 "\n"
1083 "\n"
1084 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
1085 "\n"
1086 "// fragment shader specific:\n"
1087 "#ifdef FRAGMENT_SHADER\n"
1088 "\n"
1089 "uniform sampler2D Texture_Normal;\n"
1090 "uniform sampler2D Texture_Color;\n"
1091 "uniform sampler2D Texture_Gloss;\n"
1092 "#ifdef USEGLOW\n"
1093 "uniform sampler2D Texture_Glow;\n"
1094 "#endif\n"
1095 "#ifdef USEVERTEXTEXTUREBLEND\n"
1096 "uniform sampler2D Texture_SecondaryNormal;\n"
1097 "uniform sampler2D Texture_SecondaryColor;\n"
1098 "uniform sampler2D Texture_SecondaryGloss;\n"
1099 "#ifdef USEGLOW\n"
1100 "uniform sampler2D Texture_SecondaryGlow;\n"
1101 "#endif\n"
1102 "#endif\n"
1103 "#ifdef USECOLORMAPPING\n"
1104 "uniform sampler2D Texture_Pants;\n"
1105 "uniform sampler2D Texture_Shirt;\n"
1106 "#endif\n"
1107 "#ifdef USEFOG\n"
1108 "#ifdef USEFOGHEIGHTTEXTURE\n"
1109 "uniform sampler2D Texture_FogHeightTexture;\n"
1110 "#endif\n"
1111 "uniform sampler2D Texture_FogMask;\n"
1112 "#endif\n"
1113 "#ifdef USELIGHTMAP\n"
1114 "uniform sampler2D Texture_Lightmap;\n"
1115 "#endif\n"
1116 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1117 "uniform sampler2D Texture_Deluxemap;\n"
1118 "#endif\n"
1119 "#ifdef USEREFLECTION\n"
1120 "uniform sampler2D Texture_Reflection;\n"
1121 "#endif\n"
1122 "\n"
1123 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1124 "uniform sampler2D Texture_ScreenDepth;\n"
1125 "uniform sampler2D Texture_ScreenNormalMap;\n"
1126 "#endif\n"
1127 "#ifdef USEDEFERREDLIGHTMAP\n"
1128 "uniform sampler2D Texture_ScreenDiffuse;\n"
1129 "uniform sampler2D Texture_ScreenSpecular;\n"
1130 "#endif\n"
1131 "\n"
1132 "uniform lowp vec3 Color_Pants;\n"
1133 "uniform lowp vec3 Color_Shirt;\n"
1134 "uniform lowp vec3 FogColor;\n"
1135 "\n"
1136 "#ifdef USEFOG\n"
1137 "uniform highp float FogRangeRecip;\n"
1138 "uniform highp float FogPlaneViewDist;\n"
1139 "uniform highp float FogHeightFade;\n"
1140 "vec3 FogVertex(vec3 surfacecolor)\n"
1141 "{\n"
1142 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1143 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1144 "       float fogfrac;\n"
1145 "#ifdef USEFOGHEIGHTTEXTURE\n"
1146 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1147 "       fogfrac = fogheightpixel.a;\n"
1148 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1149 "#else\n"
1150 "# ifdef USEFOGOUTSIDE\n"
1151 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1152 "# else\n"
1153 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1154 "# endif\n"
1155 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1156 "#endif\n"
1157 "}\n"
1158 "#endif\n"
1159 "\n"
1160 "#ifdef USEOFFSETMAPPING\n"
1161 "uniform mediump float OffsetMapping_Scale;\n"
1162 "vec2 OffsetMapping(vec2 TexCoord)\n"
1163 "{\n"
1164 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1165 "       // 14 sample relief mapping: linear search and then binary search\n"
1166 "       // this basically steps forward a small amount repeatedly until it finds\n"
1167 "       // itself inside solid, then jitters forward and back using decreasing\n"
1168 "       // amounts to find the impact\n"
1169 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1170 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1171 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1172 "       vec3 RT = vec3(TexCoord, 1);\n"
1173 "       OffsetVector *= 0.1;\n"
1174 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1175 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1176 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1177 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1178 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1179 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1180 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1181 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1182 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1183 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1184 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1185 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1186 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1187 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1188 "       return RT.xy;\n"
1189 "#else\n"
1190 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1191 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1192 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1193 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1194 "       OffsetVector *= 0.5;\n"
1195 "       TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1196 "       TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1197 "       return TexCoord;\n"
1198 "#endif\n"
1199 "}\n"
1200 "#endif // USEOFFSETMAPPING\n"
1201 "\n"
1202 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1203 "uniform sampler2D Texture_Attenuation;\n"
1204 "uniform samplerCube Texture_Cube;\n"
1205 "#endif\n"
1206 "\n"
1207 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1208 "\n"
1209 "#ifdef USESHADOWMAP2D\n"
1210 "# ifdef USESHADOWSAMPLER\n"
1211 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1212 "# else\n"
1213 "uniform sampler2D Texture_ShadowMap2D;\n"
1214 "# endif\n"
1215 "#endif\n"
1216 "\n"
1217 "#ifdef USESHADOWMAPVSDCT\n"
1218 "uniform samplerCube Texture_CubeProjection;\n"
1219 "#endif\n"
1220 "\n"
1221 "#if defined(USESHADOWMAP2D)\n"
1222 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1223 "uniform mediump vec4 ShadowMap_Parameters;\n"
1224 "#endif\n"
1225 "\n"
1226 "#if defined(USESHADOWMAP2D)\n"
1227 "# ifdef USESHADOWMAPORTHO\n"
1228 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1229 "# else\n"
1230 "#  ifdef USESHADOWMAPVSDCT\n"
1231 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1232 "{\n"
1233 "       vec3 adir = abs(dir);\n"
1234 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1235 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1236 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1237 "}\n"
1238 "#  else\n"
1239 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1240 "{\n"
1241 "       vec3 adir = abs(dir);\n"
1242 "       float ma = adir.z;\n"
1243 "       vec4 proj = vec4(dir, 2.5);\n"
1244 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1245 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1246 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1247 "       return vec3(proj.xy * aparams.x + vec2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1248 "}\n"
1249 "#  endif\n"
1250 "# endif\n"
1251 "#endif // defined(USESHADOWMAP2D)\n"
1252 "\n"
1253 "# ifdef USESHADOWMAP2D\n"
1254 "float ShadowMapCompare(vec3 dir)\n"
1255 "{\n"
1256 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1257 "       float f;\n"
1258 "\n"
1259 "#  ifdef USESHADOWSAMPLER\n"
1260 "#    ifdef USESHADOWMAPPCF\n"
1261 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1262 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1263 "       f = dot(vec4(0.25), vec4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
1264 "#    else\n"
1265 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1266 "#    endif\n"
1267 "#  else\n"
1268 "#    ifdef USESHADOWMAPPCF\n"
1269 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1270 "#      ifdef GL_ARB_texture_gather\n"
1271 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1272 "#      else\n"
1273 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1274 "#      endif\n"
1275 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1276 "#      if USESHADOWMAPPCF > 1\n"
1277 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1278 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1279 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1280 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1281 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1282 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1283 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1284 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1285 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1286 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1287 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1288 "       locols.yz += group2.ab;\n"
1289 "       hicols.yz += group8.rg;\n"
1290 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1291 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1292 "                               mix(locols, hicols, offset.y);\n"
1293 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1294 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1295 "       f = dot(cols, vec4(1.0/25.0));\n"
1296 "#      else\n"
1297 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1298 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1299 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1300 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1301 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1302 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1303 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1304 "#      endif\n"
1305 "#     else\n"
1306 "#      ifdef GL_EXT_gpu_shader4\n"
1307 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1308 "#      else\n"
1309 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1310 "#      endif\n"
1311 "#      if USESHADOWMAPPCF > 1\n"
1312 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1313 "       center *= ShadowMap_TextureScale;\n"
1314 "       vec4 row1 = step(shadowmaptc.z, vec4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
1315 "       vec4 row2 = step(shadowmaptc.z, vec4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
1316 "       vec4 row3 = step(shadowmaptc.z, vec4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
1317 "       vec4 row4 = step(shadowmaptc.z, vec4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
1318 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1319 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1320 "#      else\n"
1321 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1322 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1323 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1324 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1325 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1326 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1327 "#      endif\n"
1328 "#     endif\n"
1329 "#    else\n"
1330 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1331 "#    endif\n"
1332 "#  endif\n"
1333 "#  ifdef USESHADOWMAPORTHO\n"
1334 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1335 "#  else\n"
1336 "       return f;\n"
1337 "#  endif\n"
1338 "}\n"
1339 "# endif\n"
1340 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1341 "#endif // FRAGMENT_SHADER\n"
1342 "\n"
1343 "\n"
1344 "\n"
1345 "\n"
1346 "#ifdef MODE_DEFERREDGEOMETRY\n"
1347 "#ifdef VERTEX_SHADER\n"
1348 "uniform highp mat4 TexMatrix;\n"
1349 "#ifdef USEVERTEXTEXTUREBLEND\n"
1350 "uniform highp mat4 BackgroundTexMatrix;\n"
1351 "#endif\n"
1352 "uniform highp mat4 ModelViewMatrix;\n"
1353 "void main(void)\n"
1354 "{\n"
1355 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1356 "#ifdef USEVERTEXTEXTUREBLEND\n"
1357 "       VertexColor = Attrib_Color;\n"
1358 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1359 "#endif\n"
1360 "\n"
1361 "       // transform unnormalized eye direction into tangent space\n"
1362 "#ifdef USEOFFSETMAPPING\n"
1363 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1364 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1365 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1366 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1367 "#endif\n"
1368 "\n"
1369 "       VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1370 "       VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1371 "       VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1372 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1373 "}\n"
1374 "#endif // VERTEX_SHADER\n"
1375 "\n"
1376 "#ifdef FRAGMENT_SHADER\n"
1377 "void main(void)\n"
1378 "{\n"
1379 "#ifdef USEOFFSETMAPPING\n"
1380 "       // apply offsetmapping\n"
1381 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1382 "#define TexCoord TexCoordOffset\n"
1383 "#endif\n"
1384 "\n"
1385 "#ifdef USEALPHAKILL\n"
1386 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1387 "               discard;\n"
1388 "#endif\n"
1389 "\n"
1390 "#ifdef USEVERTEXTEXTUREBLEND\n"
1391 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1392 "       float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1393 "       //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1394 "       //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1395 "#endif\n"
1396 "\n"
1397 "#ifdef USEVERTEXTEXTUREBLEND\n"
1398 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1399 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1400 "#else\n"
1401 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1402 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1403 "#endif\n"
1404 "\n"
1405 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1406 "}\n"
1407 "#endif // FRAGMENT_SHADER\n"
1408 "#else // !MODE_DEFERREDGEOMETRY\n"
1409 "\n"
1410 "\n"
1411 "\n"
1412 "\n"
1413 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1414 "#ifdef VERTEX_SHADER\n"
1415 "uniform highp mat4 ModelViewMatrix;\n"
1416 "void main(void)\n"
1417 "{\n"
1418 "       ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1419 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1420 "}\n"
1421 "#endif // VERTEX_SHADER\n"
1422 "\n"
1423 "#ifdef FRAGMENT_SHADER\n"
1424 "uniform highp mat4 ViewToLight;\n"
1425 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1426 "uniform highp vec2 ScreenToDepth;\n"
1427 "uniform myhalf3 DeferredColor_Ambient;\n"
1428 "uniform myhalf3 DeferredColor_Diffuse;\n"
1429 "#ifdef USESPECULAR\n"
1430 "uniform myhalf3 DeferredColor_Specular;\n"
1431 "uniform myhalf SpecularPower;\n"
1432 "#endif\n"
1433 "uniform myhalf2 PixelToScreenTexCoord;\n"
1434 "void main(void)\n"
1435 "{\n"
1436 "       // calculate viewspace pixel position\n"
1437 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1438 "       vec3 position;\n"
1439 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1440 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1441 "       // decode viewspace pixel normal\n"
1442 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1443 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1444 "       // surfacenormal = pixel normal in viewspace\n"
1445 "       // LightVector = pixel to light in viewspace\n"
1446 "       // CubeVector = position in lightspace\n"
1447 "       // eyevector = pixel to view in viewspace\n"
1448 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1449 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1450 "#ifdef USEDIFFUSE\n"
1451 "       // calculate diffuse shading\n"
1452 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1453 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1454 "#endif\n"
1455 "#ifdef USESPECULAR\n"
1456 "       // calculate directional shading\n"
1457 "       vec3 eyevector = position * -1.0;\n"
1458 "#  ifdef USEEXACTSPECULARMATH\n"
1459 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1460 "#  else\n"
1461 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1462 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1463 "#  endif\n"
1464 "#endif\n"
1465 "\n"
1466 "#if defined(USESHADOWMAP2D)\n"
1467 "       fade *= ShadowMapCompare(CubeVector);\n"
1468 "#endif\n"
1469 "\n"
1470 "#ifdef USEDIFFUSE\n"
1471 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1472 "#else\n"
1473 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1474 "#endif\n"
1475 "#ifdef USESPECULAR\n"
1476 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1477 "#else\n"
1478 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1479 "#endif\n"
1480 "\n"
1481 "# ifdef USECUBEFILTER\n"
1482 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1483 "       gl_FragData[0].rgb *= cubecolor;\n"
1484 "       gl_FragData[1].rgb *= cubecolor;\n"
1485 "# endif\n"
1486 "}\n"
1487 "#endif // FRAGMENT_SHADER\n"
1488 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1489 "\n"
1490 "\n"
1491 "\n"
1492 "\n"
1493 "#ifdef VERTEX_SHADER\n"
1494 "uniform highp mat4 TexMatrix;\n"
1495 "#ifdef USEVERTEXTEXTUREBLEND\n"
1496 "uniform highp mat4 BackgroundTexMatrix;\n"
1497 "#endif\n"
1498 "#ifdef MODE_LIGHTSOURCE\n"
1499 "uniform highp mat4 ModelToLight;\n"
1500 "#endif\n"
1501 "#ifdef USESHADOWMAPORTHO\n"
1502 "uniform highp mat4 ShadowMapMatrix;\n"
1503 "#endif\n"
1504 "#ifdef USEBOUNCEGRID\n"
1505 "uniform highp mat4 BounceGridMatrix;\n"
1506 "#endif\n"
1507 "void main(void)\n"
1508 "{\n"
1509 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1510 "       VertexColor = Attrib_Color;\n"
1511 "#endif\n"
1512 "       // copy the surface texcoord\n"
1513 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1514 "#ifdef USEVERTEXTEXTUREBLEND\n"
1515 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1516 "#endif\n"
1517 "#ifdef USELIGHTMAP\n"
1518 "       TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1519 "#endif\n"
1520 "\n"
1521 "#ifdef USEBOUNCEGRID\n"
1522 "       BounceGridTexCoord = vec3(BounceGridMatrix * Attrib_Position);\n"
1523 "#endif\n"
1524 "\n"
1525 "#ifdef MODE_LIGHTSOURCE\n"
1526 "       // transform vertex position into light attenuation/cubemap space\n"
1527 "       // (-1 to +1 across the light box)\n"
1528 "       CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1529 "\n"
1530 "# ifdef USEDIFFUSE\n"
1531 "       // transform unnormalized light direction into tangent space\n"
1532 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1533 "       //  normalize it per pixel)\n"
1534 "       vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1535 "       LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1536 "       LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1537 "       LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1538 "# endif\n"
1539 "#endif\n"
1540 "\n"
1541 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1542 "       LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1543 "       LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1544 "       LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1545 "#endif\n"
1546 "\n"
1547 "       // transform unnormalized eye direction into tangent space\n"
1548 "#ifdef USEEYEVECTOR\n"
1549 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1550 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1551 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1552 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1553 "#endif\n"
1554 "\n"
1555 "#ifdef USEFOG\n"
1556 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1557 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1558 "#endif\n"
1559 "\n"
1560 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1561 "       VectorS = Attrib_TexCoord1.xyz;\n"
1562 "       VectorT = Attrib_TexCoord2.xyz;\n"
1563 "       VectorR = Attrib_TexCoord3.xyz;\n"
1564 "#endif\n"
1565 "\n"
1566 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1567 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1568 "\n"
1569 "#ifdef USESHADOWMAPORTHO\n"
1570 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1571 "#endif\n"
1572 "\n"
1573 "#ifdef USEREFLECTION\n"
1574 "       ModelViewProjectionPosition = gl_Position;\n"
1575 "#endif\n"
1576 "}\n"
1577 "#endif // VERTEX_SHADER\n"
1578 "\n"
1579 "\n"
1580 "\n"
1581 "\n"
1582 "#ifdef FRAGMENT_SHADER\n"
1583 "#ifdef USEDEFERREDLIGHTMAP\n"
1584 "uniform myhalf2 PixelToScreenTexCoord;\n"
1585 "uniform myhalf3 DeferredMod_Diffuse;\n"
1586 "uniform myhalf3 DeferredMod_Specular;\n"
1587 "#endif\n"
1588 "uniform myhalf3 Color_Ambient;\n"
1589 "uniform myhalf3 Color_Diffuse;\n"
1590 "uniform myhalf3 Color_Specular;\n"
1591 "uniform myhalf SpecularPower;\n"
1592 "#ifdef USEGLOW\n"
1593 "uniform myhalf3 Color_Glow;\n"
1594 "#endif\n"
1595 "uniform myhalf Alpha;\n"
1596 "#ifdef USEREFLECTION\n"
1597 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1598 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1599 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1600 "uniform lowp vec4 ReflectColor;\n"
1601 "#endif\n"
1602 "#ifdef USEREFLECTCUBE\n"
1603 "uniform highp mat4 ModelToReflectCube;\n"
1604 "uniform sampler2D Texture_ReflectMask;\n"
1605 "uniform samplerCube Texture_ReflectCube;\n"
1606 "#endif\n"
1607 "#ifdef MODE_LIGHTDIRECTION\n"
1608 "uniform myhalf3 LightColor;\n"
1609 "#endif\n"
1610 "#ifdef MODE_LIGHTSOURCE\n"
1611 "uniform myhalf3 LightColor;\n"
1612 "#endif\n"
1613 "#ifdef USEBOUNCEGRID\n"
1614 "uniform sampler3D Texture_BounceGrid;\n"
1615 "uniform float BounceGridIntensity;\n"
1616 "#endif\n"
1617 "void main(void)\n"
1618 "{\n"
1619 "#ifdef USEOFFSETMAPPING\n"
1620 "       // apply offsetmapping\n"
1621 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1622 "#define TexCoord TexCoordOffset\n"
1623 "#endif\n"
1624 "\n"
1625 "       // combine the diffuse textures (base, pants, shirt)\n"
1626 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1627 "#ifdef USEALPHAKILL\n"
1628 "       if (color.a < 0.5)\n"
1629 "               discard;\n"
1630 "#endif\n"
1631 "       color.a *= Alpha;\n"
1632 "#ifdef USECOLORMAPPING\n"
1633 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1634 "#endif\n"
1635 "#ifdef USEVERTEXTEXTUREBLEND\n"
1636 "       myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1637 "       //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1638 "       //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1639 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1640 "       color.a = 1.0;\n"
1641 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1642 "#endif\n"
1643 "\n"
1644 "       // get the surface normal\n"
1645 "#ifdef USEVERTEXTEXTUREBLEND\n"
1646 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1647 "#else\n"
1648 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1649 "#endif\n"
1650 "\n"
1651 "       // get the material colors\n"
1652 "       myhalf3 diffusetex = color.rgb;\n"
1653 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1654 "# ifdef USEVERTEXTEXTUREBLEND\n"
1655 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1656 "# else\n"
1657 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1658 "# endif\n"
1659 "#endif\n"
1660 "\n"
1661 "#ifdef USEREFLECTCUBE\n"
1662 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1663 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1664 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1665 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1666 "#endif\n"
1667 "\n"
1668 "\n"
1669 "\n"
1670 "\n"
1671 "#ifdef MODE_LIGHTSOURCE\n"
1672 "       // light source\n"
1673 "#ifdef USEDIFFUSE\n"
1674 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1675 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1676 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1677 "#ifdef USESPECULAR\n"
1678 "#ifdef USEEXACTSPECULARMATH\n"
1679 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1680 "#else\n"
1681 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1682 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1683 "#endif\n"
1684 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1685 "#endif\n"
1686 "#else\n"
1687 "       color.rgb = diffusetex * Color_Ambient;\n"
1688 "#endif\n"
1689 "       color.rgb *= LightColor;\n"
1690 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1691 "#if defined(USESHADOWMAP2D)\n"
1692 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1693 "#endif\n"
1694 "# ifdef USECUBEFILTER\n"
1695 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1696 "# endif\n"
1697 "#endif // MODE_LIGHTSOURCE\n"
1698 "\n"
1699 "\n"
1700 "\n"
1701 "\n"
1702 "#ifdef MODE_LIGHTDIRECTION\n"
1703 "#define SHADING\n"
1704 "#ifdef USEDIFFUSE\n"
1705 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1706 "#endif\n"
1707 "#define lightcolor LightColor\n"
1708 "#endif // MODE_LIGHTDIRECTION\n"
1709 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1710 "#define SHADING\n"
1711 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1712 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1713 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1714 "       // convert modelspace light vector to tangentspace\n"
1715 "       myhalf3 lightnormal;\n"
1716 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1717 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1718 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1719 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1720 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1721 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1722 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1723 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1724 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1725 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1726 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1727 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1728 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1729 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1730 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1731 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1732 "#define SHADING\n"
1733 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1734 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1735 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1736 "#endif\n"
1737 "\n"
1738 "\n"
1739 "\n"
1740 "\n"
1741 "#ifdef MODE_FAKELIGHT\n"
1742 "#define SHADING\n"
1743 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1744 "myhalf3 lightcolor = myhalf3(1.0);\n"
1745 "#endif // MODE_FAKELIGHT\n"
1746 "\n"
1747 "\n"
1748 "\n"
1749 "\n"
1750 "#ifdef MODE_LIGHTMAP\n"
1751 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1752 "#endif // MODE_LIGHTMAP\n"
1753 "#ifdef MODE_VERTEXCOLOR\n"
1754 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1755 "#endif // MODE_VERTEXCOLOR\n"
1756 "#ifdef MODE_FLATCOLOR\n"
1757 "       color.rgb = diffusetex * Color_Ambient;\n"
1758 "#endif // MODE_FLATCOLOR\n"
1759 "\n"
1760 "\n"
1761 "\n"
1762 "\n"
1763 "#ifdef SHADING\n"
1764 "# ifdef USEDIFFUSE\n"
1765 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1766 "#  ifdef USESPECULAR\n"
1767 "#   ifdef USEEXACTSPECULARMATH\n"
1768 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1769 "#   else\n"
1770 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1771 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1772 "#   endif\n"
1773 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1774 "#  else\n"
1775 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1776 "#  endif\n"
1777 "# else\n"
1778 "       color.rgb = diffusetex * Color_Ambient;\n"
1779 "# endif\n"
1780 "#endif\n"
1781 "\n"
1782 "#ifdef USESHADOWMAPORTHO\n"
1783 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1784 "#endif\n"
1785 "\n"
1786 "#ifdef USEDEFERREDLIGHTMAP\n"
1787 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1788 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1789 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1790 "#endif\n"
1791 "\n"
1792 "#ifdef USEBOUNCEGRID\n"
1793 "       color.rgb += diffusetex * myhalf3(texture3D(Texture_BounceGrid, BounceGridTexCoord)) * BounceGridIntensity;\n"
1794 "#endif\n"
1795 "\n"
1796 "#ifdef USEGLOW\n"
1797 "#ifdef USEVERTEXTEXTUREBLEND\n"
1798 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1799 "#else\n"
1800 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1801 "#endif\n"
1802 "#endif\n"
1803 "\n"
1804 "#ifdef USEFOG\n"
1805 "       color.rgb = FogVertex(color.rgb);\n"
1806 "#endif\n"
1807 "\n"
1808 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
1809 "#ifdef USEREFLECTION\n"
1810 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1811 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1812 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1813 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1814 "       // FIXME temporary hack to detect the case that the reflection\n"
1815 "       // gets blackened at edges due to leaving the area that contains actual\n"
1816 "       // content.\n"
1817 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1818 "       // 'appening.\n"
1819 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1820 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1821 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1822 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1823 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1824 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1825 "#endif\n"
1826 "\n"
1827 "       gl_FragColor = vec4(color);\n"
1828 "}\n"
1829 "#endif // FRAGMENT_SHADER\n"
1830 "\n"
1831 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1832 "#endif // !MODE_DEFERREDGEOMETRY\n"
1833 "#endif // !MODE_WATER\n"
1834 "#endif // !MODE_REFRACTION\n"
1835 "#endif // !MODE_BLOOMBLUR\n"
1836 "#endif // !MODE_GENERIC\n"
1837 "#endif // !MODE_POSTPROCESS\n"
1838 "#endif // !MODE_SHOWDEPTH\n"
1839 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1840 ;
1841
1842 /*
1843 =========================================================================================================================================================
1844
1845
1846
1847 =========================================================================================================================================================
1848
1849
1850
1851 =========================================================================================================================================================
1852
1853
1854
1855 =========================================================================================================================================================
1856
1857
1858
1859 =========================================================================================================================================================
1860
1861
1862
1863 =========================================================================================================================================================
1864
1865
1866
1867 =========================================================================================================================================================
1868 */
1869
1870 const char *builtinhlslshaderstring =
1871 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1872 "// written by Forest 'LordHavoc' Hale\n"
1873 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1874 "\n"
1875 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1876 "#if defined(USEREFLECTION)\n"
1877 "#undef USESHADOWMAPORTHO\n"
1878 "#endif\n"
1879 "\n"
1880 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1881 "# define USEFOG\n"
1882 "#endif\n"
1883 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1884 "#define USELIGHTMAP\n"
1885 "#endif\n"
1886 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1887 "#define USEEYEVECTOR\n"
1888 "#endif\n"
1889 "\n"
1890 "#ifdef FRAGMENT_SHADER\n"
1891 "#ifdef HLSL\n"
1892 "//#undef USESHADOWMAPPCF\n"
1893 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1894 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1895 "#else\n"
1896 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1897 "#endif\n"
1898 "#endif\n"
1899 "\n"
1900 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1901 "#ifdef VERTEX_SHADER\n"
1902 "void main\n"
1903 "(\n"
1904 "float4 gl_Vertex : POSITION,\n"
1905 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1906 "out float4 gl_Position : POSITION,\n"
1907 "out float Depth : TEXCOORD0\n"
1908 ")\n"
1909 "{\n"
1910 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1911 "       Depth = gl_Position.z;\n"
1912 "}\n"
1913 "#endif\n"
1914 "\n"
1915 "#ifdef FRAGMENT_SHADER\n"
1916 "void main\n"
1917 "(\n"
1918 "float Depth : TEXCOORD0,\n"
1919 "out float4 gl_FragColor : COLOR\n"
1920 ")\n"
1921 "{\n"
1922 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1923 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1924 "       temp.yz -= floor(temp.yz);\n"
1925 "       gl_FragColor = temp;\n"
1926 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1927 "}\n"
1928 "#endif\n"
1929 "#else // !MODE_DEPTH_ORSHADOW\n"
1930 "\n"
1931 "\n"
1932 "\n"
1933 "\n"
1934 "#ifdef MODE_SHOWDEPTH\n"
1935 "#ifdef VERTEX_SHADER\n"
1936 "void main\n"
1937 "(\n"
1938 "float4 gl_Vertex : POSITION,\n"
1939 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1940 "out float4 gl_Position : POSITION,\n"
1941 "out float4 gl_FrontColor : COLOR0\n"
1942 ")\n"
1943 "{\n"
1944 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1945 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1946 "}\n"
1947 "#endif\n"
1948 "\n"
1949 "#ifdef FRAGMENT_SHADER\n"
1950 "void main\n"
1951 "(\n"
1952 "float4 gl_FrontColor : COLOR0,\n"
1953 "out float4 gl_FragColor : COLOR\n"
1954 ")\n"
1955 "{\n"
1956 "       gl_FragColor = gl_FrontColor;\n"
1957 "}\n"
1958 "#endif\n"
1959 "#else // !MODE_SHOWDEPTH\n"
1960 "\n"
1961 "\n"
1962 "\n"
1963 "\n"
1964 "#ifdef MODE_POSTPROCESS\n"
1965 "\n"
1966 "#ifdef VERTEX_SHADER\n"
1967 "void main\n"
1968 "(\n"
1969 "float4 gl_Vertex : POSITION,\n"
1970 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1971 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
1972 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
1973 "out float4 gl_Position : POSITION,\n"
1974 "out float2 TexCoord1 : TEXCOORD0,\n"
1975 "out float2 TexCoord2 : TEXCOORD1\n"
1976 ")\n"
1977 "{\n"
1978 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1979 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
1980 "#ifdef USEBLOOM\n"
1981 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
1982 "#endif\n"
1983 "}\n"
1984 "#endif\n"
1985 "\n"
1986 "#ifdef FRAGMENT_SHADER\n"
1987 "void main\n"
1988 "(\n"
1989 "float2 TexCoord1 : TEXCOORD0,\n"
1990 "float2 TexCoord2 : TEXCOORD1,\n"
1991 "uniform sampler Texture_First : register(s0),\n"
1992 "#ifdef USEBLOOM\n"
1993 "uniform sampler Texture_Second : register(s1),\n"
1994 "#endif\n"
1995 "#ifdef USEGAMMARAMPS\n"
1996 "uniform sampler Texture_GammaRamps : register(s2),\n"
1997 "#endif\n"
1998 "#ifdef USESATURATION\n"
1999 "uniform float Saturation : register(c30),\n"
2000 "#endif\n"
2001 "#ifdef USEVIEWTINT\n"
2002 "uniform float4 ViewTintColor : register(c41),\n"
2003 "#endif\n"
2004 "uniform float4 UserVec1 : register(c37),\n"
2005 "uniform float4 UserVec2 : register(c38),\n"
2006 "uniform float4 UserVec3 : register(c39),\n"
2007 "uniform float4 UserVec4 : register(c40),\n"
2008 "uniform float ClientTime : register(c2),\n"
2009 "uniform float2 PixelSize : register(c25),\n"
2010 "uniform float4 BloomColorSubtract : register(c43),\n"
2011 "out float4 gl_FragColor : COLOR\n"
2012 ")\n"
2013 "{\n"
2014 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2015 "#ifdef USEBLOOM\n"
2016 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2017 "#endif\n"
2018 "#ifdef USEVIEWTINT\n"
2019 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2020 "#endif\n"
2021 "\n"
2022 "#ifdef USEPOSTPROCESSING\n"
2023 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2024 "// this code does a blur with the radius specified in the first component of r_glsl_postprocess_uservec1 and blends it using the second component\n"
2025 "       float sobel = 1.0;\n"
2026 "       // float2 ts = textureSize(Texture_First, 0);\n"
2027 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2028 "       float2 px = PixelSize;\n"
2029 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2030 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2031 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2032 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2033 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2034 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2035 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2036 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2037 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2038 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2039 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2040 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2041 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2042 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2043 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2044 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2045 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2046 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2047 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2048 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2049 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2050 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2051 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2052 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2053 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2054 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2055 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2056 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2057 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2058 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2059 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2060 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2061 "#endif\n"
2062 "\n"
2063 "#ifdef USESATURATION\n"
2064 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2065 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2066 "       // 'vampire sight' effect, wheres red is compensated\n"
2067 "       #ifdef SATURATION_REDCOMPENSATE\n"
2068 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2069 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2070 "               gl_FragColor.r += r;\n"
2071 "       #else\n"
2072 "               // normal desaturation\n"
2073 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2074 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2075 "       #endif\n"
2076 "#endif\n"
2077 "\n"
2078 "#ifdef USEGAMMARAMPS\n"
2079 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2080 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2081 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2082 "#endif\n"
2083 "}\n"
2084 "#endif\n"
2085 "#else // !MODE_POSTPROCESS\n"
2086 "\n"
2087 "\n"
2088 "\n"
2089 "\n"
2090 "#ifdef MODE_GENERIC\n"
2091 "#ifdef VERTEX_SHADER\n"
2092 "void main\n"
2093 "(\n"
2094 "float4 gl_Vertex : POSITION,\n"
2095 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2096 "float4 gl_Color : COLOR0,\n"
2097 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2098 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2099 "out float4 gl_Position : POSITION,\n"
2100 "#ifdef USEDIFFUSE\n"
2101 "out float2 TexCoord1 : TEXCOORD0,\n"
2102 "#endif\n"
2103 "#ifdef USESPECULAR\n"
2104 "out float2 TexCoord2 : TEXCOORD1,\n"
2105 "#endif\n"
2106 "out float4 gl_FrontColor : COLOR\n"
2107 ")\n"
2108 "{\n"
2109 "#ifdef HLSL\n"
2110 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2111 "#else\n"
2112 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2113 "#endif\n"
2114 "#ifdef USEDIFFUSE\n"
2115 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2116 "#endif\n"
2117 "#ifdef USESPECULAR\n"
2118 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2119 "#endif\n"
2120 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2121 "}\n"
2122 "#endif\n"
2123 "\n"
2124 "#ifdef FRAGMENT_SHADER\n"
2125 "\n"
2126 "void main\n"
2127 "(\n"
2128 "float4 gl_FrontColor : COLOR0,\n"
2129 "float2 TexCoord1 : TEXCOORD0,\n"
2130 "float2 TexCoord2 : TEXCOORD1,\n"
2131 "#ifdef USEDIFFUSE\n"
2132 "uniform sampler Texture_First : register(s0),\n"
2133 "#endif\n"
2134 "#ifdef USESPECULAR\n"
2135 "uniform sampler Texture_Second : register(s1),\n"
2136 "#endif\n"
2137 "out float4 gl_FragColor : COLOR\n"
2138 ")\n"
2139 "{\n"
2140 "#ifdef USEVIEWTINT\n"
2141 "       gl_FragColor = gl_FrontColor;\n"
2142 "#else\n"
2143 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2144 "#endif\n"
2145 "#ifdef USEDIFFUSE\n"
2146 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2147 "#endif\n"
2148 "\n"
2149 "#ifdef USESPECULAR\n"
2150 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2151 "# ifdef USECOLORMAPPING\n"
2152 "       gl_FragColor *= tex2;\n"
2153 "# endif\n"
2154 "# ifdef USEGLOW\n"
2155 "       gl_FragColor += tex2;\n"
2156 "# endif\n"
2157 "# ifdef USEVERTEXTEXTUREBLEND\n"
2158 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2159 "# endif\n"
2160 "#endif\n"
2161 "}\n"
2162 "#endif\n"
2163 "#else // !MODE_GENERIC\n"
2164 "\n"
2165 "\n"
2166 "\n"
2167 "\n"
2168 "#ifdef MODE_BLOOMBLUR\n"
2169 "#ifdef VERTEX_SHADER\n"
2170 "void main\n"
2171 "(\n"
2172 "float4 gl_Vertex : POSITION,\n"
2173 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2174 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2175 "out float4 gl_Position : POSITION,\n"
2176 "out float2 TexCoord : TEXCOORD0\n"
2177 ")\n"
2178 "{\n"
2179 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2180 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2181 "}\n"
2182 "#endif\n"
2183 "\n"
2184 "#ifdef FRAGMENT_SHADER\n"
2185 "\n"
2186 "void main\n"
2187 "(\n"
2188 "float2 TexCoord : TEXCOORD0,\n"
2189 "uniform sampler Texture_First : register(s0),\n"
2190 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2191 "out float4 gl_FragColor : COLOR\n"
2192 ")\n"
2193 "{\n"
2194 "       int i;\n"
2195 "       float2 tc = TexCoord;\n"
2196 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2197 "       tc += BloomBlur_Parameters.xy;\n"
2198 "       for (i = 1;i < SAMPLES;i++)\n"
2199 "       {\n"
2200 "               color += tex2D(Texture_First, tc).rgb;\n"
2201 "               tc += BloomBlur_Parameters.xy;\n"
2202 "       }\n"
2203 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2204 "}\n"
2205 "#endif\n"
2206 "#else // !MODE_BLOOMBLUR\n"
2207 "#ifdef MODE_REFRACTION\n"
2208 "#ifdef VERTEX_SHADER\n"
2209 "void main\n"
2210 "(\n"
2211 "float4 gl_Vertex : POSITION,\n"
2212 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2213 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2214 "uniform float4x4 TexMatrix : register(c0),\n"
2215 "uniform float3 EyePosition : register(c24),\n"
2216 "out float4 gl_Position : POSITION,\n"
2217 "out float2 TexCoord : TEXCOORD0,\n"
2218 "out float3 EyeVector : TEXCOORD1,\n"
2219 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2220 ")\n"
2221 "{\n"
2222 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2223 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2224 "       ModelViewProjectionPosition = gl_Position;\n"
2225 "}\n"
2226 "#endif\n"
2227 "\n"
2228 "#ifdef FRAGMENT_SHADER\n"
2229 "void main\n"
2230 "(\n"
2231 "float2 TexCoord : TEXCOORD0,\n"
2232 "float3 EyeVector : TEXCOORD1,\n"
2233 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2234 "uniform sampler Texture_Normal : register(s0),\n"
2235 "uniform sampler Texture_Refraction : register(s3),\n"
2236 "uniform sampler Texture_Reflection : register(s7),\n"
2237 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2238 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2239 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2240 "uniform float4 RefractColor : register(c29),\n"
2241 "out float4 gl_FragColor : COLOR\n"
2242 ")\n"
2243 "{\n"
2244 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2245 "       //float2 ScreenTexCoord = (ModelViewProjectionPosition.xy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2246 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2247 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2248 "       // FIXME temporary hack to detect the case that the reflection\n"
2249 "       // gets blackened at edges due to leaving the area that contains actual\n"
2250 "       // content.\n"
2251 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2252 "       // 'appening.\n"
2253 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2254 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2255 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2256 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2257 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2258 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2259 "}\n"
2260 "#endif\n"
2261 "#else // !MODE_REFRACTION\n"
2262 "\n"
2263 "\n"
2264 "\n"
2265 "\n"
2266 "#ifdef MODE_WATER\n"
2267 "#ifdef VERTEX_SHADER\n"
2268 "\n"
2269 "void main\n"
2270 "(\n"
2271 "float4 gl_Vertex : POSITION,\n"
2272 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2273 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2274 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2275 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2276 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2277 "uniform float4x4 TexMatrix : register(c0),\n"
2278 "uniform float3 EyePosition : register(c24),\n"
2279 "out float4 gl_Position : POSITION,\n"
2280 "out float2 TexCoord : TEXCOORD0,\n"
2281 "out float3 EyeVector : TEXCOORD1,\n"
2282 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2283 ")\n"
2284 "{\n"
2285 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2286 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2287 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2288 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2289 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2290 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2291 "       ModelViewProjectionPosition = gl_Position;\n"
2292 "}\n"
2293 "#endif\n"
2294 "\n"
2295 "#ifdef FRAGMENT_SHADER\n"
2296 "void main\n"
2297 "(\n"
2298 "float2 TexCoord : TEXCOORD0,\n"
2299 "float3 EyeVector : TEXCOORD1,\n"
2300 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2301 "uniform sampler Texture_Normal : register(s0),\n"
2302 "uniform sampler Texture_Refraction : register(s3),\n"
2303 "uniform sampler Texture_Reflection : register(s7),\n"
2304 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2305 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2306 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2307 "uniform float4 RefractColor : register(c29),\n"
2308 "uniform float4 ReflectColor : register(c26),\n"
2309 "uniform float ReflectFactor : register(c27),\n"
2310 "uniform float ReflectOffset : register(c28),\n"
2311 "out float4 gl_FragColor : COLOR\n"
2312 ")\n"
2313 "{\n"
2314 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2315 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2316 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2317 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2318 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2319 "       // FIXME temporary hack to detect the case that the reflection\n"
2320 "       // gets blackened at edges due to leaving the area that contains actual\n"
2321 "       // content.\n"
2322 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2323 "       // 'appening.\n"
2324 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2325 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2326 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2327 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2328 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2329 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2330 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2331 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2332 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2333 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2334 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2335 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2336 "}\n"
2337 "#endif\n"
2338 "#else // !MODE_WATER\n"
2339 "\n"
2340 "\n"
2341 "\n"
2342 "\n"
2343 "// TODO: get rid of tangentt (texcoord2) and use a crossproduct to regenerate it from tangents (texcoord1) and normal (texcoord3), this would require sending a 4 component texcoord1 with W as 1 or -1 according to which side the texcoord2 should be on\n"
2344 "\n"
2345 "// fragment shader specific:\n"
2346 "#ifdef FRAGMENT_SHADER\n"
2347 "\n"
2348 "#ifdef USEFOG\n"
2349 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2350 "{\n"
2351 "       float fogfrac;\n"
2352 "#ifdef USEFOGHEIGHTTEXTURE\n"
2353 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2354 "       fogfrac = fogheightpixel.a;\n"
2355 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2356 "#else\n"
2357 "# ifdef USEFOGOUTSIDE\n"
2358 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2359 "# else\n"
2360 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2361 "# endif\n"
2362 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2363 "#endif\n"
2364 "}\n"
2365 "#endif\n"
2366 "\n"
2367 "#ifdef USEOFFSETMAPPING\n"
2368 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2369 "{\n"
2370 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2371 "       // 14 sample relief mapping: linear search and then binary search\n"
2372 "       // this basically steps forward a small amount repeatedly until it finds\n"
2373 "       // itself inside solid, then jitters forward and back using decreasing\n"
2374 "       // amounts to find the impact\n"
2375 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2376 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2377 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2378 "       float3 RT = float3(TexCoord, 1);\n"
2379 "       OffsetVector *= 0.1;\n"
2380 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2381 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2382 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2383 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2384 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2385 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2386 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2387 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2388 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2389 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2390 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2391 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2392 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2393 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2394 "       return RT.xy;\n"
2395 "#else\n"
2396 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2397 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2398 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2399 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2400 "       OffsetVector *= 0.5;\n"
2401 "       TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2402 "       TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2403 "       return TexCoord;\n"
2404 "#endif\n"
2405 "}\n"
2406 "#endif // USEOFFSETMAPPING\n"
2407 "\n"
2408 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2409 "#if defined(USESHADOWMAP2D)\n"
2410 "# ifdef USESHADOWMAPORTHO\n"
2411 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2412 "# else\n"
2413 "#  ifdef USESHADOWMAPVSDCT\n"
2414 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2415 "{\n"
2416 "       float3 adir = abs(dir);\n"
2417 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2418 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2419 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2420 "}\n"
2421 "#  else\n"
2422 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2423 "{\n"
2424 "       float3 adir = abs(dir);\n"
2425 "       float ma = adir.z;\n"
2426 "       float4 proj = float4(dir, 2.5);\n"
2427 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2428 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2429 "#ifdef HLSL\n"
2430 "       return float3(proj.xy * ShadowMap_Parameters.x / ma + float2(0.5,0.5) + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, ma + 64 * ShadowMap_Parameters.w);\n"
2431 "#else\n"
2432 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2433 "       return float3(proj.xy * aparams.x + float2(proj.z < 0.0 ? 1.5 : 0.5, proj.w) * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2434 "#endif\n"
2435 "}\n"
2436 "#  endif\n"
2437 "# endif\n"
2438 "#endif // defined(USESHADOWMAP2D)\n"
2439 "\n"
2440 "# ifdef USESHADOWMAP2D\n"
2441 "#ifdef USESHADOWMAPVSDCT\n"
2442 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2443 "#else\n"
2444 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2445 "#endif\n"
2446 "{\n"
2447 "#ifdef USESHADOWMAPVSDCT\n"
2448 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2449 "#else\n"
2450 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2451 "#endif\n"
2452 "       float f;\n"
2453 "\n"
2454 "#  ifdef USESHADOWSAMPLER\n"
2455 "#    ifdef USESHADOWMAPPCF\n"
2456 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2457 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2458 "       f = dot(float4(0.25,0.25,0.25,0.25), float4(texval(-0.4, 1.0), texval(-1.0, -0.4), texval(0.4, -1.0), texval(1.0, 0.4)));\n"
2459 "#    else\n"
2460 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2461 "#    endif\n"
2462 "#  else\n"
2463 "#    ifdef USESHADOWMAPPCF\n"
2464 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2465 "#      ifdef GL_ARB_texture_gather\n"
2466 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2467 "#      else\n"
2468 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2469 "#      endif\n"
2470 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2471 "#      if USESHADOWMAPPCF > 1\n"
2472 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2473 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2474 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2475 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2476 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2477 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2478 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2479 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2480 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2481 "       float4 locols = float4(group1.ab, group3.ab);\n"
2482 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2483 "       locols.yz += group2.ab;\n"
2484 "       hicols.yz += group8.rg;\n"
2485 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2486 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2487 "                               lerp(locols, hicols, offset.y);\n"
2488 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2489 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2490 "       f = dot(cols, float4(1.0/25.0));\n"
2491 "#      else\n"
2492 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2493 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2494 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2495 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2496 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2497 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2498 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2499 "#      endif\n"
2500 "#     else\n"
2501 "#      ifdef GL_EXT_gpu_shader4\n"
2502 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2503 "#      else\n"
2504 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2505 "#      endif\n"
2506 "#      if USESHADOWMAPPCF > 1\n"
2507 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2508 "       center *= ShadowMap_TextureScale;\n"
2509 "       float4 row1 = step(shadowmaptc.z, float4(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0), texval( 2.0, -1.0)));\n"
2510 "       float4 row2 = step(shadowmaptc.z, float4(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0), texval( 2.0,  0.0)));\n"
2511 "       float4 row3 = step(shadowmaptc.z, float4(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0), texval( 2.0,  1.0)));\n"
2512 "       float4 row4 = step(shadowmaptc.z, float4(texval(-1.0,  2.0), texval( 0.0,  2.0), texval( 1.0,  2.0), texval( 2.0,  2.0)));\n"
2513 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2514 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2515 "#      else\n"
2516 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2517 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2518 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2519 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2520 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2521 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2522 "#      endif\n"
2523 "#     endif\n"
2524 "#    else\n"
2525 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2526 "#    endif\n"
2527 "#  endif\n"
2528 "#  ifdef USESHADOWMAPORTHO\n"
2529 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2530 "#  else\n"
2531 "       return f;\n"
2532 "#  endif\n"
2533 "}\n"
2534 "# endif\n"
2535 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2536 "#endif // FRAGMENT_SHADER\n"
2537 "\n"
2538 "\n"
2539 "\n"
2540 "\n"
2541 "#ifdef MODE_DEFERREDGEOMETRY\n"
2542 "#ifdef VERTEX_SHADER\n"
2543 "void main\n"
2544 "(\n"
2545 "float4 gl_Vertex : POSITION,\n"
2546 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2547 "#ifdef USEVERTEXTEXTUREBLEND\n"
2548 "float4 gl_Color : COLOR0,\n"
2549 "#endif\n"
2550 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2551 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2552 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2553 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2554 "uniform float4x4 TexMatrix : register(c0),\n"
2555 "#ifdef USEVERTEXTEXTUREBLEND\n"
2556 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2557 "#endif\n"
2558 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2559 "#ifdef USEOFFSETMAPPING\n"
2560 "uniform float3 EyePosition : register(c24),\n"
2561 "#endif\n"
2562 "out float4 gl_Position : POSITION,\n"
2563 "#ifdef USEVERTEXTEXTUREBLEND\n"
2564 "out float4 gl_FrontColor : COLOR,\n"
2565 "#endif\n"
2566 "out float4 TexCoordBoth : TEXCOORD0,\n"
2567 "#ifdef USEOFFSETMAPPING\n"
2568 "out float3 EyeVector : TEXCOORD2,\n"
2569 "#endif\n"
2570 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2571 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2572 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2573 ")\n"
2574 "{\n"
2575 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2576 "#ifdef USEVERTEXTEXTUREBLEND\n"
2577 "#ifdef HLSL\n"
2578 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2579 "#else\n"
2580 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2581 "#endif\n"
2582 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2583 "#endif\n"
2584 "\n"
2585 "       // transform unnormalized eye direction into tangent space\n"
2586 "#ifdef USEOFFSETMAPPING\n"
2587 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2588 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2589 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2590 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2591 "#endif\n"
2592 "\n"
2593 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2594 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2595 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2596 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2597 "       VectorR.w = gl_Position.z;\n"
2598 "}\n"
2599 "#endif // VERTEX_SHADER\n"
2600 "\n"
2601 "#ifdef FRAGMENT_SHADER\n"
2602 "void main\n"
2603 "(\n"
2604 "float4 TexCoordBoth : TEXCOORD0,\n"
2605 "float3 EyeVector : TEXCOORD2,\n"
2606 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2607 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2608 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2609 "uniform sampler Texture_Normal : register(s0),\n"
2610 "#ifdef USEALPHAKILL\n"
2611 "uniform sampler Texture_Color : register(s1),\n"
2612 "#endif\n"
2613 "uniform sampler Texture_Gloss : register(s2),\n"
2614 "#ifdef USEVERTEXTEXTUREBLEND\n"
2615 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2616 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2617 "#endif\n"
2618 "#ifdef USEOFFSETMAPPING\n"
2619 "uniform float OffsetMapping_Scale : register(c24),\n"
2620 "#endif\n"
2621 "uniform half SpecularPower : register(c36),\n"
2622 "#ifdef HLSL\n"
2623 "out float4 gl_FragData0 : COLOR0,\n"
2624 "out float4 gl_FragData1 : COLOR1\n"
2625 "#else\n"
2626 "out float4 gl_FragColor : COLOR\n"
2627 "#endif\n"
2628 ")\n"
2629 "{\n"
2630 "       float2 TexCoord = TexCoordBoth.xy;\n"
2631 "#ifdef USEOFFSETMAPPING\n"
2632 "       // apply offsetmapping\n"
2633 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2634 "#define TexCoord TexCoordOffset\n"
2635 "#endif\n"
2636 "\n"
2637 "#ifdef USEALPHAKILL\n"
2638 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2639 "               discard;\n"
2640 "#endif\n"
2641 "\n"
2642 "#ifdef USEVERTEXTEXTUREBLEND\n"
2643 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2644 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2645 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2646 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2647 "#endif\n"
2648 "\n"
2649 "#ifdef USEVERTEXTEXTUREBLEND\n"
2650 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2651 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2652 "#else\n"
2653 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2654 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2655 "#endif\n"
2656 "\n"
2657 "#ifdef HLSL\n"
2658 "       gl_FragData0 = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR.xyz) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2659 "       float Depth = VectorR.w / 256.0;\n"
2660 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2661 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2662 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2663 "       gl_FragData1 = depthcolor;\n"
2664 "#else\n"
2665 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2666 "#endif\n"
2667 "}\n"
2668 "#endif // FRAGMENT_SHADER\n"
2669 "#else // !MODE_DEFERREDGEOMETRY\n"
2670 "\n"
2671 "\n"
2672 "\n"
2673 "\n"
2674 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2675 "#ifdef VERTEX_SHADER\n"
2676 "void main\n"
2677 "(\n"
2678 "float4 gl_Vertex : POSITION,\n"
2679 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2680 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2681 "out float4 gl_Position : POSITION,\n"
2682 "out float4 ModelViewPosition : TEXCOORD0\n"
2683 ")\n"
2684 "{\n"
2685 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2686 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2687 "}\n"
2688 "#endif // VERTEX_SHADER\n"
2689 "\n"
2690 "#ifdef FRAGMENT_SHADER\n"
2691 "void main\n"
2692 "(\n"
2693 "#ifdef HLSL\n"
2694 "float2 Pixel : VPOS,\n"
2695 "#else\n"
2696 "float2 Pixel : WPOS,\n"
2697 "#endif\n"
2698 "float4 ModelViewPosition : TEXCOORD0,\n"
2699 "uniform float4x4 ViewToLight : register(c44),\n"
2700 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2701 "uniform float3 LightPosition : register(c23),\n"
2702 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2703 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2704 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2705 "#ifdef USESPECULAR\n"
2706 "uniform half3 DeferredColor_Specular : register(c11),\n"
2707 "uniform half SpecularPower : register(c36),\n"
2708 "#endif\n"
2709 "uniform sampler Texture_Attenuation : register(s9),\n"
2710 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2711 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2712 "\n"
2713 "#ifdef USECUBEFILTER\n"
2714 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2715 "#endif\n"
2716 "\n"
2717 "#ifdef USESHADOWMAP2D\n"
2718 "# ifdef USESHADOWSAMPLER\n"
2719 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2720 "# else\n"
2721 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2722 "# endif\n"
2723 "#endif\n"
2724 "\n"
2725 "#ifdef USESHADOWMAPVSDCT\n"
2726 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2727 "#endif\n"
2728 "\n"
2729 "#if defined(USESHADOWMAP2D)\n"
2730 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2731 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2732 "#endif\n"
2733 "\n"
2734 "out float4 gl_FragData0 : COLOR0,\n"
2735 "out float4 gl_FragData1 : COLOR1\n"
2736 ")\n"
2737 "{\n"
2738 "       // calculate viewspace pixel position\n"
2739 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2740 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2741 "       float3 position;\n"
2742 "#ifdef HLSL\n"
2743 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2744 "#else\n"
2745 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2746 "#endif\n"
2747 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2748 "       // decode viewspace pixel normal\n"
2749 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2750 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2751 "       // surfacenormal = pixel normal in viewspace\n"
2752 "       // LightVector = pixel to light in viewspace\n"
2753 "       // CubeVector = position in lightspace\n"
2754 "       // eyevector = pixel to view in viewspace\n"
2755 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2756 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2757 "#ifdef USEDIFFUSE\n"
2758 "       // calculate diffuse shading\n"
2759 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2760 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2761 "#endif\n"
2762 "#ifdef USESPECULAR\n"
2763 "       // calculate directional shading\n"
2764 "       float3 eyevector = position * -1.0;\n"
2765 "#  ifdef USEEXACTSPECULARMATH\n"
2766 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2767 "#  else\n"
2768 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2769 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2770 "#  endif\n"
2771 "#endif\n"
2772 "\n"
2773 "#if defined(USESHADOWMAP2D)\n"
2774 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2775 "#ifdef USESHADOWMAPVSDCT\n"
2776 ", Texture_CubeProjection\n"
2777 "#endif\n"
2778 "       ));\n"
2779 "#endif\n"
2780 "\n"
2781 "#ifdef USEDIFFUSE\n"
2782 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2783 "#else\n"
2784 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2785 "#endif\n"
2786 "#ifdef USESPECULAR\n"
2787 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2788 "#else\n"
2789 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2790 "#endif\n"
2791 "\n"
2792 "# ifdef USECUBEFILTER\n"
2793 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2794 "       gl_FragData0.rgb *= cubecolor;\n"
2795 "       gl_FragData1.rgb *= cubecolor;\n"
2796 "# endif\n"
2797 "}\n"
2798 "#endif // FRAGMENT_SHADER\n"
2799 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2800 "\n"
2801 "\n"
2802 "\n"
2803 "\n"
2804 "#ifdef VERTEX_SHADER\n"
2805 "void main\n"
2806 "(\n"
2807 "float4 gl_Vertex : POSITION,\n"
2808 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2809 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2810 "float4 gl_Color : COLOR0,\n"
2811 "#endif\n"
2812 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2813 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2814 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2815 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2816 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2817 "\n"
2818 "uniform float3 EyePosition : register(c24),\n"
2819 "uniform float4x4 TexMatrix : register(c0),\n"
2820 "#ifdef USEVERTEXTEXTUREBLEND\n"
2821 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2822 "#endif\n"
2823 "#ifdef MODE_LIGHTSOURCE\n"
2824 "uniform float4x4 ModelToLight : register(c20),\n"
2825 "#endif\n"
2826 "#ifdef MODE_LIGHTSOURCE\n"
2827 "uniform float3 LightPosition : register(c27),\n"
2828 "#endif\n"
2829 "#ifdef MODE_LIGHTDIRECTION\n"
2830 "uniform float3 LightDir : register(c26),\n"
2831 "#endif\n"
2832 "uniform float4 FogPlane : register(c25),\n"
2833 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2834 "uniform float3 LightPosition : register(c27),\n"
2835 "#endif\n"
2836 "#ifdef USESHADOWMAPORTHO\n"
2837 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2838 "#endif\n"
2839 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2840 "out float4 gl_FrontColor : COLOR,\n"
2841 "#endif\n"
2842 "out float4 TexCoordBoth : TEXCOORD0,\n"
2843 "#ifdef USELIGHTMAP\n"
2844 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2845 "#endif\n"
2846 "#ifdef USEEYEVECTOR\n"
2847 "out float3 EyeVector : TEXCOORD2,\n"
2848 "#endif\n"
2849 "#ifdef USEREFLECTION\n"
2850 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2851 "#endif\n"
2852 "#ifdef USEFOG\n"
2853 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2854 "#endif\n"
2855 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2856 "out float3 LightVector : TEXCOORD1,\n"
2857 "#endif\n"
2858 "#ifdef MODE_LIGHTSOURCE\n"
2859 "out float3 CubeVector : TEXCOORD3,\n"
2860 "#endif\n"
2861 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2862 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2863 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2864 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2865 "#endif\n"
2866 "#ifdef USESHADOWMAPORTHO\n"
2867 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2868 "#endif\n"
2869 "out float4 gl_Position : POSITION\n"
2870 ")\n"
2871 "{\n"
2872 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2873 "#ifdef HLSL\n"
2874 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2875 "#else\n"
2876 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2877 "#endif\n"
2878 "#endif\n"
2879 "       // copy the surface texcoord\n"
2880 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2881 "#ifdef USEVERTEXTEXTUREBLEND\n"
2882 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2883 "#endif\n"
2884 "#ifdef USELIGHTMAP\n"
2885 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2886 "#endif\n"
2887 "\n"
2888 "#ifdef MODE_LIGHTSOURCE\n"
2889 "       // transform vertex position into light attenuation/cubemap space\n"
2890 "       // (-1 to +1 across the light box)\n"
2891 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2892 "\n"
2893 "# ifdef USEDIFFUSE\n"
2894 "       // transform unnormalized light direction into tangent space\n"
2895 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2896 "       //  normalize it per pixel)\n"
2897 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2898 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2899 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2900 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2901 "# endif\n"
2902 "#endif\n"
2903 "\n"
2904 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2905 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2906 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2907 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2908 "#endif\n"
2909 "\n"
2910 "       // transform unnormalized eye direction into tangent space\n"
2911 "#ifdef USEEYEVECTOR\n"
2912 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2913 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2914 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2915 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2916 "#endif\n"
2917 "\n"
2918 "#ifdef USEFOG\n"
2919 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2920 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2921 "#endif\n"
2922 "\n"
2923 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2924 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2925 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2926 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2927 "#endif\n"
2928 "\n"
2929 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2930 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2931 "\n"
2932 "#ifdef USESHADOWMAPORTHO\n"
2933 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2934 "#endif\n"
2935 "\n"
2936 "#ifdef USEREFLECTION\n"
2937 "       ModelViewProjectionPosition = gl_Position;\n"
2938 "#endif\n"
2939 "}\n"
2940 "#endif // VERTEX_SHADER\n"
2941 "\n"
2942 "\n"
2943 "\n"
2944 "\n"
2945 "#ifdef FRAGMENT_SHADER\n"
2946 "void main\n"
2947 "(\n"
2948 "#ifdef USEDEFERREDLIGHTMAP\n"
2949 "#ifdef HLSL\n"
2950 "float2 Pixel : VPOS,\n"
2951 "#else\n"
2952 "float2 Pixel : WPOS,\n"
2953 "#endif\n"
2954 "#endif\n"
2955 "float4 gl_FrontColor : COLOR,\n"
2956 "float4 TexCoordBoth : TEXCOORD0,\n"
2957 "#ifdef USELIGHTMAP\n"
2958 "float2 TexCoordLightmap : TEXCOORD1,\n"
2959 "#endif\n"
2960 "#ifdef USEEYEVECTOR\n"
2961 "float3 EyeVector : TEXCOORD2,\n"
2962 "#endif\n"
2963 "#ifdef USEREFLECTION\n"
2964 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2965 "#endif\n"
2966 "#ifdef USEFOG\n"
2967 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2968 "#endif\n"
2969 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
2970 "float3 LightVector : TEXCOORD1,\n"
2971 "#endif\n"
2972 "#ifdef MODE_LIGHTSOURCE\n"
2973 "float3 CubeVector : TEXCOORD3,\n"
2974 "#endif\n"
2975 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2976 "float4 ModelViewPosition : TEXCOORD0,\n"
2977 "#endif\n"
2978 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2979 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2980 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2981 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2982 "#endif\n"
2983 "#ifdef USESHADOWMAPORTHO\n"
2984 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2985 "#endif\n"
2986 "\n"
2987 "uniform sampler Texture_Normal : register(s0),\n"
2988 "uniform sampler Texture_Color : register(s1),\n"
2989 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2990 "uniform sampler Texture_Gloss : register(s2),\n"
2991 "#endif\n"
2992 "#ifdef USEGLOW\n"
2993 "uniform sampler Texture_Glow : register(s3),\n"
2994 "#endif\n"
2995 "#ifdef USEVERTEXTEXTUREBLEND\n"
2996 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2997 "uniform sampler Texture_SecondaryColor : register(s5),\n"
2998 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
2999 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3000 "#endif\n"
3001 "#ifdef USEGLOW\n"
3002 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3003 "#endif\n"
3004 "#endif\n"
3005 "#ifdef USECOLORMAPPING\n"
3006 "uniform sampler Texture_Pants : register(s4),\n"
3007 "uniform sampler Texture_Shirt : register(s7),\n"
3008 "#endif\n"
3009 "#ifdef USEFOG\n"
3010 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3011 "uniform sampler Texture_FogMask : register(s8),\n"
3012 "#endif\n"
3013 "#ifdef USELIGHTMAP\n"
3014 "uniform sampler Texture_Lightmap : register(s9),\n"
3015 "#endif\n"
3016 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3017 "uniform sampler Texture_Deluxemap : register(s10),\n"
3018 "#endif\n"
3019 "#ifdef USEREFLECTION\n"
3020 "uniform sampler Texture_Reflection : register(s7),\n"
3021 "#endif\n"
3022 "\n"
3023 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3024 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3025 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3026 "#endif\n"
3027 "#ifdef USEDEFERREDLIGHTMAP\n"
3028 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3029 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3030 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3031 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3032 "#endif\n"
3033 "\n"
3034 "#ifdef USECOLORMAPPING\n"
3035 "uniform half3 Color_Pants : register(c7),\n"
3036 "uniform half3 Color_Shirt : register(c8),\n"
3037 "#endif\n"
3038 "#ifdef USEFOG\n"
3039 "uniform float3 FogColor : register(c16),\n"
3040 "uniform float FogRangeRecip : register(c20),\n"
3041 "uniform float FogPlaneViewDist : register(c19),\n"
3042 "uniform float FogHeightFade : register(c17),\n"
3043 "#endif\n"
3044 "\n"
3045 "#ifdef USEOFFSETMAPPING\n"
3046 "uniform float OffsetMapping_Scale : register(c24),\n"
3047 "#endif\n"
3048 "\n"
3049 "#ifdef USEDEFERREDLIGHTMAP\n"
3050 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3051 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3052 "uniform half3 DeferredMod_Specular : register(c13),\n"
3053 "#endif\n"
3054 "uniform half3 Color_Ambient : register(c3),\n"
3055 "uniform half3 Color_Diffuse : register(c4),\n"
3056 "uniform half3 Color_Specular : register(c5),\n"
3057 "uniform half SpecularPower : register(c36),\n"
3058 "#ifdef USEGLOW\n"
3059 "uniform half3 Color_Glow : register(c6),\n"
3060 "#endif\n"
3061 "uniform half Alpha : register(c0),\n"
3062 "#ifdef USEREFLECTION\n"
3063 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3064 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3065 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3066 "uniform half4 ReflectColor : register(c26),\n"
3067 "#endif\n"
3068 "#ifdef USEREFLECTCUBE\n"
3069 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3070 "uniform sampler Texture_ReflectMask : register(s5),\n"
3071 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3072 "#endif\n"
3073 "#ifdef MODE_LIGHTDIRECTION\n"
3074 "uniform half3 LightColor : register(c21),\n"
3075 "#endif\n"
3076 "#ifdef MODE_LIGHTSOURCE\n"
3077 "uniform half3 LightColor : register(c21),\n"
3078 "#endif\n"
3079 "\n"
3080 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3081 "uniform sampler Texture_Attenuation : register(s9),\n"
3082 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3083 "#endif\n"
3084 "\n"
3085 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3086 "\n"
3087 "#ifdef USESHADOWMAP2D\n"
3088 "# ifdef USESHADOWSAMPLER\n"
3089 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3090 "# else\n"
3091 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3092 "# endif\n"
3093 "#endif\n"
3094 "\n"
3095 "#ifdef USESHADOWMAPVSDCT\n"
3096 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3097 "#endif\n"
3098 "\n"
3099 "#if defined(USESHADOWMAP2D)\n"
3100 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3101 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3102 "#endif\n"
3103 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3104 "\n"
3105 "out float4 gl_FragColor : COLOR\n"
3106 ")\n"
3107 "{\n"
3108 "       float2 TexCoord = TexCoordBoth.xy;\n"
3109 "#ifdef USEVERTEXTEXTUREBLEND\n"
3110 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3111 "#endif\n"
3112 "#ifdef USEOFFSETMAPPING\n"
3113 "       // apply offsetmapping\n"
3114 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3115 "#define TexCoord TexCoordOffset\n"
3116 "#endif\n"
3117 "\n"
3118 "       // combine the diffuse textures (base, pants, shirt)\n"
3119 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3120 "#ifdef USEALPHAKILL\n"
3121 "       if (color.a < 0.5)\n"
3122 "               discard;\n"
3123 "#endif\n"
3124 "       color.a *= Alpha;\n"
3125 "#ifdef USECOLORMAPPING\n"
3126 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3127 "#endif\n"
3128 "#ifdef USEVERTEXTEXTUREBLEND\n"
3129 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3130 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3131 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3132 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3133 "       color.a = 1.0;\n"
3134 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3135 "#endif\n"
3136 "\n"
3137 "       // get the surface normal\n"
3138 "#ifdef USEVERTEXTEXTUREBLEND\n"
3139 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3140 "#else\n"
3141 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3142 "#endif\n"
3143 "\n"
3144 "       // get the material colors\n"
3145 "       half3 diffusetex = color.rgb;\n"
3146 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3147 "# ifdef USEVERTEXTEXTUREBLEND\n"
3148 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3149 "# else\n"
3150 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3151 "# endif\n"
3152 "#endif\n"
3153 "\n"
3154 "#ifdef USEREFLECTCUBE\n"
3155 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3156 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3157 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3158 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3159 "#endif\n"
3160 "\n"
3161 "\n"
3162 "\n"
3163 "\n"
3164 "#ifdef MODE_LIGHTSOURCE\n"
3165 "       // light source\n"
3166 "#ifdef USEDIFFUSE\n"
3167 "       half3 lightnormal = half3(normalize(LightVector));\n"
3168 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3169 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3170 "#ifdef USESPECULAR\n"
3171 "#ifdef USEEXACTSPECULARMATH\n"
3172 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3173 "#else\n"
3174 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3175 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3176 "#endif\n"
3177 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3178 "#endif\n"
3179 "#else\n"
3180 "       color.rgb = diffusetex * Color_Ambient;\n"
3181 "#endif\n"
3182 "       color.rgb *= LightColor;\n"
3183 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3184 "#if defined(USESHADOWMAP2D)\n"
3185 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3186 "#ifdef USESHADOWMAPVSDCT\n"
3187 ", Texture_CubeProjection\n"
3188 "#endif\n"
3189 "       ));\n"
3190 "\n"
3191 "#endif\n"
3192 "# ifdef USECUBEFILTER\n"
3193 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3194 "# endif\n"
3195 "\n"
3196 "#ifdef USESHADOWMAP2D\n"
3197 "#ifdef USESHADOWMAPVSDCT\n"
3198 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3199 "#else\n"
3200 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3201 "#endif\n"
3202 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3203 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3204 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3205 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3206 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3207 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3208 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3209 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3210 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3211 "//     color.r = half(shadowmaptc.z);\n"
3212 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3213 "//     color.r = half(shadowmaptc.z);\n"
3214 "//     color.r = 1;\n"
3215 "//     color.rgb = abs(CubeVector);\n"
3216 "#endif\n"
3217 "//     color.rgb = half3(1,1,1);\n"
3218 "#endif // MODE_LIGHTSOURCE\n"
3219 "\n"
3220 "\n"
3221 "\n"
3222 "\n"
3223 "#ifdef MODE_LIGHTDIRECTION\n"
3224 "#define SHADING\n"
3225 "#ifdef USEDIFFUSE\n"
3226 "       half3 lightnormal = half3(normalize(LightVector));\n"
3227 "#endif\n"
3228 "#define lightcolor LightColor\n"
3229 "#endif // MODE_LIGHTDIRECTION\n"
3230 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3231 "#define SHADING\n"
3232 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3233 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3234 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3235 "       // convert modelspace light vector to tangentspace\n"
3236 "       half3 lightnormal;\n"
3237 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3238 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3239 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3240 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3241 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3242 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3243 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3244 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3245 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3246 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3247 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3248 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3249 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3250 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3251 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3252 "#define SHADING\n"
3253 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3254 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3255 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3256 "#endif\n"
3257 "\n"
3258 "\n"
3259 "\n"
3260 "\n"
3261 "#ifdef MODE_FAKELIGHT\n"
3262 "#define SHADING\n"
3263 "half3 lightnormal = half3(normalize(EyeVector));\n"
3264 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3265 "#endif // MODE_FAKELIGHT\n"
3266 "\n"
3267 "\n"
3268 "\n"
3269 "\n"
3270 "#ifdef MODE_LIGHTMAP\n"
3271 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3272 "#endif // MODE_LIGHTMAP\n"
3273 "#ifdef MODE_VERTEXCOLOR\n"
3274 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3275 "#endif // MODE_VERTEXCOLOR\n"
3276 "#ifdef MODE_FLATCOLOR\n"
3277 "       color.rgb = diffusetex * Color_Ambient;\n"
3278 "#endif // MODE_FLATCOLOR\n"
3279 "\n"
3280 "\n"
3281 "\n"
3282 "\n"
3283 "#ifdef SHADING\n"
3284 "# ifdef USEDIFFUSE\n"
3285 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3286 "#  ifdef USESPECULAR\n"
3287 "#   ifdef USEEXACTSPECULARMATH\n"
3288 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3289 "#   else\n"
3290 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3291 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3292 "#   endif\n"
3293 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3294 "#  else\n"
3295 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3296 "#  endif\n"
3297 "# else\n"
3298 "       color.rgb = diffusetex * Color_Ambient;\n"
3299 "# endif\n"
3300 "#endif\n"
3301 "\n"
3302 "#ifdef USESHADOWMAPORTHO\n"
3303 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3304 "#endif\n"
3305 "\n"
3306 "#ifdef USEDEFERREDLIGHTMAP\n"
3307 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3308 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3309 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3310 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3311 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3312 "#endif\n"
3313 "\n"
3314 "#ifdef USEGLOW\n"
3315 "#ifdef USEVERTEXTEXTUREBLEND\n"
3316 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3317 "#else\n"
3318 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3319 "#endif\n"
3320 "#endif\n"
3321 "\n"
3322 "#ifdef USEFOG\n"
3323 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3324 "#endif\n"
3325 "\n"
3326 "       // reflection must come last because it already contains exactly the correct fog (the reflection render preserves camera distance from the plane, it only flips the side) and ContrastBoost/SceneBrightness\n"
3327 "#ifdef USEREFLECTION\n"
3328 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3329 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3330 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3331 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3332 "       // FIXME temporary hack to detect the case that the reflection\n"
3333 "       // gets blackened at edges due to leaving the area that contains actual\n"
3334 "       // content.\n"
3335 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3336 "       // 'appening.\n"
3337 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3338 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3339 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3340 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3341 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3342 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3343 "#endif\n"
3344 "\n"
3345 "       gl_FragColor = float4(color);\n"
3346 "}\n"
3347 "#endif // FRAGMENT_SHADER\n"
3348 "\n"
3349 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3350 "#endif // !MODE_DEFERREDGEOMETRY\n"
3351 "#endif // !MODE_WATER\n"
3352 "#endif // !MODE_REFRACTION\n"
3353 "#endif // !MODE_BLOOMBLUR\n"
3354 "#endif // !MODE_GENERIC\n"
3355 "#endif // !MODE_POSTPROCESS\n"
3356 "#endif // !MODE_SHOWDEPTH\n"
3357 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3358 ;
3359
3360 char *glslshaderstring = NULL;
3361 char *hlslshaderstring = NULL;
3362
3363 //=======================================================================================================================================================
3364
3365 typedef struct shaderpermutationinfo_s
3366 {
3367         const char *pretext;
3368         const char *name;
3369 }
3370 shaderpermutationinfo_t;
3371
3372 typedef struct shadermodeinfo_s
3373 {
3374         const char *vertexfilename;
3375         const char *geometryfilename;
3376         const char *fragmentfilename;
3377         const char *pretext;
3378         const char *name;
3379 }
3380 shadermodeinfo_t;
3381
3382 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3383 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3384 {
3385         {"#define USEDIFFUSE\n", " diffuse"},
3386         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3387         {"#define USEVIEWTINT\n", " viewtint"},
3388         {"#define USECOLORMAPPING\n", " colormapping"},
3389         {"#define USESATURATION\n", " saturation"},
3390         {"#define USEFOGINSIDE\n", " foginside"},
3391         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3392         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3393         {"#define USEGAMMARAMPS\n", " gammaramps"},
3394         {"#define USECUBEFILTER\n", " cubefilter"},
3395         {"#define USEGLOW\n", " glow"},
3396         {"#define USEBLOOM\n", " bloom"},
3397         {"#define USESPECULAR\n", " specular"},
3398         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3399         {"#define USEREFLECTION\n", " reflection"},
3400         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3401         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3402         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3403         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3404         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3405         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3406         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3407         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3408         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3409         {"#define USEALPHAKILL\n", " alphakill"},
3410         {"#define USEREFLECTCUBE\n", " reflectcube"},
3411         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3412         {"#define USEBOUNCEGRID\n", " bouncegrid"},
3413 };
3414
3415 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3416 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3417 {
3418         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3419         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3420         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3421         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3422         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3423         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3424         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3425         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3426         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3427         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3428         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3429         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3430         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3431         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3432         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3433         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3434 };
3435
3436 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3437 {
3438         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3439         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3440         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3441         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3442         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3443         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3444         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3445         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3446         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3447         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3448         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3449         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3450         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3451         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3452         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3453         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3454 };
3455
3456 struct r_glsl_permutation_s;
3457 typedef struct r_glsl_permutation_s
3458 {
3459         /// hash lookup data
3460         struct r_glsl_permutation_s *hashnext;
3461         unsigned int mode;
3462         unsigned int permutation;
3463
3464         /// indicates if we have tried compiling this permutation already
3465         qboolean compiled;
3466         /// 0 if compilation failed
3467         int program;
3468         // texture units assigned to each detected uniform
3469         int tex_Texture_First;
3470         int tex_Texture_Second;
3471         int tex_Texture_GammaRamps;
3472         int tex_Texture_Normal;
3473         int tex_Texture_Color;
3474         int tex_Texture_Gloss;
3475         int tex_Texture_Glow;
3476         int tex_Texture_SecondaryNormal;
3477         int tex_Texture_SecondaryColor;
3478         int tex_Texture_SecondaryGloss;
3479         int tex_Texture_SecondaryGlow;
3480         int tex_Texture_Pants;
3481         int tex_Texture_Shirt;
3482         int tex_Texture_FogHeightTexture;
3483         int tex_Texture_FogMask;
3484         int tex_Texture_Lightmap;
3485         int tex_Texture_Deluxemap;
3486         int tex_Texture_Attenuation;
3487         int tex_Texture_Cube;
3488         int tex_Texture_Refraction;
3489         int tex_Texture_Reflection;
3490         int tex_Texture_ShadowMap2D;
3491         int tex_Texture_CubeProjection;
3492         int tex_Texture_ScreenDepth;
3493         int tex_Texture_ScreenNormalMap;
3494         int tex_Texture_ScreenDiffuse;
3495         int tex_Texture_ScreenSpecular;
3496         int tex_Texture_ReflectMask;
3497         int tex_Texture_ReflectCube;
3498         int tex_Texture_BounceGrid;
3499         /// locations of detected uniforms in program object, or -1 if not found
3500         int loc_Texture_First;
3501         int loc_Texture_Second;
3502         int loc_Texture_GammaRamps;
3503         int loc_Texture_Normal;
3504         int loc_Texture_Color;
3505         int loc_Texture_Gloss;
3506         int loc_Texture_Glow;
3507         int loc_Texture_SecondaryNormal;
3508         int loc_Texture_SecondaryColor;
3509         int loc_Texture_SecondaryGloss;
3510         int loc_Texture_SecondaryGlow;
3511         int loc_Texture_Pants;
3512         int loc_Texture_Shirt;
3513         int loc_Texture_FogHeightTexture;
3514         int loc_Texture_FogMask;
3515         int loc_Texture_Lightmap;
3516         int loc_Texture_Deluxemap;
3517         int loc_Texture_Attenuation;
3518         int loc_Texture_Cube;
3519         int loc_Texture_Refraction;
3520         int loc_Texture_Reflection;
3521         int loc_Texture_ShadowMap2D;
3522         int loc_Texture_CubeProjection;
3523         int loc_Texture_ScreenDepth;
3524         int loc_Texture_ScreenNormalMap;
3525         int loc_Texture_ScreenDiffuse;
3526         int loc_Texture_ScreenSpecular;
3527         int loc_Texture_ReflectMask;
3528         int loc_Texture_ReflectCube;
3529         int loc_Texture_BounceGrid;
3530         int loc_Alpha;
3531         int loc_BloomBlur_Parameters;
3532         int loc_ClientTime;
3533         int loc_Color_Ambient;
3534         int loc_Color_Diffuse;
3535         int loc_Color_Specular;
3536         int loc_Color_Glow;
3537         int loc_Color_Pants;
3538         int loc_Color_Shirt;
3539         int loc_DeferredColor_Ambient;
3540         int loc_DeferredColor_Diffuse;
3541         int loc_DeferredColor_Specular;
3542         int loc_DeferredMod_Diffuse;
3543         int loc_DeferredMod_Specular;
3544         int loc_DistortScaleRefractReflect;
3545         int loc_EyePosition;
3546         int loc_FogColor;
3547         int loc_FogHeightFade;
3548         int loc_FogPlane;
3549         int loc_FogPlaneViewDist;
3550         int loc_FogRangeRecip;
3551         int loc_LightColor;
3552         int loc_LightDir;
3553         int loc_LightPosition;
3554         int loc_OffsetMapping_Scale;
3555         int loc_PixelSize;
3556         int loc_ReflectColor;
3557         int loc_ReflectFactor;
3558         int loc_ReflectOffset;
3559         int loc_RefractColor;
3560         int loc_Saturation;
3561         int loc_ScreenCenterRefractReflect;
3562         int loc_ScreenScaleRefractReflect;
3563         int loc_ScreenToDepth;
3564         int loc_ShadowMap_Parameters;
3565         int loc_ShadowMap_TextureScale;
3566         int loc_SpecularPower;
3567         int loc_UserVec1;
3568         int loc_UserVec2;
3569         int loc_UserVec3;
3570         int loc_UserVec4;
3571         int loc_ViewTintColor;
3572         int loc_ViewToLight;
3573         int loc_ModelToLight;
3574         int loc_TexMatrix;
3575         int loc_BackgroundTexMatrix;
3576         int loc_ModelViewProjectionMatrix;
3577         int loc_ModelViewMatrix;
3578         int loc_PixelToScreenTexCoord;
3579         int loc_ModelToReflectCube;
3580         int loc_ShadowMapMatrix;
3581         int loc_BloomColorSubtract;
3582         int loc_NormalmapScrollBlend;
3583         int loc_BounceGridMatrix;
3584         int loc_BounceGridIntensity;
3585 }
3586 r_glsl_permutation_t;
3587
3588 #define SHADERPERMUTATION_HASHSIZE 256
3589
3590
3591 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3592 // these can NOT degrade! only use for simple stuff
3593 enum
3594 {
3595         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3596         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3597         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3598         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3599         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3600         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3601 };
3602 #define SHADERSTATICPARMS_COUNT 6
3603
3604 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3605 static int shaderstaticparms_count = 0;
3606
3607 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3608 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3609 qboolean R_CompileShader_CheckStaticParms(void)
3610 {
3611         static int r_compileshader_staticparms_save[1];
3612         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3613         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3614
3615         // detect all
3616         if (r_glsl_saturation_redcompensate.integer)
3617                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3618         if (r_shadow_glossexact.integer)
3619                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3620         if (r_glsl_postprocess.integer)
3621         {
3622                 if (r_glsl_postprocess_uservec1_enable.integer)
3623                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3624                 if (r_glsl_postprocess_uservec2_enable.integer)
3625                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3626                 if (r_glsl_postprocess_uservec3_enable.integer)
3627                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3628                 if (r_glsl_postprocess_uservec4_enable.integer)
3629                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3630         }
3631         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3632 }
3633
3634 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3635         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3636                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3637         else \
3638                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3639 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3640 {
3641         shaderstaticparms_count = 0;
3642
3643         // emit all
3644         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3645         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3646         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3647         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3648         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3649         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3650 }
3651
3652 /// information about each possible shader permutation
3653 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3654 /// currently selected permutation
3655 r_glsl_permutation_t *r_glsl_permutation;
3656 /// storage for permutations linked in the hash table
3657 memexpandablearray_t r_glsl_permutationarray;
3658
3659 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3660 {
3661         //unsigned int hashdepth = 0;
3662         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3663         r_glsl_permutation_t *p;
3664         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3665         {
3666                 if (p->mode == mode && p->permutation == permutation)
3667                 {
3668                         //if (hashdepth > 10)
3669                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3670                         return p;
3671                 }
3672                 //hashdepth++;
3673         }
3674         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3675         p->mode = mode;
3676         p->permutation = permutation;
3677         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3678         r_glsl_permutationhash[mode][hashindex] = p;
3679         //if (hashdepth > 10)
3680         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3681         return p;
3682 }
3683
3684 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3685 {
3686         char *shaderstring;
3687         if (!filename || !filename[0])
3688                 return NULL;
3689         if (!strcmp(filename, "glsl/default.glsl"))
3690         {
3691                 if (!glslshaderstring)
3692                 {
3693                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3694                         if (glslshaderstring)
3695                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3696                         else
3697                                 glslshaderstring = (char *)builtinshaderstring;
3698                 }
3699                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3700                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3701                 return shaderstring;
3702         }
3703         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3704         if (shaderstring)
3705         {
3706                 if (printfromdisknotice)
3707                         Con_DPrintf("from disk %s... ", filename);
3708                 return shaderstring;
3709         }
3710         return shaderstring;
3711 }
3712
3713 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3714 {
3715         int i;
3716         int sampler;
3717         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3718         char *vertexstring, *geometrystring, *fragmentstring;
3719         char permutationname[256];
3720         int vertstrings_count = 0;
3721         int geomstrings_count = 0;
3722         int fragstrings_count = 0;
3723         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3724         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3725         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3726
3727         if (p->compiled)
3728                 return;
3729         p->compiled = true;
3730         p->program = 0;
3731
3732         permutationname[0] = 0;
3733         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3734         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3735         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3736
3737         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3738
3739         // the first pretext is which type of shader to compile as
3740         // (later these will all be bound together as a program object)
3741         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3742         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3743         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3744
3745         // the second pretext is the mode (for example a light source)
3746         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3747         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3748         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3749         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3750
3751         // now add all the permutation pretexts
3752         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3753         {
3754                 if (permutation & (1<<i))
3755                 {
3756                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3757                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3758                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3759                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3760                 }
3761                 else
3762                 {
3763                         // keep line numbers correct
3764                         vertstrings_list[vertstrings_count++] = "\n";
3765                         geomstrings_list[geomstrings_count++] = "\n";
3766                         fragstrings_list[fragstrings_count++] = "\n";
3767                 }
3768         }
3769
3770         // add static parms
3771         R_CompileShader_AddStaticParms(mode, permutation);
3772         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3773         vertstrings_count += shaderstaticparms_count;
3774         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3775         geomstrings_count += shaderstaticparms_count;
3776         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3777         fragstrings_count += shaderstaticparms_count;
3778
3779         // now append the shader text itself
3780         vertstrings_list[vertstrings_count++] = vertexstring;
3781         geomstrings_list[geomstrings_count++] = geometrystring;
3782         fragstrings_list[fragstrings_count++] = fragmentstring;
3783
3784         // if any sources were NULL, clear the respective list
3785         if (!vertexstring)
3786                 vertstrings_count = 0;
3787         if (!geometrystring)
3788                 geomstrings_count = 0;
3789         if (!fragmentstring)
3790                 fragstrings_count = 0;
3791
3792         // compile the shader program
3793         if (vertstrings_count + geomstrings_count + fragstrings_count)
3794                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3795         if (p->program)
3796         {
3797                 CHECKGLERROR
3798                 qglUseProgram(p->program);CHECKGLERROR
3799                 // look up all the uniform variable names we care about, so we don't
3800                 // have to look them up every time we set them
3801
3802                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
3803                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
3804                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3805                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
3806                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
3807                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
3808                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
3809                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3810                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3811                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3812                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3813                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
3814                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
3815                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3816                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
3817                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
3818                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3819                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
3820                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
3821                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
3822                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
3823                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3824                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3825                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3826                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3827                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3828                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3829                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3830                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3831                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
3832                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
3833                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3834                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
3835                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
3836                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
3837                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
3838                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
3839                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
3840                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
3841                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3842                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3843                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3844                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3845                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3846                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3847                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
3848                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
3849                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
3850                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
3851                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3852                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
3853                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
3854                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
3855                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
3856                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3857                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
3858                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
3859                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
3860                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
3861                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
3862                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
3863                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3864                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3865                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
3866                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3867                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3868                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
3869                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
3870                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
3871                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
3872                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
3873                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
3874                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
3875                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
3876                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
3877                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3878                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
3879                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3880                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3881                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
3882                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3883                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
3884                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3885                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
3886                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
3887                 // initialize the samplers to refer to the texture units we use
3888                 p->tex_Texture_First = -1;
3889                 p->tex_Texture_Second = -1;
3890                 p->tex_Texture_GammaRamps = -1;
3891                 p->tex_Texture_Normal = -1;
3892                 p->tex_Texture_Color = -1;
3893                 p->tex_Texture_Gloss = -1;
3894                 p->tex_Texture_Glow = -1;
3895                 p->tex_Texture_SecondaryNormal = -1;
3896                 p->tex_Texture_SecondaryColor = -1;
3897                 p->tex_Texture_SecondaryGloss = -1;
3898                 p->tex_Texture_SecondaryGlow = -1;
3899                 p->tex_Texture_Pants = -1;
3900                 p->tex_Texture_Shirt = -1;
3901                 p->tex_Texture_FogHeightTexture = -1;
3902                 p->tex_Texture_FogMask = -1;
3903                 p->tex_Texture_Lightmap = -1;
3904                 p->tex_Texture_Deluxemap = -1;
3905                 p->tex_Texture_Attenuation = -1;
3906                 p->tex_Texture_Cube = -1;
3907                 p->tex_Texture_Refraction = -1;
3908                 p->tex_Texture_Reflection = -1;
3909                 p->tex_Texture_ShadowMap2D = -1;
3910                 p->tex_Texture_CubeProjection = -1;
3911                 p->tex_Texture_ScreenDepth = -1;
3912                 p->tex_Texture_ScreenNormalMap = -1;
3913                 p->tex_Texture_ScreenDiffuse = -1;
3914                 p->tex_Texture_ScreenSpecular = -1;
3915                 p->tex_Texture_ReflectMask = -1;
3916                 p->tex_Texture_ReflectCube = -1;
3917                 p->tex_Texture_BounceGrid = -1;
3918                 sampler = 0;
3919                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
3920                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
3921                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
3922                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
3923                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
3924                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
3925                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
3926                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3927                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
3928                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
3929                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
3930                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
3931                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
3932                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3933                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
3934                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
3935                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
3936                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
3937                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
3938                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
3939                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
3940                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
3941                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
3942                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
3943                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3944                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
3945                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
3946                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
3947                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
3948                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
3949                 CHECKGLERROR
3950                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3951         }
3952         else
3953                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3954
3955         // free the strings
3956         if (vertexstring)
3957                 Mem_Free(vertexstring);
3958         if (geometrystring)
3959                 Mem_Free(geometrystring);
3960         if (fragmentstring)
3961                 Mem_Free(fragmentstring);
3962 }
3963
3964 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
3965 {
3966         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
3967         if (r_glsl_permutation != perm)
3968         {
3969                 r_glsl_permutation = perm;
3970                 if (!r_glsl_permutation->program)
3971                 {
3972                         if (!r_glsl_permutation->compiled)
3973                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3974                         if (!r_glsl_permutation->program)
3975                         {
3976                                 // remove features until we find a valid permutation
3977                                 int i;
3978                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3979                                 {
3980                                         // reduce i more quickly whenever it would not remove any bits
3981                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
3982                                         if (!(permutation & j))
3983                                                 continue;
3984                                         permutation -= j;
3985                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3986                                         if (!r_glsl_permutation->compiled)
3987                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
3988                                         if (r_glsl_permutation->program)
3989                                                 break;
3990                                 }
3991                                 if (i >= SHADERPERMUTATION_COUNT)
3992                                 {
3993                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
3994                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
3995                                         qglUseProgram(0);CHECKGLERROR
3996                                         return; // no bit left to clear, entire mode is broken
3997                                 }
3998                         }
3999                 }
4000                 CHECKGLERROR
4001                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
4002         }
4003         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4004         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4005         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
4006 }
4007
4008 #ifdef SUPPORTD3D
4009
4010 #ifdef SUPPORTD3D
4011 #include <d3d9.h>
4012 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4013 extern D3DCAPS9 vid_d3d9caps;
4014 #endif
4015
4016 struct r_hlsl_permutation_s;
4017 typedef struct r_hlsl_permutation_s
4018 {
4019         /// hash lookup data
4020         struct r_hlsl_permutation_s *hashnext;
4021         unsigned int mode;
4022         unsigned int permutation;
4023
4024         /// indicates if we have tried compiling this permutation already
4025         qboolean compiled;
4026         /// NULL if compilation failed
4027         IDirect3DVertexShader9 *vertexshader;
4028         IDirect3DPixelShader9 *pixelshader;
4029 }
4030 r_hlsl_permutation_t;
4031
4032 typedef enum D3DVSREGISTER_e
4033 {
4034         D3DVSREGISTER_TexMatrix = 0, // float4x4
4035         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4036         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4037         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4038         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4039         D3DVSREGISTER_ModelToLight = 20, // float4x4
4040         D3DVSREGISTER_EyePosition = 24,
4041         D3DVSREGISTER_FogPlane = 25,
4042         D3DVSREGISTER_LightDir = 26,
4043         D3DVSREGISTER_LightPosition = 27,
4044 }
4045 D3DVSREGISTER_t;
4046
4047 typedef enum D3DPSREGISTER_e
4048 {
4049         D3DPSREGISTER_Alpha = 0,
4050         D3DPSREGISTER_BloomBlur_Parameters = 1,
4051         D3DPSREGISTER_ClientTime = 2,
4052         D3DPSREGISTER_Color_Ambient = 3,
4053         D3DPSREGISTER_Color_Diffuse = 4,
4054         D3DPSREGISTER_Color_Specular = 5,
4055         D3DPSREGISTER_Color_Glow = 6,
4056         D3DPSREGISTER_Color_Pants = 7,
4057         D3DPSREGISTER_Color_Shirt = 8,
4058         D3DPSREGISTER_DeferredColor_Ambient = 9,
4059         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4060         D3DPSREGISTER_DeferredColor_Specular = 11,
4061         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4062         D3DPSREGISTER_DeferredMod_Specular = 13,
4063         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4064         D3DPSREGISTER_EyePosition = 15, // unused
4065         D3DPSREGISTER_FogColor = 16,
4066         D3DPSREGISTER_FogHeightFade = 17,
4067         D3DPSREGISTER_FogPlane = 18,
4068         D3DPSREGISTER_FogPlaneViewDist = 19,
4069         D3DPSREGISTER_FogRangeRecip = 20,
4070         D3DPSREGISTER_LightColor = 21,
4071         D3DPSREGISTER_LightDir = 22, // unused
4072         D3DPSREGISTER_LightPosition = 23,
4073         D3DPSREGISTER_OffsetMapping_Scale = 24,
4074         D3DPSREGISTER_PixelSize = 25,
4075         D3DPSREGISTER_ReflectColor = 26,
4076         D3DPSREGISTER_ReflectFactor = 27,
4077         D3DPSREGISTER_ReflectOffset = 28,
4078         D3DPSREGISTER_RefractColor = 29,
4079         D3DPSREGISTER_Saturation = 30,
4080         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4081         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4082         D3DPSREGISTER_ScreenToDepth = 33,
4083         D3DPSREGISTER_ShadowMap_Parameters = 34,
4084         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4085         D3DPSREGISTER_SpecularPower = 36,
4086         D3DPSREGISTER_UserVec1 = 37,
4087         D3DPSREGISTER_UserVec2 = 38,
4088         D3DPSREGISTER_UserVec3 = 39,
4089         D3DPSREGISTER_UserVec4 = 40,
4090         D3DPSREGISTER_ViewTintColor = 41,
4091         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4092         D3DPSREGISTER_BloomColorSubtract = 43,
4093         D3DPSREGISTER_ViewToLight = 44, // float4x4
4094         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4095         D3DPSREGISTER_NormalmapScrollBlend = 52,
4096         // next at 53
4097 }
4098 D3DPSREGISTER_t;
4099
4100 /// information about each possible shader permutation
4101 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4102 /// currently selected permutation
4103 r_hlsl_permutation_t *r_hlsl_permutation;
4104 /// storage for permutations linked in the hash table
4105 memexpandablearray_t r_hlsl_permutationarray;
4106
4107 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4108 {
4109         //unsigned int hashdepth = 0;
4110         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4111         r_hlsl_permutation_t *p;
4112         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4113         {
4114                 if (p->mode == mode && p->permutation == permutation)
4115                 {
4116                         //if (hashdepth > 10)
4117                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4118                         return p;
4119                 }
4120                 //hashdepth++;
4121         }
4122         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4123         p->mode = mode;
4124         p->permutation = permutation;
4125         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4126         r_hlsl_permutationhash[mode][hashindex] = p;
4127         //if (hashdepth > 10)
4128         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4129         return p;
4130 }
4131
4132 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4133 {
4134         char *shaderstring;
4135         if (!filename || !filename[0])
4136                 return NULL;
4137         if (!strcmp(filename, "hlsl/default.hlsl"))
4138         {
4139                 if (!hlslshaderstring)
4140                 {
4141                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4142                         if (hlslshaderstring)
4143                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4144                         else
4145                                 hlslshaderstring = (char *)builtinhlslshaderstring;
4146                 }
4147                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4148                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4149                 return shaderstring;
4150         }
4151         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4152         if (shaderstring)
4153         {
4154                 if (printfromdisknotice)
4155                         Con_DPrintf("from disk %s... ", filename);
4156                 return shaderstring;
4157         }
4158         return shaderstring;
4159 }
4160
4161 #include <d3dx9.h>
4162 //#include <d3dx9shader.h>
4163 //#include <d3dx9mesh.h>
4164
4165 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4166 {
4167         DWORD *vsbin = NULL;
4168         DWORD *psbin = NULL;
4169         fs_offset_t vsbinsize;
4170         fs_offset_t psbinsize;
4171 //      IDirect3DVertexShader9 *vs = NULL;
4172 //      IDirect3DPixelShader9 *ps = NULL;
4173         ID3DXBuffer *vslog = NULL;
4174         ID3DXBuffer *vsbuffer = NULL;
4175         ID3DXConstantTable *vsconstanttable = NULL;
4176         ID3DXBuffer *pslog = NULL;
4177         ID3DXBuffer *psbuffer = NULL;
4178         ID3DXConstantTable *psconstanttable = NULL;
4179         int vsresult = 0;
4180         int psresult = 0;
4181         char temp[MAX_INPUTLINE];
4182         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4183         qboolean debugshader = gl_paranoid.integer != 0;
4184         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4185         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4186         if (!debugshader)
4187         {
4188                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4189                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4190         }
4191         if ((!vsbin && vertstring) || (!psbin && fragstring))
4192         {
4193                 const char* dllnames_d3dx9 [] =
4194                 {
4195                         "d3dx9_43.dll",
4196                         "d3dx9_42.dll",
4197                         "d3dx9_41.dll",
4198                         "d3dx9_40.dll",
4199                         "d3dx9_39.dll",
4200                         "d3dx9_38.dll",
4201                         "d3dx9_37.dll",
4202                         "d3dx9_36.dll",
4203                         "d3dx9_35.dll",
4204                         "d3dx9_34.dll",
4205                         "d3dx9_33.dll",
4206                         "d3dx9_32.dll",
4207                         "d3dx9_31.dll",
4208                         "d3dx9_30.dll",
4209                         "d3dx9_29.dll",
4210                         "d3dx9_28.dll",
4211                         "d3dx9_27.dll",
4212                         "d3dx9_26.dll",
4213                         "d3dx9_25.dll",
4214                         "d3dx9_24.dll",
4215                         NULL
4216                 };
4217                 dllhandle_t d3dx9_dll = NULL;
4218                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4219                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4220                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4221                 dllfunction_t d3dx9_dllfuncs[] =
4222                 {
4223                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4224                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4225                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4226                         {NULL, NULL}
4227                 };
4228                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4229                 {
4230                         DWORD shaderflags = 0;
4231                         if (debugshader)
4232                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4233                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4234                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4235                         if (vertstring && vertstring[0])
4236                         {
4237                                 if (debugshader)
4238                                 {
4239 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4240 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4241                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4242                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4243                                 }
4244                                 else
4245                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4246                                 if (vsbuffer)
4247                                 {
4248                                         vsbinsize = vsbuffer->GetBufferSize();
4249                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4250                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4251                                         vsbuffer->Release();
4252                                 }
4253                                 if (vslog)
4254                                 {
4255                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4256                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4257                                         vslog->Release();
4258                                 }
4259                         }
4260                         if (fragstring && fragstring[0])
4261                         {
4262                                 if (debugshader)
4263                                 {
4264 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4265 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4266                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4267                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4268                                 }
4269                                 else
4270                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4271                                 if (psbuffer)
4272                                 {
4273                                         psbinsize = psbuffer->GetBufferSize();
4274                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4275                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4276                                         psbuffer->Release();
4277                                 }
4278                                 if (pslog)
4279                                 {
4280                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4281                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4282                                         pslog->Release();
4283                                 }
4284                         }
4285                         Sys_UnloadLibrary(&d3dx9_dll);
4286                 }
4287                 else
4288                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4289         }
4290         if (vsbin && psbin)
4291         {
4292                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4293                 if (FAILED(vsresult))
4294                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4295                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4296                 if (FAILED(psresult))
4297                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4298         }
4299         // free the shader data
4300         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4301         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4302 }
4303
4304 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4305 {
4306         int i;
4307         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4308         int vertstring_length = 0;
4309         int geomstring_length = 0;
4310         int fragstring_length = 0;
4311         char *t;
4312         char *vertexstring, *geometrystring, *fragmentstring;
4313         char *vertstring, *geomstring, *fragstring;
4314         char permutationname[256];
4315         char cachename[256];
4316         int vertstrings_count = 0;
4317         int geomstrings_count = 0;
4318         int fragstrings_count = 0;
4319         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4320         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4321         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4322
4323         if (p->compiled)
4324                 return;
4325         p->compiled = true;
4326         p->vertexshader = NULL;
4327         p->pixelshader = NULL;
4328
4329         permutationname[0] = 0;
4330         cachename[0] = 0;
4331         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4332         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4333         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4334
4335         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4336         strlcat(cachename, "hlsl/", sizeof(cachename));
4337
4338         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4339         vertstrings_count = 0;
4340         geomstrings_count = 0;
4341         fragstrings_count = 0;
4342         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4343         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4344         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4345
4346         // the first pretext is which type of shader to compile as
4347         // (later these will all be bound together as a program object)
4348         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4349         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4350         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4351
4352         // the second pretext is the mode (for example a light source)
4353         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4354         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4355         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4356         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4357         strlcat(cachename, modeinfo->name, sizeof(cachename));
4358
4359         // now add all the permutation pretexts
4360         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4361         {
4362                 if (permutation & (1<<i))
4363                 {
4364                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4365                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4366                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4367                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4368                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4369                 }
4370                 else
4371                 {
4372                         // keep line numbers correct
4373                         vertstrings_list[vertstrings_count++] = "\n";
4374                         geomstrings_list[geomstrings_count++] = "\n";
4375                         fragstrings_list[fragstrings_count++] = "\n";
4376                 }
4377         }
4378
4379         // add static parms
4380         R_CompileShader_AddStaticParms(mode, permutation);
4381         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4382         vertstrings_count += shaderstaticparms_count;
4383         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4384         geomstrings_count += shaderstaticparms_count;
4385         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4386         fragstrings_count += shaderstaticparms_count;
4387
4388         // replace spaces in the cachename with _ characters
4389         for (i = 0;cachename[i];i++)
4390                 if (cachename[i] == ' ')
4391                         cachename[i] = '_';
4392
4393         // now append the shader text itself
4394         vertstrings_list[vertstrings_count++] = vertexstring;
4395         geomstrings_list[geomstrings_count++] = geometrystring;
4396         fragstrings_list[fragstrings_count++] = fragmentstring;
4397
4398         // if any sources were NULL, clear the respective list
4399         if (!vertexstring)
4400                 vertstrings_count = 0;
4401         if (!geometrystring)
4402                 geomstrings_count = 0;
4403         if (!fragmentstring)
4404                 fragstrings_count = 0;
4405
4406         vertstring_length = 0;
4407         for (i = 0;i < vertstrings_count;i++)
4408                 vertstring_length += strlen(vertstrings_list[i]);
4409         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4410         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4411                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4412
4413         geomstring_length = 0;
4414         for (i = 0;i < geomstrings_count;i++)
4415                 geomstring_length += strlen(geomstrings_list[i]);
4416         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4417         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4418                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4419
4420         fragstring_length = 0;
4421         for (i = 0;i < fragstrings_count;i++)
4422                 fragstring_length += strlen(fragstrings_list[i]);
4423         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4424         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4425                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4426
4427         // try to load the cached shader, or generate one
4428         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4429
4430         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4431                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4432         else
4433                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4434
4435         // free the strings
4436         if (vertstring)
4437                 Mem_Free(vertstring);
4438         if (geomstring)
4439                 Mem_Free(geomstring);
4440         if (fragstring)
4441                 Mem_Free(fragstring);
4442         if (vertexstring)
4443                 Mem_Free(vertexstring);
4444         if (geometrystring)
4445                 Mem_Free(geometrystring);
4446         if (fragmentstring)
4447                 Mem_Free(fragmentstring);
4448 }
4449
4450 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4451 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4452 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4453 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4454 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4455 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
4456
4457 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4458 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4459 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4460 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4461 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4462 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
4463
4464 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4465 {
4466         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4467         if (r_hlsl_permutation != perm)
4468         {
4469                 r_hlsl_permutation = perm;
4470                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4471                 {
4472                         if (!r_hlsl_permutation->compiled)
4473                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4474                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4475                         {
4476                                 // remove features until we find a valid permutation
4477                                 int i;
4478                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4479                                 {
4480                                         // reduce i more quickly whenever it would not remove any bits
4481                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4482                                         if (!(permutation & j))
4483                                                 continue;
4484                                         permutation -= j;
4485                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4486                                         if (!r_hlsl_permutation->compiled)
4487                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4488                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4489                                                 break;
4490                                 }
4491                                 if (i >= SHADERPERMUTATION_COUNT)
4492                                 {
4493                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4494                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4495                                         return; // no bit left to clear, entire mode is broken
4496                                 }
4497                         }
4498                 }
4499                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4500                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4501         }
4502         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4503         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4504         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4505 }
4506 #endif
4507
4508 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4509 {
4510         DPSOFTRAST_SetShader(mode, permutation);
4511         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4512         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4513         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4514 }
4515
4516 void R_GLSL_Restart_f(void)
4517 {
4518         unsigned int i, limit;
4519         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4520                 Mem_Free(glslshaderstring);
4521         glslshaderstring = NULL;
4522         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4523                 Mem_Free(hlslshaderstring);
4524         hlslshaderstring = NULL;
4525         switch(vid.renderpath)
4526         {
4527         case RENDERPATH_D3D9:
4528 #ifdef SUPPORTD3D
4529                 {
4530                         r_hlsl_permutation_t *p;
4531                         r_hlsl_permutation = NULL;
4532                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4533                         for (i = 0;i < limit;i++)
4534                         {
4535                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4536                                 {
4537                                         if (p->vertexshader)
4538                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4539                                         if (p->pixelshader)
4540                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4541                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4542                                 }
4543                         }
4544                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4545                 }
4546 #endif
4547                 break;
4548         case RENDERPATH_D3D10:
4549                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4550                 break;
4551         case RENDERPATH_D3D11:
4552                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4553                 break;
4554         case RENDERPATH_GL20:
4555         case RENDERPATH_GLES2:
4556                 {
4557                         r_glsl_permutation_t *p;
4558                         r_glsl_permutation = NULL;
4559                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4560                         for (i = 0;i < limit;i++)
4561                         {
4562                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4563                                 {
4564                                         GL_Backend_FreeProgram(p->program);
4565                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4566                                 }
4567                         }
4568                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4569                 }
4570                 break;
4571         case RENDERPATH_GL13:
4572         case RENDERPATH_GL11:
4573                 break;
4574         case RENDERPATH_SOFT:
4575                 break;
4576         }
4577 }
4578
4579 void R_GLSL_DumpShader_f(void)
4580 {
4581         int i;
4582         qfile_t *file;
4583
4584         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4585         if (file)
4586         {
4587                 FS_Print(file, "/* The engine may define the following macros:\n");
4588                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4589                 for (i = 0;i < SHADERMODE_COUNT;i++)
4590                         FS_Print(file, glslshadermodeinfo[i].pretext);
4591                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4592                         FS_Print(file, shaderpermutationinfo[i].pretext);
4593                 FS_Print(file, "*/\n");
4594                 FS_Print(file, builtinshaderstring);
4595                 FS_Close(file);
4596                 Con_Printf("glsl/default.glsl written\n");
4597         }
4598         else
4599                 Con_Printf("failed to write to glsl/default.glsl\n");
4600
4601         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4602         if (file)
4603         {
4604                 FS_Print(file, "/* The engine may define the following macros:\n");
4605                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4606                 for (i = 0;i < SHADERMODE_COUNT;i++)
4607                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4608                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4609                         FS_Print(file, shaderpermutationinfo[i].pretext);
4610                 FS_Print(file, "*/\n");
4611                 FS_Print(file, builtinhlslshaderstring);
4612                 FS_Close(file);
4613                 Con_Printf("hlsl/default.hlsl written\n");
4614         }
4615         else
4616                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4617 }
4618
4619 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4620 {
4621         if (!second)
4622                 texturemode = GL_MODULATE;
4623         switch (vid.renderpath)
4624         {
4625         case RENDERPATH_D3D9:
4626 #ifdef SUPPORTD3D
4627                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4628                 R_Mesh_TexBind(GL20TU_FIRST , first );
4629                 R_Mesh_TexBind(GL20TU_SECOND, second);
4630 #endif
4631                 break;
4632         case RENDERPATH_D3D10:
4633                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4634                 break;
4635         case RENDERPATH_D3D11:
4636                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4637                 break;
4638         case RENDERPATH_GL20:
4639         case RENDERPATH_GLES2:
4640                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4641                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4642                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4643                 break;
4644         case RENDERPATH_GL13:
4645                 R_Mesh_TexBind(0, first );
4646                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4647                 R_Mesh_TexBind(1, second);
4648                 if (second)
4649                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4650                 break;
4651         case RENDERPATH_GL11:
4652                 R_Mesh_TexBind(0, first );
4653                 break;
4654         case RENDERPATH_SOFT:
4655                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, SHADERPERMUTATION_VIEWTINT | (first ? SHADERPERMUTATION_DIFFUSE : 0) | (second ? SHADERPERMUTATION_SPECULAR : 0) | (texturemode == GL_MODULATE ? SHADERPERMUTATION_COLORMAPPING : (texturemode == GL_ADD ? SHADERPERMUTATION_GLOW : (texturemode == GL_DECAL ? SHADERPERMUTATION_VERTEXTEXTUREBLEND : 0))));
4656                 R_Mesh_TexBind(GL20TU_FIRST , first );
4657                 R_Mesh_TexBind(GL20TU_SECOND, second);
4658                 break;
4659         }
4660 }
4661
4662 void R_SetupShader_DepthOrShadow(void)
4663 {
4664         switch (vid.renderpath)
4665         {
4666         case RENDERPATH_D3D9:
4667 #ifdef SUPPORTD3D
4668                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4669 #endif
4670                 break;
4671         case RENDERPATH_D3D10:
4672                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4673                 break;
4674         case RENDERPATH_D3D11:
4675                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4676                 break;
4677         case RENDERPATH_GL20:
4678         case RENDERPATH_GLES2:
4679                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4680                 break;
4681         case RENDERPATH_GL13:
4682                 R_Mesh_TexBind(0, 0);
4683                 R_Mesh_TexBind(1, 0);
4684                 break;
4685         case RENDERPATH_GL11:
4686                 R_Mesh_TexBind(0, 0);
4687                 break;
4688         case RENDERPATH_SOFT:
4689                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4690                 break;
4691         }
4692 }
4693
4694 void R_SetupShader_ShowDepth(void)
4695 {
4696         switch (vid.renderpath)
4697         {
4698         case RENDERPATH_D3D9:
4699 #ifdef SUPPORTHLSL
4700                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4701 #endif
4702                 break;
4703         case RENDERPATH_D3D10:
4704                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4705                 break;
4706         case RENDERPATH_D3D11:
4707                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4708                 break;
4709         case RENDERPATH_GL20:
4710         case RENDERPATH_GLES2:
4711                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4712                 break;
4713         case RENDERPATH_GL13:
4714                 break;
4715         case RENDERPATH_GL11:
4716                 break;
4717         case RENDERPATH_SOFT:
4718                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4719                 break;
4720         }
4721 }
4722
4723 extern qboolean r_shadow_usingdeferredprepass;
4724 extern cvar_t r_shadow_deferred_8bitrange;
4725 extern rtexture_t *r_shadow_attenuationgradienttexture;
4726 extern rtexture_t *r_shadow_attenuation2dtexture;
4727 extern rtexture_t *r_shadow_attenuation3dtexture;
4728 extern qboolean r_shadow_usingshadowmap2d;
4729 extern qboolean r_shadow_usingshadowmaportho;
4730 extern float r_shadow_shadowmap_texturescale[2];
4731 extern float r_shadow_shadowmap_parameters[4];
4732 extern qboolean r_shadow_shadowmapvsdct;
4733 extern qboolean r_shadow_shadowmapsampler;
4734 extern int r_shadow_shadowmappcf;
4735 extern rtexture_t *r_shadow_shadowmap2dtexture;
4736 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4737 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4738 extern matrix4x4_t r_shadow_shadowmapmatrix;
4739 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4740 extern int r_shadow_prepass_width;
4741 extern int r_shadow_prepass_height;
4742 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4743 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4744 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4745 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4746 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4747 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4748 {
4749         // a blendfunc allows colormod if:
4750         // a) it can never keep the destination pixel invariant, or
4751         // b) it can keep the destination pixel invariant, and still can do so if colormodded
4752         // this is to prevent unintended side effects from colormod
4753
4754         // in formulas:
4755         // IF there is a (s, sa) for which for all (d, da),
4756         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4757         // THEN, for this (s, sa) and all (colormod, d, da):
4758         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4759         // OBVIOUSLY, this means that
4760         //   s*colormod * src(s*colormod, d, sa, da) = 0
4761         //   dst(s*colormod, d, sa, da)              = 1
4762
4763         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4764
4765         // main condition to leave dst color invariant:
4766         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4767         //   src == GL_ZERO:
4768         //     s * 0 + d * dst(s, d, sa, da) == d
4769         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4770         //       => colormod is a problem for GL_SRC_COLOR only
4771         //   src == GL_ONE:
4772         //     s + d * dst(s, d, sa, da) == d
4773         //       => s == 0
4774         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4775         //       => colormod is never problematic for these
4776         //   src == GL_SRC_COLOR:
4777         //     s*s + d * dst(s, d, sa, da) == d
4778         //       => s == 0
4779         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4780         //       => colormod is never problematic for these
4781         //   src == GL_ONE_MINUS_SRC_COLOR:
4782         //     s*(1-s) + d * dst(s, d, sa, da) == d
4783         //       => s == 0 or s == 1
4784         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4785         //       => colormod is a problem for GL_SRC_COLOR only
4786         //   src == GL_DST_COLOR
4787         //     s*d + d * dst(s, d, sa, da) == d
4788         //       => s == 1
4789         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4790         //       => colormod is always a problem
4791         //     or
4792         //       => s == 0
4793         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4794         //       => colormod is never problematic for these
4795         //       => BUT, we do not know s! We must assume it is problematic
4796         //       then... except in GL_ONE case, where we know all invariant
4797         //       cases are fine
4798         //   src == GL_ONE_MINUS_DST_COLOR
4799         //     s*(1-d) + d * dst(s, d, sa, da) == d
4800         //       => s == 0 (1-d is impossible to handle for our desired result)
4801         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4802         //       => colormod is never problematic for these
4803         //   src == GL_SRC_ALPHA
4804         //     s*sa + d * dst(s, d, sa, da) == d
4805         //       => s == 0, or sa == 0
4806         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4807         //       => colormod breaks in the case GL_SRC_COLOR only
4808         //   src == GL_ONE_MINUS_SRC_ALPHA
4809         //     s*(1-sa) + d * dst(s, d, sa, da) == d
4810         //       => s == 0, or sa == 1
4811         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4812         //       => colormod breaks in the case GL_SRC_COLOR only
4813         //   src == GL_DST_ALPHA
4814         //     s*da + d * dst(s, d, sa, da) == d
4815         //       => s == 0
4816         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4817         //       => colormod is never problematic for these
4818
4819         switch(src)
4820         {
4821                 case GL_ZERO:
4822                 case GL_ONE_MINUS_SRC_COLOR:
4823                 case GL_SRC_ALPHA:
4824                 case GL_ONE_MINUS_SRC_ALPHA:
4825                         if(dst == GL_SRC_COLOR)
4826                                 return false;
4827                         return true;
4828                 case GL_ONE:
4829                 case GL_SRC_COLOR:
4830                 case GL_ONE_MINUS_DST_COLOR:
4831                 case GL_DST_ALPHA:
4832                 case GL_ONE_MINUS_DST_ALPHA:
4833                         return true;
4834                 case GL_DST_COLOR:
4835                         if(dst == GL_ONE)
4836                                 return true;
4837                         return false;
4838                 default:
4839                         return false;
4840         }
4841 }
4842 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane)
4843 {
4844         // select a permutation of the lighting shader appropriate to this
4845         // combination of texture, entity, light source, and fogging, only use the
4846         // minimum features necessary to avoid wasting rendering time in the
4847         // fragment shader on features that are not being used
4848         unsigned int permutation = 0;
4849         unsigned int mode = 0;
4850         qboolean allow_colormod;
4851         static float dummy_colormod[3] = {1, 1, 1};
4852         float *colormod = rsurface.colormod;
4853         float m16f[16];
4854         matrix4x4_t tempmatrix;
4855         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4856         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4857                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4858         if (rsurfacepass == RSURFPASS_BACKGROUND)
4859         {
4860                 // distorted background
4861                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4862                 {
4863                         mode = SHADERMODE_WATER;
4864                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4865                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4866                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4867                         {
4868                                 // this is the right thing to do for wateralpha
4869                                 GL_BlendFunc(GL_ONE, GL_ZERO);
4870                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4871                         }
4872                         else
4873                         {
4874                                 // this is the right thing to do for entity alpha
4875                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4876                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4877                         }
4878                 }
4879                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4880                 {
4881                         mode = SHADERMODE_REFRACTION;
4882                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4883                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4884                 }
4885                 else
4886                 {
4887                         mode = SHADERMODE_GENERIC;
4888                         permutation |= SHADERPERMUTATION_DIFFUSE;
4889                         GL_BlendFunc(GL_ONE, GL_ZERO);
4890                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4891                 }
4892         }
4893         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4894         {
4895                 if (r_glsl_offsetmapping.integer)
4896                 {
4897                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4898                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4899                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4900                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4901                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4902                         {
4903                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4904                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4905                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4906                         }
4907                 }
4908                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4909                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4910                 // normalmap (deferred prepass), may use alpha test on diffuse
4911                 mode = SHADERMODE_DEFERREDGEOMETRY;
4912                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4913                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4914                 GL_BlendFunc(GL_ONE, GL_ZERO);
4915                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4916         }
4917         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4918         {
4919                 if (r_glsl_offsetmapping.integer)
4920                 {
4921                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4922                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4923                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4924                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4925                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4926                         {
4927                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4928                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4929                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4930                         }
4931                 }
4932                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4933                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4934                 // light source
4935                 mode = SHADERMODE_LIGHTSOURCE;
4936                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4937                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4938                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4939                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4940                 if (diffusescale > 0)
4941                         permutation |= SHADERPERMUTATION_DIFFUSE;
4942                 if (specularscale > 0)
4943                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
4944                 if (r_refdef.fogenabled)
4945                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4946                 if (rsurface.texture->colormapping)
4947                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4948                 if (r_shadow_usingshadowmap2d)
4949                 {
4950                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4951                         if(r_shadow_shadowmapvsdct)
4952                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4953
4954                         if (r_shadow_shadowmapsampler)
4955                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4956                         if (r_shadow_shadowmappcf > 1)
4957                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
4958                         else if (r_shadow_shadowmappcf)
4959                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
4960                 }
4961                 if (rsurface.texture->reflectmasktexture)
4962                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
4963                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
4964                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
4965         }
4966         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
4967         {
4968                 if (r_glsl_offsetmapping.integer)
4969                 {
4970                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4971                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4972                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4973                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4974                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4975                         {
4976                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4977                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4978                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4979                         }
4980                 }
4981                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4982                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4983                 // unshaded geometry (fullbright or ambient model lighting)
4984                 mode = SHADERMODE_FLATCOLOR;
4985                 ambientscale = diffusescale = specularscale = 0;
4986                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
4987                         permutation |= SHADERPERMUTATION_GLOW;
4988                 if (r_refdef.fogenabled)
4989                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
4990                 if (rsurface.texture->colormapping)
4991                         permutation |= SHADERPERMUTATION_COLORMAPPING;
4992                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
4993                 {
4994                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
4995                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4996
4997                         if (r_shadow_shadowmapsampler)
4998                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
4999                         if (r_shadow_shadowmappcf > 1)
5000                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5001                         else if (r_shadow_shadowmappcf)
5002                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5003                 }
5004                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5005                         permutation |= SHADERPERMUTATION_REFLECTION;
5006                 if (rsurface.texture->reflectmasktexture)
5007                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5008                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5009                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5010         }
5011         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5012         {
5013                 if (r_glsl_offsetmapping.integer)
5014                 {
5015                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5016                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5017                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5018                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5019                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5020                         {
5021                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5022                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5023                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5024                         }
5025                 }
5026                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5027                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5028                 // directional model lighting
5029                 mode = SHADERMODE_LIGHTDIRECTION;
5030                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5031                         permutation |= SHADERPERMUTATION_GLOW;
5032                 permutation |= SHADERPERMUTATION_DIFFUSE;
5033                 if (specularscale > 0)
5034                         permutation |= SHADERPERMUTATION_SPECULAR;
5035                 if (r_refdef.fogenabled)
5036                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5037                 if (rsurface.texture->colormapping)
5038                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5039                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5040                 {
5041                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5042                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5043
5044                         if (r_shadow_shadowmapsampler)
5045                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5046                         if (r_shadow_shadowmappcf > 1)
5047                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5048                         else if (r_shadow_shadowmappcf)
5049                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5050                 }
5051                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5052                         permutation |= SHADERPERMUTATION_REFLECTION;
5053                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5054                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5055                 if (rsurface.texture->reflectmasktexture)
5056                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5057                 if (r_shadow_bouncegridtexture)
5058                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5059                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5060                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5061         }
5062         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5063         {
5064                 if (r_glsl_offsetmapping.integer)
5065                 {
5066                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5067                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5068                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5069                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5070                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5071                         {
5072                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5073                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5074                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5075                         }
5076                 }
5077                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5078                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5079                 // ambient model lighting
5080                 mode = SHADERMODE_LIGHTDIRECTION;
5081                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5082                         permutation |= SHADERPERMUTATION_GLOW;
5083                 if (r_refdef.fogenabled)
5084                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5085                 if (rsurface.texture->colormapping)
5086                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5087                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5088                 {
5089                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5090                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5091
5092                         if (r_shadow_shadowmapsampler)
5093                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5094                         if (r_shadow_shadowmappcf > 1)
5095                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5096                         else if (r_shadow_shadowmappcf)
5097                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5098                 }
5099                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5100                         permutation |= SHADERPERMUTATION_REFLECTION;
5101                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5102                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5103                 if (rsurface.texture->reflectmasktexture)
5104                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5105                 if (r_shadow_bouncegridtexture)
5106                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5107                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5108                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5109         }
5110         else
5111         {
5112                 if (r_glsl_offsetmapping.integer)
5113                 {
5114                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5115                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5116                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5117                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5118                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5119                         {
5120                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5121                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5122                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5123                         }
5124                 }
5125                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5126                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5127                 // lightmapped wall
5128                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5129                         permutation |= SHADERPERMUTATION_GLOW;
5130                 if (r_refdef.fogenabled)
5131                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5132                 if (rsurface.texture->colormapping)
5133                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5134                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5135                 {
5136                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5137                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5138
5139                         if (r_shadow_shadowmapsampler)
5140                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5141                         if (r_shadow_shadowmappcf > 1)
5142                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5143                         else if (r_shadow_shadowmappcf)
5144                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5145                 }
5146                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5147                         permutation |= SHADERPERMUTATION_REFLECTION;
5148                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5149                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5150                 if (rsurface.texture->reflectmasktexture)
5151                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5152                 if (FAKELIGHT_ENABLED)
5153                 {
5154                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5155                         mode = SHADERMODE_FAKELIGHT;
5156                         permutation |= SHADERPERMUTATION_DIFFUSE;
5157                         if (specularscale > 0)
5158                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5159                 }
5160                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5161                 {
5162                         // deluxemapping (light direction texture)
5163                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5164                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5165                         else
5166                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5167                         permutation |= SHADERPERMUTATION_DIFFUSE;
5168                         if (specularscale > 0)
5169                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5170                 }
5171                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5172                 {
5173                         // fake deluxemapping (uniform light direction in tangentspace)
5174                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5175                         permutation |= SHADERPERMUTATION_DIFFUSE;
5176                         if (specularscale > 0)
5177                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5178                 }
5179                 else if (rsurface.uselightmaptexture)
5180                 {
5181                         // ordinary lightmapping (q1bsp, q3bsp)
5182                         mode = SHADERMODE_LIGHTMAP;
5183                 }
5184                 else
5185                 {
5186                         // ordinary vertex coloring (q3bsp)
5187                         mode = SHADERMODE_VERTEXCOLOR;
5188                 }
5189                 if (r_shadow_bouncegridtexture)
5190                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5191                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5192                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5193         }
5194         if(!allow_colormod)
5195                 colormod = dummy_colormod;
5196         switch(vid.renderpath)
5197         {
5198         case RENDERPATH_D3D9:
5199 #ifdef SUPPORTD3D
5200                 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);
5201                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5202                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5203                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5204                 if (mode == SHADERMODE_LIGHTSOURCE)
5205                 {
5206                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5207                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5208                 }
5209                 else
5210                 {
5211                         if (mode == SHADERMODE_LIGHTDIRECTION)
5212                         {
5213                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5214                         }
5215                 }
5216                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5217                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5218                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5219                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5220                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5221
5222                 if (mode == SHADERMODE_LIGHTSOURCE)
5223                 {
5224                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5225                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5226                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5227                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5228                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5229
5230                         // additive passes are only darkened by fog, not tinted
5231                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5232                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5233                 }
5234                 else
5235                 {
5236                         if (mode == SHADERMODE_FLATCOLOR)
5237                         {
5238                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5239                         }
5240                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5241                         {
5242                                 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]);
5243                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5244                                 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);
5245                                 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);
5246                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5247                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5248                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5249                         }
5250                         else
5251                         {
5252                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5253                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5254                                 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);
5255                                 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);
5256                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5257                         }
5258                         // additive passes are only darkened by fog, not tinted
5259                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5260                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5261                         else
5262                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5263                         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);
5264                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5265                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5266                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5267                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5268                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5269                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5270                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5271                         if (mode == SHADERMODE_WATER)
5272                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5273                 }
5274                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5275                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5276                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5277                 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));
5278                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5279                 if (rsurface.texture->pantstexture)
5280                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5281                 else
5282                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5283                 if (rsurface.texture->shirttexture)
5284                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5285                 else
5286                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5287                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5288                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5289                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5290                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5291                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5292                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5293                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5294
5295                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5296                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5297                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5298                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5299                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5300                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5301                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5302                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5303                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5304                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5305                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5306                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5307                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5308                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5309                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5310                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5311                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5312                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5313                 {
5314                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5315                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5316                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5317                 }
5318                 else
5319                 {
5320                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5321                 }
5322 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5323 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5324                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5325                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5326                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5327                 {
5328                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5329                         if (rsurface.rtlight)
5330                         {
5331                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5332                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5333                         }
5334                 }
5335 #endif
5336                 break;
5337         case RENDERPATH_D3D10:
5338                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5339                 break;
5340         case RENDERPATH_D3D11:
5341                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5342                 break;
5343         case RENDERPATH_GL20:
5344         case RENDERPATH_GLES2:
5345                 if (!vid.useinterleavedarrays)
5346                 {
5347                         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);
5348                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5349                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5350                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5351                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5352                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5353                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5354                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5355                 }
5356                 else
5357                 {
5358                         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);
5359                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5360                 }
5361                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5362                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5363                 if (mode == SHADERMODE_LIGHTSOURCE)
5364                 {
5365                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5366                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5367                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5368                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5369                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5370                         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);
5371         
5372                         // additive passes are only darkened by fog, not tinted
5373                         if (r_glsl_permutation->loc_FogColor >= 0)
5374                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5375                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5376                 }
5377                 else
5378                 {
5379                         if (mode == SHADERMODE_FLATCOLOR)
5380                         {
5381                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5382                         }
5383                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5384                         {
5385                                 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]);
5386                                 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]);
5387                                 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);
5388                                 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);
5389                                 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);
5390                                 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]);
5391                                 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]);
5392                         }
5393                         else
5394                         {
5395                                 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]);
5396                                 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]);
5397                                 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);
5398                                 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);
5399                                 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);
5400                         }
5401                         // additive passes are only darkened by fog, not tinted
5402                         if (r_glsl_permutation->loc_FogColor >= 0)
5403                         {
5404                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5405                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5406                                 else
5407                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5408                         }
5409                         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);
5410                         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]);
5411                         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]);
5412                         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]);
5413                         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]);
5414                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5415                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5416                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5417                         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]);
5418                 }
5419                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5420                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5421                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5422                 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]);
5423                 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]);
5424
5425                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5426                 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));
5427                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5428                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5429                 {
5430                         if (rsurface.texture->pantstexture)
5431                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5432                         else
5433                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5434                 }
5435                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5436                 {
5437                         if (rsurface.texture->shirttexture)
5438                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5439                         else
5440                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5441                 }
5442                 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]);
5443                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5444                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5445                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5446                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5447                 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]);
5448                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5449                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
5450                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
5451
5452                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
5453                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
5454                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
5455                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
5456                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
5457                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
5458                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
5459                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
5460                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
5461                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
5462                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
5463                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
5464                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
5465                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
5466                 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);
5467                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
5468                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
5469                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5470                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5471                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
5472                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5473                 {
5474                         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);
5475                         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);
5476                         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);
5477                 }
5478                 else
5479                 {
5480                         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);
5481                 }
5482                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
5483                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
5484                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
5485                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
5486                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5487                 {
5488                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
5489                         if (rsurface.rtlight)
5490                         {
5491                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
5492                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
5493                         }
5494                 }
5495                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
5496                 CHECKGLERROR
5497                 break;
5498         case RENDERPATH_GL13:
5499         case RENDERPATH_GL11:
5500                 break;
5501         case RENDERPATH_SOFT:
5502                 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);
5503                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5504                 R_SetupShader_SetPermutationSoft(mode, permutation);
5505                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5506                 if (mode == SHADERMODE_LIGHTSOURCE)
5507                 {
5508                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5509                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5510                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5511                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5512                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5513                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5514         
5515                         // additive passes are only darkened by fog, not tinted
5516                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5517                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5518                 }
5519                 else
5520                 {
5521                         if (mode == SHADERMODE_FLATCOLOR)
5522                         {
5523                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5524                         }
5525                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5526                         {
5527                                 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]);
5528                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5529                                 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);
5530                                 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);
5531                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5532                                 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]);
5533                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5534                         }
5535                         else
5536                         {
5537                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5538                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5539                                 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);
5540                                 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);
5541                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5542                         }
5543                         // additive passes are only darkened by fog, not tinted
5544                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5545                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5546                         else
5547                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5548                         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);
5549                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5550                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5551                         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]);
5552                         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]);
5553                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5554                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5555                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5556                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5557                 }
5558                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5559                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5560                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5561                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5562                 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]);
5563
5564                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5565                 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));
5566                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5567                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5568                 {
5569                         if (rsurface.texture->pantstexture)
5570                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5571                         else
5572                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5573                 }
5574                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5575                 {
5576                         if (rsurface.texture->shirttexture)
5577                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5578                         else
5579                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5580                 }
5581                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5582                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5583                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5584                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5585                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5586                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5587                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5588
5589                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5590                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5591                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5592                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5593                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5594                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5595                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5596                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5597                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5598                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5599                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5600                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5601                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5602                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5603                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5604                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5605                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5606                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5607                 {
5608                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5609                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5610                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5611                 }
5612                 else
5613                 {
5614                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5615                 }
5616 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5617 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5618                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5619                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5620                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5621                 {
5622                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5623                         if (rsurface.rtlight)
5624                         {
5625                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5626                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5627                         }
5628                 }
5629                 break;
5630         }
5631 }
5632
5633 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5634 {
5635         // select a permutation of the lighting shader appropriate to this
5636         // combination of texture, entity, light source, and fogging, only use the
5637         // minimum features necessary to avoid wasting rendering time in the
5638         // fragment shader on features that are not being used
5639         unsigned int permutation = 0;
5640         unsigned int mode = 0;
5641         const float *lightcolorbase = rtlight->currentcolor;
5642         float ambientscale = rtlight->ambientscale;
5643         float diffusescale = rtlight->diffusescale;
5644         float specularscale = rtlight->specularscale;
5645         // this is the location of the light in view space
5646         vec3_t viewlightorigin;
5647         // this transforms from view space (camera) to light space (cubemap)
5648         matrix4x4_t viewtolight;
5649         matrix4x4_t lighttoview;
5650         float viewtolight16f[16];
5651         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5652         // light source
5653         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5654         if (rtlight->currentcubemap != r_texture_whitecube)
5655                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5656         if (diffusescale > 0)
5657                 permutation |= SHADERPERMUTATION_DIFFUSE;
5658         if (specularscale > 0)
5659                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5660         if (r_shadow_usingshadowmap2d)
5661         {
5662                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5663                 if (r_shadow_shadowmapvsdct)
5664                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5665
5666                 if (r_shadow_shadowmapsampler)
5667                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5668                 if (r_shadow_shadowmappcf > 1)
5669                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5670                 else if (r_shadow_shadowmappcf)
5671                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5672         }
5673         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5674         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5675         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5676         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5677         switch(vid.renderpath)
5678         {
5679         case RENDERPATH_D3D9:
5680 #ifdef SUPPORTD3D
5681                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5682                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5683                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5684                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5685                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5686                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5687                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5688                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5689                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5690                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5691                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5692
5693                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5694                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
5695                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5696                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5697                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
5698                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5699 #endif
5700                 break;
5701         case RENDERPATH_D3D10:
5702                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5703                 break;
5704         case RENDERPATH_D3D11:
5705                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5706                 break;
5707         case RENDERPATH_GL20:
5708         case RENDERPATH_GLES2:
5709                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5710                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5711                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5712                 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);
5713                 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);
5714                 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);
5715                 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]);
5716                 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]);
5717                 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));
5718                 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]);
5719                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
5720
5721                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
5722                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
5723                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
5724                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
5725                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
5726                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
5727                 break;
5728         case RENDERPATH_GL13:
5729         case RENDERPATH_GL11:
5730                 break;
5731         case RENDERPATH_SOFT:
5732                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5733                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5734                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
5735                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5736                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5737                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5738                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5739                 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]);
5740                 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));
5741                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5742                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5743
5744                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5745                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5746                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5747                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5748                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5749                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5750                 break;
5751         }
5752 }
5753
5754 #define SKINFRAME_HASH 1024
5755
5756 typedef struct
5757 {
5758         int loadsequence; // incremented each level change
5759         memexpandablearray_t array;
5760         skinframe_t *hash[SKINFRAME_HASH];
5761 }
5762 r_skinframe_t;
5763 r_skinframe_t r_skinframe;
5764
5765 void R_SkinFrame_PrepareForPurge(void)
5766 {
5767         r_skinframe.loadsequence++;
5768         // wrap it without hitting zero
5769         if (r_skinframe.loadsequence >= 200)
5770                 r_skinframe.loadsequence = 1;
5771 }
5772
5773 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5774 {
5775         if (!skinframe)
5776                 return;
5777         // mark the skinframe as used for the purging code
5778         skinframe->loadsequence = r_skinframe.loadsequence;
5779 }
5780
5781 void R_SkinFrame_Purge(void)
5782 {
5783         int i;
5784         skinframe_t *s;
5785         for (i = 0;i < SKINFRAME_HASH;i++)
5786         {
5787                 for (s = r_skinframe.hash[i];s;s = s->next)
5788                 {
5789                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5790                         {
5791                                 if (s->merged == s->base)
5792                                         s->merged = NULL;
5793                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5794                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5795                                 R_PurgeTexture(s->merged);s->merged = NULL;
5796                                 R_PurgeTexture(s->base  );s->base   = NULL;
5797                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5798                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5799                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5800                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5801                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5802                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5803                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5804                                 s->loadsequence = 0;
5805                         }
5806                 }
5807         }
5808 }
5809
5810 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5811         skinframe_t *item;
5812         char basename[MAX_QPATH];
5813
5814         Image_StripImageExtension(name, basename, sizeof(basename));
5815
5816         if( last == NULL ) {
5817                 int hashindex;
5818                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5819                 item = r_skinframe.hash[hashindex];
5820         } else {
5821                 item = last->next;
5822         }
5823
5824         // linearly search through the hash bucket
5825         for( ; item ; item = item->next ) {
5826                 if( !strcmp( item->basename, basename ) ) {
5827                         return item;
5828                 }
5829         }
5830         return NULL;
5831 }
5832
5833 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5834 {
5835         skinframe_t *item;
5836         int hashindex;
5837         char basename[MAX_QPATH];
5838
5839         Image_StripImageExtension(name, basename, sizeof(basename));
5840
5841         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5842         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5843                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5844                         break;
5845
5846         if (!item) {
5847                 rtexture_t *dyntexture;
5848                 // check whether its a dynamic texture
5849                 dyntexture = CL_GetDynTexture( basename );
5850                 if (!add && !dyntexture)
5851                         return NULL;
5852                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5853                 memset(item, 0, sizeof(*item));
5854                 strlcpy(item->basename, basename, sizeof(item->basename));
5855                 item->base = dyntexture; // either NULL or dyntexture handle
5856                 item->textureflags = textureflags;
5857                 item->comparewidth = comparewidth;
5858                 item->compareheight = compareheight;
5859                 item->comparecrc = comparecrc;
5860                 item->next = r_skinframe.hash[hashindex];
5861                 r_skinframe.hash[hashindex] = item;
5862         }
5863         else if( item->base == NULL )
5864         {
5865                 rtexture_t *dyntexture;
5866                 // check whether its a dynamic texture
5867                 // 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]
5868                 dyntexture = CL_GetDynTexture( basename );
5869                 item->base = dyntexture; // either NULL or dyntexture handle
5870         }
5871
5872         R_SkinFrame_MarkUsed(item);
5873         return item;
5874 }
5875
5876 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5877         { \
5878                 unsigned long long avgcolor[5], wsum; \
5879                 int pix, comp, w; \
5880                 avgcolor[0] = 0; \
5881                 avgcolor[1] = 0; \
5882                 avgcolor[2] = 0; \
5883                 avgcolor[3] = 0; \
5884                 avgcolor[4] = 0; \
5885                 wsum = 0; \
5886                 for(pix = 0; pix < cnt; ++pix) \
5887                 { \
5888                         w = 0; \
5889                         for(comp = 0; comp < 3; ++comp) \
5890                                 w += getpixel; \
5891                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5892                         { \
5893                                 ++wsum; \
5894                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5895                                 w = getpixel; \
5896                                 for(comp = 0; comp < 3; ++comp) \
5897                                         avgcolor[comp] += getpixel * w; \
5898                                 avgcolor[3] += w; \
5899                         } \
5900                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5901                         avgcolor[4] += getpixel; \
5902                 } \
5903                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5904                         avgcolor[3] = 1; \
5905                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5906                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5907                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5908                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5909         }
5910
5911 extern cvar_t gl_picmip;
5912 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
5913 {
5914         int j;
5915         unsigned char *pixels;
5916         unsigned char *bumppixels;
5917         unsigned char *basepixels = NULL;
5918         int basepixels_width = 0;
5919         int basepixels_height = 0;
5920         skinframe_t *skinframe;
5921         rtexture_t *ddsbase = NULL;
5922         qboolean ddshasalpha = false;
5923         float ddsavgcolor[4];
5924         char basename[MAX_QPATH];
5925         int miplevel = R_PicmipForFlags(textureflags);
5926         int savemiplevel = miplevel;
5927         int mymiplevel;
5928
5929         if (cls.state == ca_dedicated)
5930                 return NULL;
5931
5932         // return an existing skinframe if already loaded
5933         // if loading of the first image fails, don't make a new skinframe as it
5934         // would cause all future lookups of this to be missing
5935         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
5936         if (skinframe && skinframe->base)
5937                 return skinframe;
5938
5939         Image_StripImageExtension(name, basename, sizeof(basename));
5940
5941         // check for DDS texture file first
5942         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
5943         {
5944                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
5945                 if (basepixels == NULL)
5946                         return NULL;
5947         }
5948
5949         // FIXME handle miplevel
5950
5951         if (developer_loading.integer)
5952                 Con_Printf("loading skin \"%s\"\n", name);
5953
5954         // we've got some pixels to store, so really allocate this new texture now
5955         if (!skinframe)
5956                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
5957         skinframe->stain = NULL;
5958         skinframe->merged = NULL;
5959         skinframe->base = NULL;
5960         skinframe->pants = NULL;
5961         skinframe->shirt = NULL;
5962         skinframe->nmap = NULL;
5963         skinframe->gloss = NULL;
5964         skinframe->glow = NULL;
5965         skinframe->fog = NULL;
5966         skinframe->reflect = NULL;
5967         skinframe->hasalpha = false;
5968
5969         if (ddsbase)
5970         {
5971                 skinframe->base = ddsbase;
5972                 skinframe->hasalpha = ddshasalpha;
5973                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
5974                 if (r_loadfog && skinframe->hasalpha)
5975                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
5976                 //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]);
5977         }
5978         else
5979         {
5980                 basepixels_width = image_width;
5981                 basepixels_height = image_height;
5982                 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);
5983                 if (textureflags & TEXF_ALPHA)
5984                 {
5985                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
5986                         {
5987                                 if (basepixels[j] < 255)
5988                                 {
5989                                         skinframe->hasalpha = true;
5990                                         break;
5991                                 }
5992                         }
5993                         if (r_loadfog && skinframe->hasalpha)
5994                         {
5995                                 // has transparent pixels
5996                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
5997                                 for (j = 0;j < image_width * image_height * 4;j += 4)
5998                                 {
5999                                         pixels[j+0] = 255;
6000                                         pixels[j+1] = 255;
6001                                         pixels[j+2] = 255;
6002                                         pixels[j+3] = basepixels[j+3];
6003                                 }
6004                                 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);
6005                                 Mem_Free(pixels);
6006                         }
6007                 }
6008                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6009                 //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]);
6010                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6011                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6012                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6013                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6014         }
6015
6016         if (r_loaddds)
6017         {
6018                 mymiplevel = savemiplevel;
6019                 if (r_loadnormalmap)
6020                         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);
6021                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6022                 if (r_loadgloss)
6023                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6024                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6025                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6026                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6027         }
6028
6029         // _norm is the name used by tenebrae and has been adopted as standard
6030         if (r_loadnormalmap && skinframe->nmap == NULL)
6031         {
6032                 mymiplevel = savemiplevel;
6033                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6034                 {
6035                         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);
6036                         Mem_Free(pixels);
6037                         pixels = NULL;
6038                 }
6039                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6040                 {
6041                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6042                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6043                         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);
6044                         Mem_Free(pixels);
6045                         Mem_Free(bumppixels);
6046                 }
6047                 else if (r_shadow_bumpscale_basetexture.value > 0)
6048                 {
6049                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6050                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6051                         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);
6052                         Mem_Free(pixels);
6053                 }
6054                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6055                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6056         }
6057
6058         // _luma is supported only for tenebrae compatibility
6059         // _glow is the preferred name
6060         mymiplevel = savemiplevel;
6061         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))))
6062         {
6063                 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);
6064                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6065                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6066                 Mem_Free(pixels);pixels = NULL;
6067         }
6068
6069         mymiplevel = savemiplevel;
6070         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6071         {
6072                 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);
6073                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6074                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6075                 Mem_Free(pixels);
6076                 pixels = NULL;
6077         }
6078
6079         mymiplevel = savemiplevel;
6080         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6081         {
6082                 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);
6083                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6084                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6085                 Mem_Free(pixels);
6086                 pixels = NULL;
6087         }
6088
6089         mymiplevel = savemiplevel;
6090         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6091         {
6092                 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);
6093                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6094                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6095                 Mem_Free(pixels);
6096                 pixels = NULL;
6097         }
6098
6099         mymiplevel = savemiplevel;
6100         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6101         {
6102                 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);
6103                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6104                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6105                 Mem_Free(pixels);
6106                 pixels = NULL;
6107         }
6108
6109         if (basepixels)
6110                 Mem_Free(basepixels);
6111
6112         return skinframe;
6113 }
6114
6115 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6116 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6117 {
6118         int i;
6119         unsigned char *temp1, *temp2;
6120         skinframe_t *skinframe;
6121
6122         if (cls.state == ca_dedicated)
6123                 return NULL;
6124
6125         // if already loaded just return it, otherwise make a new skinframe
6126         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6127         if (skinframe && skinframe->base)
6128                 return skinframe;
6129
6130         skinframe->stain = NULL;
6131         skinframe->merged = NULL;
6132         skinframe->base = NULL;
6133         skinframe->pants = NULL;
6134         skinframe->shirt = NULL;
6135         skinframe->nmap = NULL;
6136         skinframe->gloss = NULL;
6137         skinframe->glow = NULL;
6138         skinframe->fog = NULL;
6139         skinframe->reflect = NULL;
6140         skinframe->hasalpha = false;
6141
6142         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6143         if (!skindata)
6144                 return NULL;
6145
6146         if (developer_loading.integer)
6147                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6148
6149         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6150         {
6151                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6152                 temp2 = temp1 + width * height * 4;
6153                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6154                 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);
6155                 Mem_Free(temp1);
6156         }
6157         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6158         if (textureflags & TEXF_ALPHA)
6159         {
6160                 for (i = 3;i < width * height * 4;i += 4)
6161                 {
6162                         if (skindata[i] < 255)
6163                         {
6164                                 skinframe->hasalpha = true;
6165                                 break;
6166                         }
6167                 }
6168                 if (r_loadfog && skinframe->hasalpha)
6169                 {
6170                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6171                         memcpy(fogpixels, skindata, width * height * 4);
6172                         for (i = 0;i < width * height * 4;i += 4)
6173                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6174                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6175                         Mem_Free(fogpixels);
6176                 }
6177         }
6178
6179         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6180         //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]);
6181
6182         return skinframe;
6183 }
6184
6185 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6186 {
6187         int i;
6188         int featuresmask;
6189         skinframe_t *skinframe;
6190
6191         if (cls.state == ca_dedicated)
6192                 return NULL;
6193
6194         // if already loaded just return it, otherwise make a new skinframe
6195         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6196         if (skinframe && skinframe->base)
6197                 return skinframe;
6198
6199         skinframe->stain = NULL;
6200         skinframe->merged = NULL;
6201         skinframe->base = NULL;
6202         skinframe->pants = NULL;
6203         skinframe->shirt = NULL;
6204         skinframe->nmap = NULL;
6205         skinframe->gloss = NULL;
6206         skinframe->glow = NULL;
6207         skinframe->fog = NULL;
6208         skinframe->reflect = NULL;
6209         skinframe->hasalpha = false;
6210
6211         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6212         if (!skindata)
6213                 return NULL;
6214
6215         if (developer_loading.integer)
6216                 Con_Printf("loading quake skin \"%s\"\n", name);
6217
6218         // 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)
6219         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6220         memcpy(skinframe->qpixels, skindata, width*height);
6221         skinframe->qwidth = width;
6222         skinframe->qheight = height;
6223
6224         featuresmask = 0;
6225         for (i = 0;i < width * height;i++)
6226                 featuresmask |= palette_featureflags[skindata[i]];
6227
6228         skinframe->hasalpha = false;
6229         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6230         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6231         skinframe->qgeneratemerged = true;
6232         skinframe->qgeneratebase = skinframe->qhascolormapping;
6233         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6234
6235         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6236         //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]);
6237
6238         return skinframe;
6239 }
6240
6241 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6242 {
6243         int width;
6244         int height;
6245         unsigned char *skindata;
6246
6247         if (!skinframe->qpixels)
6248                 return;
6249
6250         if (!skinframe->qhascolormapping)
6251                 colormapped = false;
6252
6253         if (colormapped)
6254         {
6255                 if (!skinframe->qgeneratebase)
6256                         return;
6257         }
6258         else
6259         {
6260                 if (!skinframe->qgeneratemerged)
6261                         return;
6262         }
6263
6264         width = skinframe->qwidth;
6265         height = skinframe->qheight;
6266         skindata = skinframe->qpixels;
6267
6268         if (skinframe->qgeneratenmap)
6269         {
6270                 unsigned char *temp1, *temp2;
6271                 skinframe->qgeneratenmap = false;
6272                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6273                 temp2 = temp1 + width * height * 4;
6274                 // use either a custom palette or the quake palette
6275                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6276                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6277                 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);
6278                 Mem_Free(temp1);
6279         }
6280
6281         if (skinframe->qgenerateglow)
6282         {
6283                 skinframe->qgenerateglow = false;
6284                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6285         }
6286
6287         if (colormapped)
6288         {
6289                 skinframe->qgeneratebase = false;
6290                 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);
6291                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6292                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6293         }
6294         else
6295         {
6296                 skinframe->qgeneratemerged = false;
6297                 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);
6298         }
6299
6300         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6301         {
6302                 Mem_Free(skinframe->qpixels);
6303                 skinframe->qpixels = NULL;
6304         }
6305 }
6306
6307 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)
6308 {
6309         int i;
6310         skinframe_t *skinframe;
6311
6312         if (cls.state == ca_dedicated)
6313                 return NULL;
6314
6315         // if already loaded just return it, otherwise make a new skinframe
6316         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6317         if (skinframe && skinframe->base)
6318                 return skinframe;
6319
6320         skinframe->stain = NULL;
6321         skinframe->merged = NULL;
6322         skinframe->base = NULL;
6323         skinframe->pants = NULL;
6324         skinframe->shirt = NULL;
6325         skinframe->nmap = NULL;
6326         skinframe->gloss = NULL;
6327         skinframe->glow = NULL;
6328         skinframe->fog = NULL;
6329         skinframe->reflect = NULL;
6330         skinframe->hasalpha = false;
6331
6332         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6333         if (!skindata)
6334                 return NULL;
6335
6336         if (developer_loading.integer)
6337                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6338
6339         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6340         if (textureflags & TEXF_ALPHA)
6341         {
6342                 for (i = 0;i < width * height;i++)
6343                 {
6344                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6345                         {
6346                                 skinframe->hasalpha = true;
6347                                 break;
6348                         }
6349                 }
6350                 if (r_loadfog && skinframe->hasalpha)
6351                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6352         }
6353
6354         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6355         //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]);
6356
6357         return skinframe;
6358 }
6359
6360 skinframe_t *R_SkinFrame_LoadMissing(void)
6361 {
6362         skinframe_t *skinframe;
6363
6364         if (cls.state == ca_dedicated)
6365                 return NULL;
6366
6367         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6368         skinframe->stain = NULL;
6369         skinframe->merged = NULL;
6370         skinframe->base = NULL;
6371         skinframe->pants = NULL;
6372         skinframe->shirt = NULL;
6373         skinframe->nmap = NULL;
6374         skinframe->gloss = NULL;
6375         skinframe->glow = NULL;
6376         skinframe->fog = NULL;
6377         skinframe->reflect = NULL;
6378         skinframe->hasalpha = false;
6379
6380         skinframe->avgcolor[0] = rand() / RAND_MAX;
6381         skinframe->avgcolor[1] = rand() / RAND_MAX;
6382         skinframe->avgcolor[2] = rand() / RAND_MAX;
6383         skinframe->avgcolor[3] = 1;
6384
6385         return skinframe;
6386 }
6387
6388 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6389 typedef struct suffixinfo_s
6390 {
6391         const char *suffix;
6392         qboolean flipx, flipy, flipdiagonal;
6393 }
6394 suffixinfo_t;
6395 static suffixinfo_t suffix[3][6] =
6396 {
6397         {
6398                 {"px",   false, false, false},
6399                 {"nx",   false, false, false},
6400                 {"py",   false, false, false},
6401                 {"ny",   false, false, false},
6402                 {"pz",   false, false, false},
6403                 {"nz",   false, false, false}
6404         },
6405         {
6406                 {"posx", false, false, false},
6407                 {"negx", false, false, false},
6408                 {"posy", false, false, false},
6409                 {"negy", false, false, false},
6410                 {"posz", false, false, false},
6411                 {"negz", false, false, false}
6412         },
6413         {
6414                 {"rt",    true, false,  true},
6415                 {"lf",   false,  true,  true},
6416                 {"ft",    true,  true, false},
6417                 {"bk",   false, false, false},
6418                 {"up",    true, false,  true},
6419                 {"dn",    true, false,  true}
6420         }
6421 };
6422
6423 static int componentorder[4] = {0, 1, 2, 3};
6424
6425 rtexture_t *R_LoadCubemap(const char *basename)
6426 {
6427         int i, j, cubemapsize;
6428         unsigned char *cubemappixels, *image_buffer;
6429         rtexture_t *cubemaptexture;
6430         char name[256];
6431         // must start 0 so the first loadimagepixels has no requested width/height
6432         cubemapsize = 0;
6433         cubemappixels = NULL;
6434         cubemaptexture = NULL;
6435         // keep trying different suffix groups (posx, px, rt) until one loads
6436         for (j = 0;j < 3 && !cubemappixels;j++)
6437         {
6438                 // load the 6 images in the suffix group
6439                 for (i = 0;i < 6;i++)
6440                 {
6441                         // generate an image name based on the base and and suffix
6442                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6443                         // load it
6444                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6445                         {
6446                                 // an image loaded, make sure width and height are equal
6447                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6448                                 {
6449                                         // if this is the first image to load successfully, allocate the cubemap memory
6450                                         if (!cubemappixels && image_width >= 1)
6451                                         {
6452                                                 cubemapsize = image_width;
6453                                                 // note this clears to black, so unavailable sides are black
6454                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6455                                         }
6456                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6457                                         if (cubemappixels)
6458                                                 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);
6459                                 }
6460                                 else
6461                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6462                                 // free the image
6463                                 Mem_Free(image_buffer);
6464                         }
6465                 }
6466         }
6467         // if a cubemap loaded, upload it
6468         if (cubemappixels)
6469         {
6470                 if (developer_loading.integer)
6471                         Con_Printf("loading cubemap \"%s\"\n", basename);
6472
6473                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6474                 Mem_Free(cubemappixels);
6475         }
6476         else
6477         {
6478                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6479                 if (developer_loading.integer)
6480                 {
6481                         Con_Printf("(tried tried images ");
6482                         for (j = 0;j < 3;j++)
6483                                 for (i = 0;i < 6;i++)
6484                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6485                         Con_Print(" and was unable to find any of them).\n");
6486                 }
6487         }
6488         return cubemaptexture;
6489 }
6490
6491 rtexture_t *R_GetCubemap(const char *basename)
6492 {
6493         int i;
6494         for (i = 0;i < r_texture_numcubemaps;i++)
6495                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6496                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6497         if (i >= MAX_CUBEMAPS)
6498                 return r_texture_whitecube;
6499         r_texture_numcubemaps++;
6500         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6501         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6502         return r_texture_cubemaps[i].texture;
6503 }
6504
6505 void R_FreeCubemaps(void)
6506 {
6507         int i;
6508         for (i = 0;i < r_texture_numcubemaps;i++)
6509         {
6510                 if (developer_loading.integer)
6511                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6512                 if (r_texture_cubemaps[i].texture)
6513                         R_FreeTexture(r_texture_cubemaps[i].texture);
6514         }
6515         r_texture_numcubemaps = 0;
6516 }
6517
6518 void R_Main_FreeViewCache(void)
6519 {
6520         if (r_refdef.viewcache.entityvisible)
6521                 Mem_Free(r_refdef.viewcache.entityvisible);
6522         if (r_refdef.viewcache.world_pvsbits)
6523                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6524         if (r_refdef.viewcache.world_leafvisible)
6525                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6526         if (r_refdef.viewcache.world_surfacevisible)
6527                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6528         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6529 }
6530
6531 void R_Main_ResizeViewCache(void)
6532 {
6533         int numentities = r_refdef.scene.numentities;
6534         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6535         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6536         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6537         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6538         if (r_refdef.viewcache.maxentities < numentities)
6539         {
6540                 r_refdef.viewcache.maxentities = numentities;
6541                 if (r_refdef.viewcache.entityvisible)
6542                         Mem_Free(r_refdef.viewcache.entityvisible);
6543                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6544         }
6545         if (r_refdef.viewcache.world_numclusters != numclusters)
6546         {
6547                 r_refdef.viewcache.world_numclusters = numclusters;
6548                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6549                 if (r_refdef.viewcache.world_pvsbits)
6550                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6551                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6552         }
6553         if (r_refdef.viewcache.world_numleafs != numleafs)
6554         {
6555                 r_refdef.viewcache.world_numleafs = numleafs;
6556                 if (r_refdef.viewcache.world_leafvisible)
6557                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6558                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6559         }
6560         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6561         {
6562                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6563                 if (r_refdef.viewcache.world_surfacevisible)
6564                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6565                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6566         }
6567 }
6568
6569 extern rtexture_t *loadingscreentexture;
6570 void gl_main_start(void)
6571 {
6572         loadingscreentexture = NULL;
6573         r_texture_blanknormalmap = NULL;
6574         r_texture_white = NULL;
6575         r_texture_grey128 = NULL;
6576         r_texture_black = NULL;
6577         r_texture_whitecube = NULL;
6578         r_texture_normalizationcube = NULL;
6579         r_texture_fogattenuation = NULL;
6580         r_texture_fogheighttexture = NULL;
6581         r_texture_gammaramps = NULL;
6582         r_texture_numcubemaps = 0;
6583
6584         r_loaddds = r_texture_dds_load.integer != 0;
6585         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6586
6587         switch(vid.renderpath)
6588         {
6589         case RENDERPATH_GL20:
6590         case RENDERPATH_D3D9:
6591         case RENDERPATH_D3D10:
6592         case RENDERPATH_D3D11:
6593         case RENDERPATH_SOFT:
6594                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6595                 Cvar_SetValueQuick(&gl_combine, 1);
6596                 Cvar_SetValueQuick(&r_glsl, 1);
6597                 r_loadnormalmap = true;
6598                 r_loadgloss = true;
6599                 r_loadfog = false;
6600                 break;
6601         case RENDERPATH_GL13:
6602                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6603                 Cvar_SetValueQuick(&gl_combine, 1);
6604                 Cvar_SetValueQuick(&r_glsl, 0);
6605                 r_loadnormalmap = false;
6606                 r_loadgloss = false;
6607                 r_loadfog = true;
6608                 break;
6609         case RENDERPATH_GL11:
6610                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6611                 Cvar_SetValueQuick(&gl_combine, 0);
6612                 Cvar_SetValueQuick(&r_glsl, 0);
6613                 r_loadnormalmap = false;
6614                 r_loadgloss = false;
6615                 r_loadfog = true;
6616                 break;
6617         case RENDERPATH_GLES2:
6618                 Cvar_SetValueQuick(&r_textureunits, 1);
6619                 Cvar_SetValueQuick(&gl_combine, 1);
6620                 Cvar_SetValueQuick(&r_glsl, 1);
6621                 r_loadnormalmap = true;
6622                 r_loadgloss = false;
6623                 r_loadfog = false;
6624                 break;
6625         }
6626
6627         R_AnimCache_Free();
6628         R_FrameData_Reset();
6629
6630         r_numqueries = 0;
6631         r_maxqueries = 0;
6632         memset(r_queries, 0, sizeof(r_queries));
6633
6634         r_qwskincache = NULL;
6635         r_qwskincache_size = 0;
6636
6637         // set up r_skinframe loading system for textures
6638         memset(&r_skinframe, 0, sizeof(r_skinframe));
6639         r_skinframe.loadsequence = 1;
6640         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6641
6642         r_main_texturepool = R_AllocTexturePool();
6643         R_BuildBlankTextures();
6644         R_BuildNoTexture();
6645         if (vid.support.arb_texture_cube_map)
6646         {
6647                 R_BuildWhiteCube();
6648                 R_BuildNormalizationCube();
6649         }
6650         r_texture_fogattenuation = NULL;
6651         r_texture_fogheighttexture = NULL;
6652         r_texture_gammaramps = NULL;
6653         //r_texture_fogintensity = NULL;
6654         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6655         memset(&r_waterstate, 0, sizeof(r_waterstate));
6656         r_glsl_permutation = NULL;
6657         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6658         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6659         glslshaderstring = NULL;
6660 #ifdef SUPPORTD3D
6661         r_hlsl_permutation = NULL;
6662         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6663         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6664 #endif
6665         hlslshaderstring = NULL;
6666         memset(&r_svbsp, 0, sizeof (r_svbsp));
6667
6668         r_refdef.fogmasktable_density = 0;
6669 }
6670
6671 void gl_main_shutdown(void)
6672 {
6673         R_AnimCache_Free();
6674         R_FrameData_Reset();
6675
6676         R_Main_FreeViewCache();
6677
6678         switch(vid.renderpath)
6679         {
6680         case RENDERPATH_GL11:
6681         case RENDERPATH_GL13:
6682         case RENDERPATH_GL20:
6683         case RENDERPATH_GLES2:
6684                 if (r_maxqueries)
6685                         qglDeleteQueriesARB(r_maxqueries, r_queries);
6686                 break;
6687         case RENDERPATH_D3D9:
6688                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6689                 break;
6690         case RENDERPATH_D3D10:
6691                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6692                 break;
6693         case RENDERPATH_D3D11:
6694                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6695                 break;
6696         case RENDERPATH_SOFT:
6697                 break;
6698         }
6699
6700         r_numqueries = 0;
6701         r_maxqueries = 0;
6702         memset(r_queries, 0, sizeof(r_queries));
6703
6704         r_qwskincache = NULL;
6705         r_qwskincache_size = 0;
6706
6707         // clear out the r_skinframe state
6708         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6709         memset(&r_skinframe, 0, sizeof(r_skinframe));
6710
6711         if (r_svbsp.nodes)
6712                 Mem_Free(r_svbsp.nodes);
6713         memset(&r_svbsp, 0, sizeof (r_svbsp));
6714         R_FreeTexturePool(&r_main_texturepool);
6715         loadingscreentexture = NULL;
6716         r_texture_blanknormalmap = NULL;
6717         r_texture_white = NULL;
6718         r_texture_grey128 = NULL;
6719         r_texture_black = NULL;
6720         r_texture_whitecube = NULL;
6721         r_texture_normalizationcube = NULL;
6722         r_texture_fogattenuation = NULL;
6723         r_texture_fogheighttexture = NULL;
6724         r_texture_gammaramps = NULL;
6725         r_texture_numcubemaps = 0;
6726         //r_texture_fogintensity = NULL;
6727         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6728         memset(&r_waterstate, 0, sizeof(r_waterstate));
6729         R_GLSL_Restart_f();
6730
6731         r_glsl_permutation = NULL;
6732         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6733         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6734         glslshaderstring = NULL;
6735 #ifdef SUPPORTD3D
6736         r_hlsl_permutation = NULL;
6737         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6738         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6739 #endif
6740         hlslshaderstring = NULL;
6741 }
6742
6743 extern void CL_ParseEntityLump(char *entitystring);
6744 void gl_main_newmap(void)
6745 {
6746         // FIXME: move this code to client
6747         char *entities, entname[MAX_QPATH];
6748         if (r_qwskincache)
6749                 Mem_Free(r_qwskincache);
6750         r_qwskincache = NULL;
6751         r_qwskincache_size = 0;
6752         if (cl.worldmodel)
6753         {
6754                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6755                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6756                 {
6757                         CL_ParseEntityLump(entities);
6758                         Mem_Free(entities);
6759                         return;
6760                 }
6761                 if (cl.worldmodel->brush.entities)
6762                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6763         }
6764         R_Main_FreeViewCache();
6765
6766         R_FrameData_Reset();
6767 }
6768
6769 void GL_Main_Init(void)
6770 {
6771         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6772
6773         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6774         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6775         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6776         if (gamemode == GAME_NEHAHRA)
6777         {
6778                 Cvar_RegisterVariable (&gl_fogenable);
6779                 Cvar_RegisterVariable (&gl_fogdensity);
6780                 Cvar_RegisterVariable (&gl_fogred);
6781                 Cvar_RegisterVariable (&gl_foggreen);
6782                 Cvar_RegisterVariable (&gl_fogblue);
6783                 Cvar_RegisterVariable (&gl_fogstart);
6784                 Cvar_RegisterVariable (&gl_fogend);
6785                 Cvar_RegisterVariable (&gl_skyclip);
6786         }
6787         Cvar_RegisterVariable(&r_motionblur);
6788         Cvar_RegisterVariable(&r_motionblur_maxblur);
6789         Cvar_RegisterVariable(&r_motionblur_bmin);
6790         Cvar_RegisterVariable(&r_motionblur_vmin);
6791         Cvar_RegisterVariable(&r_motionblur_vmax);
6792         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6793         Cvar_RegisterVariable(&r_motionblur_randomize);
6794         Cvar_RegisterVariable(&r_damageblur);
6795         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6796         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6797         Cvar_RegisterVariable(&r_equalize_entities_by);
6798         Cvar_RegisterVariable(&r_equalize_entities_to);
6799         Cvar_RegisterVariable(&r_depthfirst);
6800         Cvar_RegisterVariable(&r_useinfinitefarclip);
6801         Cvar_RegisterVariable(&r_farclip_base);
6802         Cvar_RegisterVariable(&r_farclip_world);
6803         Cvar_RegisterVariable(&r_nearclip);
6804         Cvar_RegisterVariable(&r_showbboxes);
6805         Cvar_RegisterVariable(&r_showsurfaces);
6806         Cvar_RegisterVariable(&r_showtris);
6807         Cvar_RegisterVariable(&r_shownormals);
6808         Cvar_RegisterVariable(&r_showlighting);
6809         Cvar_RegisterVariable(&r_showshadowvolumes);
6810         Cvar_RegisterVariable(&r_showcollisionbrushes);
6811         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6812         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6813         Cvar_RegisterVariable(&r_showdisabledepthtest);
6814         Cvar_RegisterVariable(&r_drawportals);
6815         Cvar_RegisterVariable(&r_drawentities);
6816         Cvar_RegisterVariable(&r_draw2d);
6817         Cvar_RegisterVariable(&r_drawworld);
6818         Cvar_RegisterVariable(&r_cullentities_trace);
6819         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6820         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6821         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6822         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6823         Cvar_RegisterVariable(&r_drawviewmodel);
6824         Cvar_RegisterVariable(&r_drawexteriormodel);
6825         Cvar_RegisterVariable(&r_speeds);
6826         Cvar_RegisterVariable(&r_fullbrights);
6827         Cvar_RegisterVariable(&r_wateralpha);
6828         Cvar_RegisterVariable(&r_dynamic);
6829         Cvar_RegisterVariable(&r_fakelight);
6830         Cvar_RegisterVariable(&r_fakelight_intensity);
6831         Cvar_RegisterVariable(&r_fullbright);
6832         Cvar_RegisterVariable(&r_shadows);
6833         Cvar_RegisterVariable(&r_shadows_darken);
6834         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6835         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6836         Cvar_RegisterVariable(&r_shadows_throwdistance);
6837         Cvar_RegisterVariable(&r_shadows_throwdirection);
6838         Cvar_RegisterVariable(&r_shadows_focus);
6839         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6840         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6841         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6842         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6843         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6844         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6845         Cvar_RegisterVariable(&r_fog_exp2);
6846         Cvar_RegisterVariable(&r_drawfog);
6847         Cvar_RegisterVariable(&r_transparentdepthmasking);
6848         Cvar_RegisterVariable(&r_texture_dds_load);
6849         Cvar_RegisterVariable(&r_texture_dds_save);
6850         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6851         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6852         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6853         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6854         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6855         Cvar_RegisterVariable(&r_textureunits);
6856         Cvar_RegisterVariable(&gl_combine);
6857         Cvar_RegisterVariable(&r_glsl);
6858         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6859         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6860         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6861         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6862         Cvar_RegisterVariable(&r_glsl_postprocess);
6863         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6864         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6865         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6866         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6867         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6868         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6869         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6870         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6871
6872         Cvar_RegisterVariable(&r_water);
6873         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6874         Cvar_RegisterVariable(&r_water_clippingplanebias);
6875         Cvar_RegisterVariable(&r_water_refractdistort);
6876         Cvar_RegisterVariable(&r_water_reflectdistort);
6877         Cvar_RegisterVariable(&r_water_scissormode);
6878         Cvar_RegisterVariable(&r_lerpsprites);
6879         Cvar_RegisterVariable(&r_lerpmodels);
6880         Cvar_RegisterVariable(&r_lerplightstyles);
6881         Cvar_RegisterVariable(&r_waterscroll);
6882         Cvar_RegisterVariable(&r_bloom);
6883         Cvar_RegisterVariable(&r_bloom_colorscale);
6884         Cvar_RegisterVariable(&r_bloom_brighten);
6885         Cvar_RegisterVariable(&r_bloom_blur);
6886         Cvar_RegisterVariable(&r_bloom_resolution);
6887         Cvar_RegisterVariable(&r_bloom_colorexponent);
6888         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6889         Cvar_RegisterVariable(&r_hdr);
6890         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6891         Cvar_RegisterVariable(&r_hdr_glowintensity);
6892         Cvar_RegisterVariable(&r_hdr_range);
6893         Cvar_RegisterVariable(&r_hdr_irisadaptation);
6894         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6895         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6896         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6897         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6898         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6899         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6900         Cvar_RegisterVariable(&developer_texturelogging);
6901         Cvar_RegisterVariable(&gl_lightmaps);
6902         Cvar_RegisterVariable(&r_test);
6903         Cvar_RegisterVariable(&r_glsl_saturation);
6904         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6905         Cvar_RegisterVariable(&r_framedatasize);
6906         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6907                 Cvar_SetValue("r_fullbrights", 0);
6908         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6909
6910         Cvar_RegisterVariable(&r_track_sprites);
6911         Cvar_RegisterVariable(&r_track_sprites_flags);
6912         Cvar_RegisterVariable(&r_track_sprites_scalew);
6913         Cvar_RegisterVariable(&r_track_sprites_scaleh);
6914         Cvar_RegisterVariable(&r_overheadsprites_perspective);
6915         Cvar_RegisterVariable(&r_overheadsprites_pushback);
6916         Cvar_RegisterVariable(&r_overheadsprites_scalex);
6917         Cvar_RegisterVariable(&r_overheadsprites_scaley);
6918 }
6919
6920 extern void R_Textures_Init(void);
6921 extern void GL_Draw_Init(void);
6922 extern void GL_Main_Init(void);
6923 extern void R_Shadow_Init(void);
6924 extern void R_Sky_Init(void);
6925 extern void GL_Surf_Init(void);
6926 extern void R_Particles_Init(void);
6927 extern void R_Explosion_Init(void);
6928 extern void gl_backend_init(void);
6929 extern void Sbar_Init(void);
6930 extern void R_LightningBeams_Init(void);
6931 extern void Mod_RenderInit(void);
6932 extern void Font_Init(void);
6933
6934 void Render_Init(void)
6935 {
6936         gl_backend_init();
6937         R_Textures_Init();
6938         GL_Main_Init();
6939         Font_Init();
6940         GL_Draw_Init();
6941         R_Shadow_Init();
6942         R_Sky_Init();
6943         GL_Surf_Init();
6944         Sbar_Init();
6945         R_Particles_Init();
6946         R_Explosion_Init();
6947         R_LightningBeams_Init();
6948         Mod_RenderInit();
6949 }
6950
6951 /*
6952 ===============
6953 GL_Init
6954 ===============
6955 */
6956 extern char *ENGINE_EXTENSIONS;
6957 void GL_Init (void)
6958 {
6959         gl_renderer = (const char *)qglGetString(GL_RENDERER);
6960         gl_vendor = (const char *)qglGetString(GL_VENDOR);
6961         gl_version = (const char *)qglGetString(GL_VERSION);
6962         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
6963
6964         if (!gl_extensions)
6965                 gl_extensions = "";
6966         if (!gl_platformextensions)
6967                 gl_platformextensions = "";
6968
6969         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
6970         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
6971         Con_Printf("GL_VERSION: %s\n", gl_version);
6972         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
6973         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
6974
6975         VID_CheckExtensions();
6976
6977         // LordHavoc: report supported extensions
6978         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
6979
6980         // clear to black (loading plaque will be seen over this)
6981         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6982 }
6983
6984 int R_CullBox(const vec3_t mins, const vec3_t maxs)
6985 {
6986         int i;
6987         mplane_t *p;
6988         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
6989         {
6990                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
6991                 if (i == 4)
6992                         continue;
6993                 p = r_refdef.view.frustum + i;
6994                 switch(p->signbits)
6995                 {
6996                 default:
6997                 case 0:
6998                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
6999                                 return true;
7000                         break;
7001                 case 1:
7002                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7003                                 return true;
7004                         break;
7005                 case 2:
7006                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7007                                 return true;
7008                         break;
7009                 case 3:
7010                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7011                                 return true;
7012                         break;
7013                 case 4:
7014                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7015                                 return true;
7016                         break;
7017                 case 5:
7018                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7019                                 return true;
7020                         break;
7021                 case 6:
7022                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7023                                 return true;
7024                         break;
7025                 case 7:
7026                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7027                                 return true;
7028                         break;
7029                 }
7030         }
7031         return false;
7032 }
7033
7034 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7035 {
7036         int i;
7037         const mplane_t *p;
7038         for (i = 0;i < numplanes;i++)
7039         {
7040                 p = planes + i;
7041                 switch(p->signbits)
7042                 {
7043                 default:
7044                 case 0:
7045                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7046                                 return true;
7047                         break;
7048                 case 1:
7049                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7050                                 return true;
7051                         break;
7052                 case 2:
7053                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7054                                 return true;
7055                         break;
7056                 case 3:
7057                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7058                                 return true;
7059                         break;
7060                 case 4:
7061                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7062                                 return true;
7063                         break;
7064                 case 5:
7065                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7066                                 return true;
7067                         break;
7068                 case 6:
7069                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7070                                 return true;
7071                         break;
7072                 case 7:
7073                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7074                                 return true;
7075                         break;
7076                 }
7077         }
7078         return false;
7079 }
7080
7081 //==================================================================================
7082
7083 // LordHavoc: this stores temporary data used within the same frame
7084
7085 typedef struct r_framedata_mem_s
7086 {
7087         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7088         size_t size; // how much usable space
7089         size_t current; // how much space in use
7090         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7091         size_t wantedsize; // how much space was allocated
7092         unsigned char *data; // start of real data (16byte aligned)
7093 }
7094 r_framedata_mem_t;
7095
7096 static r_framedata_mem_t *r_framedata_mem;
7097
7098 void R_FrameData_Reset(void)
7099 {
7100         while (r_framedata_mem)
7101         {
7102                 r_framedata_mem_t *next = r_framedata_mem->purge;
7103                 Mem_Free(r_framedata_mem);
7104                 r_framedata_mem = next;
7105         }
7106 }
7107
7108 void R_FrameData_Resize(void)
7109 {
7110         size_t wantedsize;
7111         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7112         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7113         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7114         {
7115                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7116                 newmem->wantedsize = wantedsize;
7117                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7118                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7119                 newmem->current = 0;
7120                 newmem->mark = 0;
7121                 newmem->purge = r_framedata_mem;
7122                 r_framedata_mem = newmem;
7123         }
7124 }
7125
7126 void R_FrameData_NewFrame(void)
7127 {
7128         R_FrameData_Resize();
7129         if (!r_framedata_mem)
7130                 return;
7131         // if we ran out of space on the last frame, free the old memory now
7132         while (r_framedata_mem->purge)
7133         {
7134                 // repeatedly remove the second item in the list, leaving only head
7135                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7136                 Mem_Free(r_framedata_mem->purge);
7137                 r_framedata_mem->purge = next;
7138         }
7139         // reset the current mem pointer
7140         r_framedata_mem->current = 0;
7141         r_framedata_mem->mark = 0;
7142 }
7143
7144 void *R_FrameData_Alloc(size_t size)
7145 {
7146         void *data;
7147
7148         // align to 16 byte boundary - the data pointer is already aligned, so we
7149         // only need to ensure the size of every allocation is also aligned
7150         size = (size + 15) & ~15;
7151
7152         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7153         {
7154                 // emergency - we ran out of space, allocate more memory
7155                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7156                 R_FrameData_Resize();
7157         }
7158
7159         data = r_framedata_mem->data + r_framedata_mem->current;
7160         r_framedata_mem->current += size;
7161
7162         // count the usage for stats
7163         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7164         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7165
7166         return (void *)data;
7167 }
7168
7169 void *R_FrameData_Store(size_t size, void *data)
7170 {
7171         void *d = R_FrameData_Alloc(size);
7172         if (d && data)
7173                 memcpy(d, data, size);
7174         return d;
7175 }
7176
7177 void R_FrameData_SetMark(void)
7178 {
7179         if (!r_framedata_mem)
7180                 return;
7181         r_framedata_mem->mark = r_framedata_mem->current;
7182 }
7183
7184 void R_FrameData_ReturnToMark(void)
7185 {
7186         if (!r_framedata_mem)
7187                 return;
7188         r_framedata_mem->current = r_framedata_mem->mark;
7189 }
7190
7191 //==================================================================================
7192
7193 // LordHavoc: animcache originally written by Echon, rewritten since then
7194
7195 /**
7196  * Animation cache prevents re-generating mesh data for an animated model
7197  * multiple times in one frame for lighting, shadowing, reflections, etc.
7198  */
7199
7200 void R_AnimCache_Free(void)
7201 {
7202 }
7203
7204 void R_AnimCache_ClearCache(void)
7205 {
7206         int i;
7207         entity_render_t *ent;
7208
7209         for (i = 0;i < r_refdef.scene.numentities;i++)
7210         {
7211                 ent = r_refdef.scene.entities[i];
7212                 ent->animcache_vertex3f = NULL;
7213                 ent->animcache_normal3f = NULL;
7214                 ent->animcache_svector3f = NULL;
7215                 ent->animcache_tvector3f = NULL;
7216                 ent->animcache_vertexmesh = NULL;
7217                 ent->animcache_vertex3fbuffer = NULL;
7218                 ent->animcache_vertexmeshbuffer = NULL;
7219         }
7220 }
7221
7222 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7223 {
7224         int i;
7225
7226         // check if we need the meshbuffers
7227         if (!vid.useinterleavedarrays)
7228                 return;
7229
7230         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7231                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7232         // TODO: upload vertex3f buffer?
7233         if (ent->animcache_vertexmesh)
7234         {
7235                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7236                 for (i = 0;i < numvertices;i++)
7237                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7238                 if (ent->animcache_svector3f)
7239                         for (i = 0;i < numvertices;i++)
7240                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7241                 if (ent->animcache_tvector3f)
7242                         for (i = 0;i < numvertices;i++)
7243                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7244                 if (ent->animcache_normal3f)
7245                         for (i = 0;i < numvertices;i++)
7246                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7247                 // TODO: upload vertexmeshbuffer?
7248         }
7249 }
7250
7251 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7252 {
7253         dp_model_t *model = ent->model;
7254         int numvertices;
7255         // see if it's already cached this frame
7256         if (ent->animcache_vertex3f)
7257         {
7258                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7259                 if (wantnormals || wanttangents)
7260                 {
7261                         if (ent->animcache_normal3f)
7262                                 wantnormals = false;
7263                         if (ent->animcache_svector3f)
7264                                 wanttangents = false;
7265                         if (wantnormals || wanttangents)
7266                         {
7267                                 numvertices = model->surfmesh.num_vertices;
7268                                 if (wantnormals)
7269                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7270                                 if (wanttangents)
7271                                 {
7272                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7273                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7274                                 }
7275                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7276                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7277                         }
7278                 }
7279         }
7280         else
7281         {
7282                 // see if this ent is worth caching
7283                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7284                         return false;
7285                 // get some memory for this entity and generate mesh data
7286                 numvertices = model->surfmesh.num_vertices;
7287                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7288                 if (wantnormals)
7289                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7290                 if (wanttangents)
7291                 {
7292                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7293                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7294                 }
7295                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7296                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7297         }
7298         return true;
7299 }
7300
7301 void R_AnimCache_CacheVisibleEntities(void)
7302 {
7303         int i;
7304         qboolean wantnormals = true;
7305         qboolean wanttangents = !r_showsurfaces.integer;
7306
7307         switch(vid.renderpath)
7308         {
7309         case RENDERPATH_GL20:
7310         case RENDERPATH_D3D9:
7311         case RENDERPATH_D3D10:
7312         case RENDERPATH_D3D11:
7313         case RENDERPATH_GLES2:
7314                 break;
7315         case RENDERPATH_GL13:
7316         case RENDERPATH_GL11:
7317                 wanttangents = false;
7318                 break;
7319         case RENDERPATH_SOFT:
7320                 break;
7321         }
7322
7323         if (r_shownormals.integer)
7324                 wanttangents = wantnormals = true;
7325
7326         // TODO: thread this
7327         // NOTE: R_PrepareRTLights() also caches entities
7328
7329         for (i = 0;i < r_refdef.scene.numentities;i++)
7330                 if (r_refdef.viewcache.entityvisible[i])
7331                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7332 }
7333
7334 //==================================================================================
7335
7336 static void R_View_UpdateEntityLighting (void)
7337 {
7338         int i;
7339         entity_render_t *ent;
7340         vec3_t tempdiffusenormal, avg;
7341         vec_t f, fa, fd, fdd;
7342         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7343
7344         for (i = 0;i < r_refdef.scene.numentities;i++)
7345         {
7346                 ent = r_refdef.scene.entities[i];
7347
7348                 // skip unseen models
7349                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7350                         continue;
7351
7352                 // skip bsp models
7353                 if (ent->model && ent->model->brush.num_leafs)
7354                 {
7355                         // TODO: use modellight for r_ambient settings on world?
7356                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7357                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7358                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7359                         continue;
7360                 }
7361
7362                 // fetch the lighting from the worldmodel data
7363                 VectorClear(ent->modellight_ambient);
7364                 VectorClear(ent->modellight_diffuse);
7365                 VectorClear(tempdiffusenormal);
7366                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7367                 {
7368                         vec3_t org;
7369                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7370
7371                         // complete lightning for lit sprites
7372                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7373                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7374                         {
7375                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7376                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7377                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7378                         }
7379                         else
7380                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7381
7382                         if(ent->flags & RENDER_EQUALIZE)
7383                         {
7384                                 // first fix up ambient lighting...
7385                                 if(r_equalize_entities_minambient.value > 0)
7386                                 {
7387                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7388                                         if(fd > 0)
7389                                         {
7390                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7391                                                 if(fa < r_equalize_entities_minambient.value * fd)
7392                                                 {
7393                                                         // solve:
7394                                                         //   fa'/fd' = minambient
7395                                                         //   fa'+0.25*fd' = fa+0.25*fd
7396                                                         //   ...
7397                                                         //   fa' = fd' * minambient
7398                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7399                                                         //   ...
7400                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7401                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7402                                                         //   ...
7403                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7404                                                         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
7405                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7406                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7407                                                 }
7408                                         }
7409                                 }
7410
7411                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7412                                 {
7413                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7414                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7415                                         f = fa + 0.25 * fd;
7416                                         if(f > 0)
7417                                         {
7418                                                 // adjust brightness and saturation to target
7419                                                 avg[0] = avg[1] = avg[2] = fa / f;
7420                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7421                                                 avg[0] = avg[1] = avg[2] = fd / f;
7422                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7423                                         }
7424                                 }
7425                         }
7426                 }
7427                 else // highly rare
7428                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7429
7430                 // move the light direction into modelspace coordinates for lighting code
7431                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7432                 if(VectorLength2(ent->modellight_lightdir) == 0)
7433                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7434                 VectorNormalize(ent->modellight_lightdir);
7435         }
7436 }
7437
7438 #define MAX_LINEOFSIGHTTRACES 64
7439
7440 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7441 {
7442         int i;
7443         vec3_t boxmins, boxmaxs;
7444         vec3_t start;
7445         vec3_t end;
7446         dp_model_t *model = r_refdef.scene.worldmodel;
7447
7448         if (!model || !model->brush.TraceLineOfSight)
7449                 return true;
7450
7451         // expand the box a little
7452         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7453         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7454         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7455         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7456         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7457         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7458
7459         // return true if eye is inside enlarged box
7460         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7461                 return true;
7462
7463         // try center
7464         VectorCopy(eye, start);
7465         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7466         if (model->brush.TraceLineOfSight(model, start, end))
7467                 return true;
7468
7469         // try various random positions
7470         for (i = 0;i < numsamples;i++)
7471         {
7472                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7473                 if (model->brush.TraceLineOfSight(model, start, end))
7474                         return true;
7475         }
7476
7477         return false;
7478 }
7479
7480
7481 static void R_View_UpdateEntityVisible (void)
7482 {
7483         int i;
7484         int renderimask;
7485         int samples;
7486         entity_render_t *ent;
7487
7488         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7489                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7490                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7491                 :                                                          RENDER_EXTERIORMODEL;
7492         if (!r_drawviewmodel.integer)
7493                 renderimask |= RENDER_VIEWMODEL;
7494         if (!r_drawexteriormodel.integer)
7495                 renderimask |= RENDER_EXTERIORMODEL;
7496         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7497         {
7498                 // worldmodel can check visibility
7499                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7500                 for (i = 0;i < r_refdef.scene.numentities;i++)
7501                 {
7502                         ent = r_refdef.scene.entities[i];
7503                         if (!(ent->flags & renderimask))
7504                         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)))
7505                         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))
7506                                 r_refdef.viewcache.entityvisible[i] = true;
7507                 }
7508                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7509                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7510                 {
7511                         for (i = 0;i < r_refdef.scene.numentities;i++)
7512                         {
7513                                 ent = r_refdef.scene.entities[i];
7514                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7515                                 {
7516                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7517                                         if (samples < 0)
7518                                                 continue; // temp entities do pvs only
7519                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7520                                                 ent->last_trace_visibility = realtime;
7521                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7522                                                 r_refdef.viewcache.entityvisible[i] = 0;
7523                                 }
7524                         }
7525                 }
7526         }
7527         else
7528         {
7529                 // no worldmodel or it can't check visibility
7530                 for (i = 0;i < r_refdef.scene.numentities;i++)
7531                 {
7532                         ent = r_refdef.scene.entities[i];
7533                         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));
7534                 }
7535         }
7536 }
7537
7538 /// only used if skyrendermasked, and normally returns false
7539 int R_DrawBrushModelsSky (void)
7540 {
7541         int i, sky;
7542         entity_render_t *ent;
7543
7544         sky = false;
7545         for (i = 0;i < r_refdef.scene.numentities;i++)
7546         {
7547                 if (!r_refdef.viewcache.entityvisible[i])
7548                         continue;
7549                 ent = r_refdef.scene.entities[i];
7550                 if (!ent->model || !ent->model->DrawSky)
7551                         continue;
7552                 ent->model->DrawSky(ent);
7553                 sky = true;
7554         }
7555         return sky;
7556 }
7557
7558 static void R_DrawNoModel(entity_render_t *ent);
7559 static void R_DrawModels(void)
7560 {
7561         int i;
7562         entity_render_t *ent;
7563
7564         for (i = 0;i < r_refdef.scene.numentities;i++)
7565         {
7566                 if (!r_refdef.viewcache.entityvisible[i])
7567                         continue;
7568                 ent = r_refdef.scene.entities[i];
7569                 r_refdef.stats.entities++;
7570                 if (ent->model && ent->model->Draw != NULL)
7571                         ent->model->Draw(ent);
7572                 else
7573                         R_DrawNoModel(ent);
7574         }
7575 }
7576
7577 static void R_DrawModelsDepth(void)
7578 {
7579         int i;
7580         entity_render_t *ent;
7581
7582         for (i = 0;i < r_refdef.scene.numentities;i++)
7583         {
7584                 if (!r_refdef.viewcache.entityvisible[i])
7585                         continue;
7586                 ent = r_refdef.scene.entities[i];
7587                 if (ent->model && ent->model->DrawDepth != NULL)
7588                         ent->model->DrawDepth(ent);
7589         }
7590 }
7591
7592 static void R_DrawModelsDebug(void)
7593 {
7594         int i;
7595         entity_render_t *ent;
7596
7597         for (i = 0;i < r_refdef.scene.numentities;i++)
7598         {
7599                 if (!r_refdef.viewcache.entityvisible[i])
7600                         continue;
7601                 ent = r_refdef.scene.entities[i];
7602                 if (ent->model && ent->model->DrawDebug != NULL)
7603                         ent->model->DrawDebug(ent);
7604         }
7605 }
7606
7607 static void R_DrawModelsAddWaterPlanes(void)
7608 {
7609         int i;
7610         entity_render_t *ent;
7611
7612         for (i = 0;i < r_refdef.scene.numentities;i++)
7613         {
7614                 if (!r_refdef.viewcache.entityvisible[i])
7615                         continue;
7616                 ent = r_refdef.scene.entities[i];
7617                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7618                         ent->model->DrawAddWaterPlanes(ent);
7619         }
7620 }
7621
7622 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7623 {
7624         if (r_hdr_irisadaptation.integer)
7625         {
7626                 vec3_t ambient;
7627                 vec3_t diffuse;
7628                 vec3_t diffusenormal;
7629                 vec_t brightness;
7630                 vec_t goal;
7631                 vec_t adjust;
7632                 vec_t current;
7633                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7634                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7635                 brightness = max(0.0000001f, brightness);
7636                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7637                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7638                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7639                 current = r_hdr_irisadaptation_value.value;
7640                 if (current < goal)
7641                         current = min(current + adjust, goal);
7642                 else if (current > goal)
7643                         current = max(current - adjust, goal);
7644                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7645                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7646         }
7647         else if (r_hdr_irisadaptation_value.value != 1.0f)
7648                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7649 }
7650
7651 static void R_View_SetFrustum(const int *scissor)
7652 {
7653         int i;
7654         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7655         vec3_t forward, left, up, origin, v;
7656
7657         if(scissor)
7658         {
7659                 // flipped x coordinates (because x points left here)
7660                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7661                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7662
7663                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7664                 switch(vid.renderpath)
7665                 {
7666                         case RENDERPATH_D3D9:
7667                         case RENDERPATH_D3D10:
7668                         case RENDERPATH_D3D11:
7669                         case RENDERPATH_SOFT:
7670                                 // non-flipped y coordinates
7671                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7672                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7673                                 break;
7674                         case RENDERPATH_GL11:
7675                         case RENDERPATH_GL13:
7676                         case RENDERPATH_GL20:
7677                         case RENDERPATH_GLES2:
7678                                 // non-flipped y coordinates
7679                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7680                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7681                                 break;
7682                 }
7683         }
7684
7685         // we can't trust r_refdef.view.forward and friends in reflected scenes
7686         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7687
7688 #if 0
7689         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7690         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7691         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7692         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7693         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7694         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7695         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7696         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7697         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7698         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7699         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7700         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7701 #endif
7702
7703 #if 0
7704         zNear = r_refdef.nearclip;
7705         nudge = 1.0 - 1.0 / (1<<23);
7706         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7707         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7708         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7709         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7710         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7711         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7712         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7713         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7714 #endif
7715
7716
7717
7718 #if 0
7719         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7720         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7721         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7722         r_refdef.view.frustum[0].dist = m[15] - m[12];
7723
7724         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7725         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7726         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7727         r_refdef.view.frustum[1].dist = m[15] + m[12];
7728
7729         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7730         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7731         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7732         r_refdef.view.frustum[2].dist = m[15] - m[13];
7733
7734         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7735         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7736         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7737         r_refdef.view.frustum[3].dist = m[15] + m[13];
7738
7739         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7740         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7741         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7742         r_refdef.view.frustum[4].dist = m[15] - m[14];
7743
7744         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7745         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7746         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7747         r_refdef.view.frustum[5].dist = m[15] + m[14];
7748 #endif
7749
7750         if (r_refdef.view.useperspective)
7751         {
7752                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7753                 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]);
7754                 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]);
7755                 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]);
7756                 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]);
7757
7758                 // then the normals from the corners relative to origin
7759                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7760                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7761                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7762                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7763
7764                 // in a NORMAL view, forward cross left == up
7765                 // in a REFLECTED view, forward cross left == down
7766                 // so our cross products above need to be adjusted for a left handed coordinate system
7767                 CrossProduct(forward, left, v);
7768                 if(DotProduct(v, up) < 0)
7769                 {
7770                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7771                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7772                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7773                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7774                 }
7775
7776                 // Leaving those out was a mistake, those were in the old code, and they
7777                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7778                 // I couldn't reproduce it after adding those normalizations. --blub
7779                 VectorNormalize(r_refdef.view.frustum[0].normal);
7780                 VectorNormalize(r_refdef.view.frustum[1].normal);
7781                 VectorNormalize(r_refdef.view.frustum[2].normal);
7782                 VectorNormalize(r_refdef.view.frustum[3].normal);
7783
7784                 // make the corners absolute
7785                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7786                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7787                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7788                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7789
7790                 // one more normal
7791                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7792
7793                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7794                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7795                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7796                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7797                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7798         }
7799         else
7800         {
7801                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7802                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7803                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7804                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7805                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7806                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7807                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7808                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7809                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7810                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7811         }
7812         r_refdef.view.numfrustumplanes = 5;
7813
7814         if (r_refdef.view.useclipplane)
7815         {
7816                 r_refdef.view.numfrustumplanes = 6;
7817                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7818         }
7819
7820         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7821                 PlaneClassify(r_refdef.view.frustum + i);
7822
7823         // LordHavoc: note to all quake engine coders, Quake had a special case
7824         // for 90 degrees which assumed a square view (wrong), so I removed it,
7825         // Quake2 has it disabled as well.
7826
7827         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7828         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7829         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7830         //PlaneClassify(&frustum[0]);
7831
7832         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7833         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7834         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7835         //PlaneClassify(&frustum[1]);
7836
7837         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7838         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7839         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7840         //PlaneClassify(&frustum[2]);
7841
7842         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7843         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7844         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7845         //PlaneClassify(&frustum[3]);
7846
7847         // nearclip plane
7848         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7849         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7850         //PlaneClassify(&frustum[4]);
7851 }
7852
7853 void R_View_UpdateWithScissor(const int *myscissor)
7854 {
7855         R_Main_ResizeViewCache();
7856         R_View_SetFrustum(myscissor);
7857         R_View_WorldVisibility(r_refdef.view.useclipplane);
7858         R_View_UpdateEntityVisible();
7859         R_View_UpdateEntityLighting();
7860 }
7861
7862 void R_View_Update(void)
7863 {
7864         R_Main_ResizeViewCache();
7865         R_View_SetFrustum(NULL);
7866         R_View_WorldVisibility(r_refdef.view.useclipplane);
7867         R_View_UpdateEntityVisible();
7868         R_View_UpdateEntityLighting();
7869 }
7870
7871 void R_SetupView(qboolean allowwaterclippingplane)
7872 {
7873         const float *customclipplane = NULL;
7874         float plane[4];
7875         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7876         {
7877                 // LordHavoc: couldn't figure out how to make this approach the
7878                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7879                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7880                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7881                         dist = r_refdef.view.clipplane.dist;
7882                 plane[0] = r_refdef.view.clipplane.normal[0];
7883                 plane[1] = r_refdef.view.clipplane.normal[1];
7884                 plane[2] = r_refdef.view.clipplane.normal[2];
7885                 plane[3] = dist;
7886                 customclipplane = plane;
7887         }
7888
7889         if (!r_refdef.view.useperspective)
7890                 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);
7891         else if (vid.stencil && r_useinfinitefarclip.integer)
7892                 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);
7893         else
7894                 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);
7895         R_SetViewport(&r_refdef.view.viewport);
7896 }
7897
7898 void R_EntityMatrix(const matrix4x4_t *matrix)
7899 {
7900         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7901         {
7902                 gl_modelmatrixchanged = false;
7903                 gl_modelmatrix = *matrix;
7904                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7905                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7906                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7907                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7908                 CHECKGLERROR
7909                 switch(vid.renderpath)
7910                 {
7911                 case RENDERPATH_D3D9:
7912 #ifdef SUPPORTD3D
7913                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
7914                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
7915 #endif
7916                         break;
7917                 case RENDERPATH_D3D10:
7918                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
7919                         break;
7920                 case RENDERPATH_D3D11:
7921                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
7922                         break;
7923                 case RENDERPATH_GL13:
7924                 case RENDERPATH_GL11:
7925                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
7926                         break;
7927                 case RENDERPATH_SOFT:
7928                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
7929                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
7930                         break;
7931                 case RENDERPATH_GL20:
7932                 case RENDERPATH_GLES2:
7933                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
7934                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
7935                         break;
7936                 }
7937         }
7938 }
7939
7940 void R_ResetViewRendering2D(void)
7941 {
7942         r_viewport_t viewport;
7943         DrawQ_Finish();
7944
7945         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
7946         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);
7947         R_SetViewport(&viewport);
7948         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
7949         GL_Color(1, 1, 1, 1);
7950         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7951         GL_BlendFunc(GL_ONE, GL_ZERO);
7952         GL_ScissorTest(false);
7953         GL_DepthMask(false);
7954         GL_DepthRange(0, 1);
7955         GL_DepthTest(false);
7956         GL_DepthFunc(GL_LEQUAL);
7957         R_EntityMatrix(&identitymatrix);
7958         R_Mesh_ResetTextureState();
7959         GL_PolygonOffset(0, 0);
7960         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7961         switch(vid.renderpath)
7962         {
7963         case RENDERPATH_GL11:
7964         case RENDERPATH_GL13:
7965         case RENDERPATH_GL20:
7966         case RENDERPATH_GLES2:
7967                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
7968                 break;
7969         case RENDERPATH_D3D9:
7970         case RENDERPATH_D3D10:
7971         case RENDERPATH_D3D11:
7972         case RENDERPATH_SOFT:
7973                 break;
7974         }
7975         GL_CullFace(GL_NONE);
7976 }
7977
7978 void R_ResetViewRendering3D(void)
7979 {
7980         DrawQ_Finish();
7981
7982         R_SetupView(true);
7983         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
7984         GL_Color(1, 1, 1, 1);
7985         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
7986         GL_BlendFunc(GL_ONE, GL_ZERO);
7987         GL_ScissorTest(true);
7988         GL_DepthMask(true);
7989         GL_DepthRange(0, 1);
7990         GL_DepthTest(true);
7991         GL_DepthFunc(GL_LEQUAL);
7992         R_EntityMatrix(&identitymatrix);
7993         R_Mesh_ResetTextureState();
7994         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7995         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
7996         switch(vid.renderpath)
7997         {
7998         case RENDERPATH_GL11:
7999         case RENDERPATH_GL13:
8000         case RENDERPATH_GL20:
8001         case RENDERPATH_GLES2:
8002                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8003                 break;
8004         case RENDERPATH_D3D9:
8005         case RENDERPATH_D3D10:
8006         case RENDERPATH_D3D11:
8007         case RENDERPATH_SOFT:
8008                 break;
8009         }
8010         GL_CullFace(r_refdef.view.cullface_back);
8011 }
8012
8013 /*
8014 ================
8015 R_RenderView_UpdateViewVectors
8016 ================
8017 */
8018 static void R_RenderView_UpdateViewVectors(void)
8019 {
8020         // break apart the view matrix into vectors for various purposes
8021         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8022         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8023         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8024         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8025         // make an inverted copy of the view matrix for tracking sprites
8026         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8027 }
8028
8029 void R_RenderScene(void);
8030 void R_RenderWaterPlanes(void);
8031
8032 static void R_Water_StartFrame(void)
8033 {
8034         int i;
8035         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8036         r_waterstate_waterplane_t *p;
8037
8038         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8039                 return;
8040
8041         switch(vid.renderpath)
8042         {
8043         case RENDERPATH_GL20:
8044         case RENDERPATH_D3D9:
8045         case RENDERPATH_D3D10:
8046         case RENDERPATH_D3D11:
8047         case RENDERPATH_SOFT:
8048         case RENDERPATH_GLES2:
8049                 break;
8050         case RENDERPATH_GL13:
8051         case RENDERPATH_GL11:
8052                 return;
8053         }
8054
8055         // set waterwidth and waterheight to the water resolution that will be
8056         // used (often less than the screen resolution for faster rendering)
8057         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8058         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8059
8060         // calculate desired texture sizes
8061         // can't use water if the card does not support the texture size
8062         if (!r_water.integer || r_showsurfaces.integer)
8063                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8064         else if (vid.support.arb_texture_non_power_of_two)
8065         {
8066                 texturewidth = waterwidth;
8067                 textureheight = waterheight;
8068                 camerawidth = waterwidth;
8069                 cameraheight = waterheight;
8070         }
8071         else
8072         {
8073                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8074                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8075                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8076                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8077         }
8078
8079         // allocate textures as needed
8080         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8081         {
8082                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8083                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8084                 {
8085                         if (p->texture_refraction)
8086                                 R_FreeTexture(p->texture_refraction);
8087                         p->texture_refraction = NULL;
8088                         if (p->texture_reflection)
8089                                 R_FreeTexture(p->texture_reflection);
8090                         p->texture_reflection = NULL;
8091                         if (p->texture_camera)
8092                                 R_FreeTexture(p->texture_camera);
8093                         p->texture_camera = NULL;
8094                 }
8095                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8096                 r_waterstate.texturewidth = texturewidth;
8097                 r_waterstate.textureheight = textureheight;
8098                 r_waterstate.camerawidth = camerawidth;
8099                 r_waterstate.cameraheight = cameraheight;
8100         }
8101
8102         if (r_waterstate.texturewidth)
8103         {
8104                 r_waterstate.enabled = true;
8105
8106                 // when doing a reduced render (HDR) we want to use a smaller area
8107                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8108                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8109
8110                 // set up variables that will be used in shader setup
8111                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8112                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8113                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8114                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8115         }
8116
8117         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8118         r_waterstate.numwaterplanes = 0;
8119 }
8120
8121 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8122 {
8123         int triangleindex, planeindex;
8124         const int *e;
8125         vec3_t vert[3];
8126         vec3_t normal;
8127         vec3_t center;
8128         mplane_t plane;
8129         r_waterstate_waterplane_t *p;
8130         texture_t *t = R_GetCurrentTexture(surface->texture);
8131
8132         // just use the first triangle with a valid normal for any decisions
8133         VectorClear(normal);
8134         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8135         {
8136                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8137                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8138                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8139                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8140                 if (VectorLength2(normal) >= 0.001)
8141                         break;
8142         }
8143
8144         VectorCopy(normal, plane.normal);
8145         VectorNormalize(plane.normal);
8146         plane.dist = DotProduct(vert[0], plane.normal);
8147         PlaneClassify(&plane);
8148         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8149         {
8150                 // skip backfaces (except if nocullface is set)
8151                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8152                         return;
8153                 VectorNegate(plane.normal, plane.normal);
8154                 plane.dist *= -1;
8155                 PlaneClassify(&plane);
8156         }
8157
8158
8159         // find a matching plane if there is one
8160         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8161                 if(p->camera_entity == t->camera_entity)
8162                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8163                                 break;
8164         if (planeindex >= r_waterstate.maxwaterplanes)
8165                 return; // nothing we can do, out of planes
8166
8167         // if this triangle does not fit any known plane rendered this frame, add one
8168         if (planeindex >= r_waterstate.numwaterplanes)
8169         {
8170                 // store the new plane
8171                 r_waterstate.numwaterplanes++;
8172                 p->plane = plane;
8173                 // clear materialflags and pvs
8174                 p->materialflags = 0;
8175                 p->pvsvalid = false;
8176                 p->camera_entity = t->camera_entity;
8177                 VectorCopy(surface->mins, p->mins);
8178                 VectorCopy(surface->maxs, p->maxs);
8179         }
8180         else
8181         {
8182                 // merge mins/maxs
8183                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8184                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8185                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8186                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8187                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8188                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8189         }
8190         // merge this surface's materialflags into the waterplane
8191         p->materialflags |= t->currentmaterialflags;
8192         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8193         {
8194                 // merge this surface's PVS into the waterplane
8195                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8196                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8197                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8198                 {
8199                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8200                         p->pvsvalid = true;
8201                 }
8202         }
8203 }
8204
8205 static void R_Water_ProcessPlanes(void)
8206 {
8207         int myscissor[4];
8208         r_refdef_view_t originalview;
8209         r_refdef_view_t myview;
8210         int planeindex;
8211         r_waterstate_waterplane_t *p;
8212         vec3_t visorigin;
8213
8214         originalview = r_refdef.view;
8215
8216         // make sure enough textures are allocated
8217         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8218         {
8219                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8220                 {
8221                         if (!p->texture_refraction)
8222                                 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);
8223                         if (!p->texture_refraction)
8224                                 goto error;
8225                 }
8226                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8227                 {
8228                         if (!p->texture_camera)
8229                                 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);
8230                         if (!p->texture_camera)
8231                                 goto error;
8232                 }
8233
8234                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8235                 {
8236                         if (!p->texture_reflection)
8237                                 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);
8238                         if (!p->texture_reflection)
8239                                 goto error;
8240                 }
8241         }
8242
8243         // render views
8244         r_refdef.view = originalview;
8245         r_refdef.view.showdebug = false;
8246         r_refdef.view.width = r_waterstate.waterwidth;
8247         r_refdef.view.height = r_waterstate.waterheight;
8248         r_refdef.view.useclipplane = true;
8249         myview = r_refdef.view;
8250         r_waterstate.renderingscene = true;
8251         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8252         {
8253                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8254                 {
8255                         r_refdef.view = myview;
8256                         if(r_water_scissormode.integer)
8257                         {
8258                                 R_SetupView(true);
8259                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8260                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8261                         }
8262
8263                         // render reflected scene and copy into texture
8264                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8265                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8266                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8267                         r_refdef.view.clipplane = p->plane;
8268
8269                         // reverse the cullface settings for this render
8270                         r_refdef.view.cullface_front = GL_FRONT;
8271                         r_refdef.view.cullface_back = GL_BACK;
8272                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8273                         {
8274                                 r_refdef.view.usecustompvs = true;
8275                                 if (p->pvsvalid)
8276                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8277                                 else
8278                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8279                         }
8280
8281                         R_ResetViewRendering3D();
8282                         R_ClearScreen(r_refdef.fogenabled);
8283                         if(r_water_scissormode.integer & 2)
8284                                 R_View_UpdateWithScissor(myscissor);
8285                         else
8286                                 R_View_Update();
8287                         if(r_water_scissormode.integer & 1)
8288                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8289                         R_RenderScene();
8290
8291                         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);
8292                 }
8293
8294                 // render the normal view scene and copy into texture
8295                 // (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)
8296                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8297                 {
8298                         r_refdef.view = myview;
8299                         if(r_water_scissormode.integer)
8300                         {
8301                                 R_SetupView(true);
8302                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8303                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8304                         }
8305
8306                         r_waterstate.renderingrefraction = true;
8307
8308                         r_refdef.view.clipplane = p->plane;
8309                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8310                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8311
8312                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8313                         {
8314                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8315                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8316                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8317                                 R_RenderView_UpdateViewVectors();
8318                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8319                                 {
8320                                         r_refdef.view.usecustompvs = true;
8321                                         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);
8322                                 }
8323                         }
8324
8325                         PlaneClassify(&r_refdef.view.clipplane);
8326
8327                         R_ResetViewRendering3D();
8328                         R_ClearScreen(r_refdef.fogenabled);
8329                         if(r_water_scissormode.integer & 2)
8330                                 R_View_UpdateWithScissor(myscissor);
8331                         else
8332                                 R_View_Update();
8333                         if(r_water_scissormode.integer & 1)
8334                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8335                         R_RenderScene();
8336
8337                         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);
8338                         r_waterstate.renderingrefraction = false;
8339                 }
8340                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8341                 {
8342                         r_refdef.view = myview;
8343
8344                         r_refdef.view.clipplane = p->plane;
8345                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8346                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8347
8348                         r_refdef.view.width = r_waterstate.camerawidth;
8349                         r_refdef.view.height = r_waterstate.cameraheight;
8350                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8351                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8352
8353                         if(p->camera_entity)
8354                         {
8355                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8356                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8357                         }
8358
8359                         // note: all of the view is used for displaying... so
8360                         // there is no use in scissoring
8361
8362                         // reverse the cullface settings for this render
8363                         r_refdef.view.cullface_front = GL_FRONT;
8364                         r_refdef.view.cullface_back = GL_BACK;
8365                         // also reverse the view matrix
8366                         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
8367                         R_RenderView_UpdateViewVectors();
8368                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8369                         {
8370                                 r_refdef.view.usecustompvs = true;
8371                                 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);
8372                         }
8373                         
8374                         // camera needs no clipplane
8375                         r_refdef.view.useclipplane = false;
8376
8377                         PlaneClassify(&r_refdef.view.clipplane);
8378
8379                         R_ResetViewRendering3D();
8380                         R_ClearScreen(r_refdef.fogenabled);
8381                         R_View_Update();
8382                         R_RenderScene();
8383
8384                         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);
8385                         r_waterstate.renderingrefraction = false;
8386                 }
8387
8388         }
8389         r_waterstate.renderingscene = false;
8390         r_refdef.view = originalview;
8391         R_ResetViewRendering3D();
8392         R_ClearScreen(r_refdef.fogenabled);
8393         R_View_Update();
8394         return;
8395 error:
8396         r_refdef.view = originalview;
8397         r_waterstate.renderingscene = false;
8398         Cvar_SetValueQuick(&r_water, 0);
8399         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8400         return;
8401 }
8402
8403 void R_Bloom_StartFrame(void)
8404 {
8405         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8406
8407         switch(vid.renderpath)
8408         {
8409         case RENDERPATH_GL20:
8410         case RENDERPATH_D3D9:
8411         case RENDERPATH_D3D10:
8412         case RENDERPATH_D3D11:
8413         case RENDERPATH_SOFT:
8414         case RENDERPATH_GLES2:
8415                 break;
8416         case RENDERPATH_GL13:
8417         case RENDERPATH_GL11:
8418                 return;
8419         }
8420
8421         // set bloomwidth and bloomheight to the bloom resolution that will be
8422         // used (often less than the screen resolution for faster rendering)
8423         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8424         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8425         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8426         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8427         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8428
8429         // calculate desired texture sizes
8430         if (vid.support.arb_texture_non_power_of_two)
8431         {
8432                 screentexturewidth = r_refdef.view.width;
8433                 screentextureheight = r_refdef.view.height;
8434                 bloomtexturewidth = r_bloomstate.bloomwidth;
8435                 bloomtextureheight = r_bloomstate.bloomheight;
8436         }
8437         else
8438         {
8439                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8440                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8441                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8442                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8443         }
8444
8445         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))
8446         {
8447                 Cvar_SetValueQuick(&r_hdr, 0);
8448                 Cvar_SetValueQuick(&r_bloom, 0);
8449                 Cvar_SetValueQuick(&r_motionblur, 0);
8450                 Cvar_SetValueQuick(&r_damageblur, 0);
8451         }
8452
8453         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)))
8454                 screentexturewidth = screentextureheight = 0;
8455         if (!r_hdr.integer && !r_bloom.integer)
8456                 bloomtexturewidth = bloomtextureheight = 0;
8457
8458         // allocate textures as needed
8459         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8460         {
8461                 if (r_bloomstate.texture_screen)
8462                         R_FreeTexture(r_bloomstate.texture_screen);
8463                 r_bloomstate.texture_screen = NULL;
8464                 r_bloomstate.screentexturewidth = screentexturewidth;
8465                 r_bloomstate.screentextureheight = screentextureheight;
8466                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8467                         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);
8468         }
8469         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8470         {
8471                 if (r_bloomstate.texture_bloom)
8472                         R_FreeTexture(r_bloomstate.texture_bloom);
8473                 r_bloomstate.texture_bloom = NULL;
8474                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8475                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8476                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8477                         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);
8478         }
8479
8480         // when doing a reduced render (HDR) we want to use a smaller area
8481         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8482         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8483         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8484         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8485         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8486
8487         // set up a texcoord array for the full resolution screen image
8488         // (we have to keep this around to copy back during final render)
8489         r_bloomstate.screentexcoord2f[0] = 0;
8490         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8491         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8492         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8493         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8494         r_bloomstate.screentexcoord2f[5] = 0;
8495         r_bloomstate.screentexcoord2f[6] = 0;
8496         r_bloomstate.screentexcoord2f[7] = 0;
8497
8498         // set up a texcoord array for the reduced resolution bloom image
8499         // (which will be additive blended over the screen image)
8500         r_bloomstate.bloomtexcoord2f[0] = 0;
8501         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8502         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8503         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8504         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8505         r_bloomstate.bloomtexcoord2f[5] = 0;
8506         r_bloomstate.bloomtexcoord2f[6] = 0;
8507         r_bloomstate.bloomtexcoord2f[7] = 0;
8508
8509         switch(vid.renderpath)
8510         {
8511         case RENDERPATH_GL11:
8512         case RENDERPATH_GL13:
8513         case RENDERPATH_GL20:
8514         case RENDERPATH_SOFT:
8515         case RENDERPATH_GLES2:
8516                 break;
8517         case RENDERPATH_D3D9:
8518         case RENDERPATH_D3D10:
8519         case RENDERPATH_D3D11:
8520                 {
8521                         int i;
8522                         for (i = 0;i < 4;i++)
8523                         {
8524                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8525                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8526                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8527                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8528                         }
8529                 }
8530                 break;
8531         }
8532
8533         if (r_hdr.integer || r_bloom.integer)
8534         {
8535                 r_bloomstate.enabled = true;
8536                 r_bloomstate.hdr = r_hdr.integer != 0;
8537         }
8538
8539         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);
8540 }
8541
8542 void R_Bloom_CopyBloomTexture(float colorscale)
8543 {
8544         r_refdef.stats.bloom++;
8545
8546         // scale down screen texture to the bloom texture size
8547         CHECKGLERROR
8548         R_SetViewport(&r_bloomstate.viewport);
8549         GL_BlendFunc(GL_ONE, GL_ZERO);
8550         GL_Color(colorscale, colorscale, colorscale, 1);
8551         // 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...
8552         switch(vid.renderpath)
8553         {
8554         case RENDERPATH_GL11:
8555         case RENDERPATH_GL13:
8556         case RENDERPATH_GL20:
8557         case RENDERPATH_SOFT:
8558         case RENDERPATH_GLES2:
8559                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8560                 break;
8561         case RENDERPATH_D3D9:
8562         case RENDERPATH_D3D10:
8563         case RENDERPATH_D3D11:
8564                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8565                 break;
8566         }
8567         // TODO: do boxfilter scale-down in shader?
8568         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8569         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8570         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8571
8572         // we now have a bloom image in the framebuffer
8573         // copy it into the bloom image texture for later processing
8574         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);
8575         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8576 }
8577
8578 void R_Bloom_CopyHDRTexture(void)
8579 {
8580         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);
8581         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8582 }
8583
8584 void R_Bloom_MakeTexture(void)
8585 {
8586         int x, range, dir;
8587         float xoffset, yoffset, r, brighten;
8588
8589         r_refdef.stats.bloom++;
8590
8591         R_ResetViewRendering2D();
8592
8593         // we have a bloom image in the framebuffer
8594         CHECKGLERROR
8595         R_SetViewport(&r_bloomstate.viewport);
8596
8597         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8598         {
8599                 x *= 2;
8600                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8601                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8602                 GL_Color(r,r,r,1);
8603                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8604                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8605                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8606                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8607
8608                 // copy the vertically blurred bloom view to a texture
8609                 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);
8610                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8611         }
8612
8613         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8614         brighten = r_bloom_brighten.value;
8615         if (r_hdr.integer)
8616                 brighten *= r_hdr_range.value;
8617         brighten = sqrt(brighten);
8618         if(range >= 1)
8619                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8620         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8621
8622         for (dir = 0;dir < 2;dir++)
8623         {
8624                 // blend on at multiple vertical offsets to achieve a vertical blur
8625                 // TODO: do offset blends using GLSL
8626                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8627                 GL_BlendFunc(GL_ONE, GL_ZERO);
8628                 for (x = -range;x <= range;x++)
8629                 {
8630                         if (!dir){xoffset = 0;yoffset = x;}
8631                         else {xoffset = x;yoffset = 0;}
8632                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8633                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8634                         // compute a texcoord array with the specified x and y offset
8635                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8636                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8637                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8638                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8639                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8640                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8641                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8642                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8643                         // this r value looks like a 'dot' particle, fading sharply to
8644                         // black at the edges
8645                         // (probably not realistic but looks good enough)
8646                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8647                         //r = brighten/(range*2+1);
8648                         r = brighten / (range * 2 + 1);
8649                         if(range >= 1)
8650                                 r *= (1 - x*x/(float)(range*range));
8651                         GL_Color(r, r, r, 1);
8652                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8653                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8654                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8655                         GL_BlendFunc(GL_ONE, GL_ONE);
8656                 }
8657
8658                 // copy the vertically blurred bloom view to a texture
8659                 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);
8660                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8661         }
8662 }
8663
8664 void R_HDR_RenderBloomTexture(void)
8665 {
8666         int oldwidth, oldheight;
8667         float oldcolorscale;
8668         qboolean oldwaterstate;
8669
8670         oldwaterstate = r_waterstate.enabled;
8671         oldcolorscale = r_refdef.view.colorscale;
8672         oldwidth = r_refdef.view.width;
8673         oldheight = r_refdef.view.height;
8674         r_refdef.view.width = r_bloomstate.bloomwidth;
8675         r_refdef.view.height = r_bloomstate.bloomheight;
8676
8677         if(r_hdr.integer < 2)
8678                 r_waterstate.enabled = false;
8679
8680         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8681         // TODO: add exposure compensation features
8682         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8683
8684         r_refdef.view.showdebug = false;
8685         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8686
8687         R_ResetViewRendering3D();
8688
8689         R_ClearScreen(r_refdef.fogenabled);
8690         if (r_timereport_active)
8691                 R_TimeReport("HDRclear");
8692
8693         R_View_Update();
8694         if (r_timereport_active)
8695                 R_TimeReport("visibility");
8696
8697         // only do secondary renders with HDR if r_hdr is 2 or higher
8698         r_waterstate.numwaterplanes = 0;
8699         if (r_waterstate.enabled)
8700                 R_RenderWaterPlanes();
8701
8702         r_refdef.view.showdebug = true;
8703         R_RenderScene();
8704         r_waterstate.numwaterplanes = 0;
8705
8706         R_ResetViewRendering2D();
8707
8708         R_Bloom_CopyHDRTexture();
8709         R_Bloom_MakeTexture();
8710
8711         // restore the view settings
8712         r_waterstate.enabled = oldwaterstate;
8713         r_refdef.view.width = oldwidth;
8714         r_refdef.view.height = oldheight;
8715         r_refdef.view.colorscale = oldcolorscale;
8716
8717         R_ResetViewRendering3D();
8718
8719         R_ClearScreen(r_refdef.fogenabled);
8720         if (r_timereport_active)
8721                 R_TimeReport("viewclear");
8722 }
8723
8724 static void R_BlendView(void)
8725 {
8726         unsigned int permutation;
8727         float uservecs[4][4];
8728
8729         switch (vid.renderpath)
8730         {
8731         case RENDERPATH_GL20:
8732         case RENDERPATH_D3D9:
8733         case RENDERPATH_D3D10:
8734         case RENDERPATH_D3D11:
8735         case RENDERPATH_SOFT:
8736         case RENDERPATH_GLES2:
8737                 permutation =
8738                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8739                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8740                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8741                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8742                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8743
8744                 if (r_bloomstate.texture_screen)
8745                 {
8746                         // make sure the buffer is available
8747                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8748
8749                         R_ResetViewRendering2D();
8750
8751                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8752                         {
8753                                 // declare variables
8754                                 float speed;
8755                                 static float avgspeed;
8756
8757                                 speed = VectorLength(cl.movement_velocity);
8758
8759                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8760                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8761
8762                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8763                                 speed = bound(0, speed, 1);
8764                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8765
8766                                 // calculate values into a standard alpha
8767                                 cl.motionbluralpha = 1 - exp(-
8768                                                 (
8769                                                  (r_motionblur.value * speed / 80)
8770                                                  +
8771                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8772                                                 )
8773                                                 /
8774                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8775                                            );
8776
8777                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8778                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8779                                 // apply the blur
8780                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8781                                 {
8782                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8783                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8784                                         switch(vid.renderpath)
8785                                         {
8786                                         case RENDERPATH_GL11:
8787                                         case RENDERPATH_GL13:
8788                                         case RENDERPATH_GL20:
8789                                         case RENDERPATH_SOFT:
8790                                         case RENDERPATH_GLES2:
8791                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8792                                                 break;
8793                                         case RENDERPATH_D3D9:
8794                                         case RENDERPATH_D3D10:
8795                                         case RENDERPATH_D3D11:
8796                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8797                                                 break;
8798                                         }
8799                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8800                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8801                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8802                                 }
8803                         }
8804
8805                         // copy view into the screen texture
8806                         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);
8807                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8808                 }
8809                 else if (!r_bloomstate.texture_bloom)
8810                 {
8811                         // we may still have to do view tint...
8812                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8813                         {
8814                                 // apply a color tint to the whole view
8815                                 R_ResetViewRendering2D();
8816                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8817                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8818                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8819                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8820                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8821                         }
8822                         break; // no screen processing, no bloom, skip it
8823                 }
8824
8825                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8826                 {
8827                         // render simple bloom effect
8828                         // copy the screen and shrink it and darken it for the bloom process
8829                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8830                         // make the bloom texture
8831                         R_Bloom_MakeTexture();
8832                 }
8833
8834 #if _MSC_VER >= 1400
8835 #define sscanf sscanf_s
8836 #endif
8837                 memset(uservecs, 0, sizeof(uservecs));
8838                 if (r_glsl_postprocess_uservec1_enable.integer)
8839                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8840                 if (r_glsl_postprocess_uservec2_enable.integer)
8841                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8842                 if (r_glsl_postprocess_uservec3_enable.integer)
8843                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8844                 if (r_glsl_postprocess_uservec4_enable.integer)
8845                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8846
8847                 R_ResetViewRendering2D();
8848                 GL_Color(1, 1, 1, 1);
8849                 GL_BlendFunc(GL_ONE, GL_ZERO);
8850
8851                 switch(vid.renderpath)
8852                 {
8853                 case RENDERPATH_GL20:
8854                 case RENDERPATH_GLES2:
8855                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8856                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8857                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
8858                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
8859                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
8860                         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]);
8861                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8862                         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]);
8863                         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]);
8864                         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]);
8865                         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]);
8866                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8867                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8868                         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);
8869                         break;
8870                 case RENDERPATH_D3D9:
8871 #ifdef SUPPORTD3D
8872                         // 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...
8873                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8874                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8875                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8876                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8877                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8878                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8879                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8880                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8881                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8882                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8883                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8884                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
8885                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8886                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8887 #endif
8888                         break;
8889                 case RENDERPATH_D3D10:
8890                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8891                         break;
8892                 case RENDERPATH_D3D11:
8893                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8894                         break;
8895                 case RENDERPATH_SOFT:
8896                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8897                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8898                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8899                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8900                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8901                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8902                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8903                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8904                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8905                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8906                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8907                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
8908                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8909                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8910                         break;
8911                 default:
8912                         break;
8913                 }
8914                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8915                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8916                 break;
8917         case RENDERPATH_GL13:
8918         case RENDERPATH_GL11:
8919                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8920                 {
8921                         // apply a color tint to the whole view
8922                         R_ResetViewRendering2D();
8923                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8924                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8925                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8926                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8927                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8928                 }
8929                 break;
8930         }
8931 }
8932
8933 matrix4x4_t r_waterscrollmatrix;
8934
8935 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
8936 {
8937         if (r_refdef.fog_density)
8938         {
8939                 r_refdef.fogcolor[0] = r_refdef.fog_red;
8940                 r_refdef.fogcolor[1] = r_refdef.fog_green;
8941                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
8942
8943                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
8944                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
8945                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
8946                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
8947
8948                 {
8949                         vec3_t fogvec;
8950                         VectorCopy(r_refdef.fogcolor, fogvec);
8951                         //   color.rgb *= ContrastBoost * SceneBrightness;
8952                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
8953                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
8954                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
8955                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
8956                 }
8957         }
8958 }
8959
8960 void R_UpdateVariables(void)
8961 {
8962         R_Textures_Frame();
8963
8964         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
8965
8966         r_refdef.farclip = r_farclip_base.value;
8967         if (r_refdef.scene.worldmodel)
8968                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
8969         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
8970
8971         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
8972                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
8973         r_refdef.polygonfactor = 0;
8974         r_refdef.polygonoffset = 0;
8975         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8976         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
8977
8978         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
8979         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
8980         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
8981         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
8982         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
8983         if (FAKELIGHT_ENABLED)
8984         {
8985                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
8986         }
8987         if (r_showsurfaces.integer)
8988         {
8989                 r_refdef.scene.rtworld = false;
8990                 r_refdef.scene.rtworldshadows = false;
8991                 r_refdef.scene.rtdlight = false;
8992                 r_refdef.scene.rtdlightshadows = false;
8993                 r_refdef.lightmapintensity = 0;
8994         }
8995
8996         if (gamemode == GAME_NEHAHRA)
8997         {
8998                 if (gl_fogenable.integer)
8999                 {
9000                         r_refdef.oldgl_fogenable = true;
9001                         r_refdef.fog_density = gl_fogdensity.value;
9002                         r_refdef.fog_red = gl_fogred.value;
9003                         r_refdef.fog_green = gl_foggreen.value;
9004                         r_refdef.fog_blue = gl_fogblue.value;
9005                         r_refdef.fog_alpha = 1;
9006                         r_refdef.fog_start = 0;
9007                         r_refdef.fog_end = gl_skyclip.value;
9008                         r_refdef.fog_height = 1<<30;
9009                         r_refdef.fog_fadedepth = 128;
9010                 }
9011                 else if (r_refdef.oldgl_fogenable)
9012                 {
9013                         r_refdef.oldgl_fogenable = false;
9014                         r_refdef.fog_density = 0;
9015                         r_refdef.fog_red = 0;
9016                         r_refdef.fog_green = 0;
9017                         r_refdef.fog_blue = 0;
9018                         r_refdef.fog_alpha = 0;
9019                         r_refdef.fog_start = 0;
9020                         r_refdef.fog_end = 0;
9021                         r_refdef.fog_height = 1<<30;
9022                         r_refdef.fog_fadedepth = 128;
9023                 }
9024         }
9025
9026         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9027         r_refdef.fog_start = max(0, r_refdef.fog_start);
9028         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9029
9030         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9031
9032         if (r_refdef.fog_density && r_drawfog.integer)
9033         {
9034                 r_refdef.fogenabled = true;
9035                 // this is the point where the fog reaches 0.9986 alpha, which we
9036                 // consider a good enough cutoff point for the texture
9037                 // (0.9986 * 256 == 255.6)
9038                 if (r_fog_exp2.integer)
9039                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9040                 else
9041                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9042                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9043                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9044                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9045                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9046                         R_BuildFogHeightTexture();
9047                 // fog color was already set
9048                 // update the fog texture
9049                 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)
9050                         R_BuildFogTexture();
9051                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9052                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9053         }
9054         else
9055                 r_refdef.fogenabled = false;
9056
9057         switch(vid.renderpath)
9058         {
9059         case RENDERPATH_GL20:
9060         case RENDERPATH_D3D9:
9061         case RENDERPATH_D3D10:
9062         case RENDERPATH_D3D11:
9063         case RENDERPATH_SOFT:
9064         case RENDERPATH_GLES2:
9065                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9066                 {
9067                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9068                         {
9069                                 // build GLSL gamma texture
9070 #define RAMPWIDTH 256
9071                                 unsigned short ramp[RAMPWIDTH * 3];
9072                                 unsigned char rampbgr[RAMPWIDTH][4];
9073                                 int i;
9074
9075                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9076
9077                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9078                                 for(i = 0; i < RAMPWIDTH; ++i)
9079                                 {
9080                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9081                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9082                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9083                                         rampbgr[i][3] = 0;
9084                                 }
9085                                 if (r_texture_gammaramps)
9086                                 {
9087                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
9088                                 }
9089                                 else
9090                                 {
9091                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9092                                 }
9093                         }
9094                 }
9095                 else
9096                 {
9097                         // remove GLSL gamma texture
9098                 }
9099                 break;
9100         case RENDERPATH_GL13:
9101         case RENDERPATH_GL11:
9102                 break;
9103         }
9104 }
9105
9106 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9107 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9108 /*
9109 ================
9110 R_SelectScene
9111 ================
9112 */
9113 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9114         if( scenetype != r_currentscenetype ) {
9115                 // store the old scenetype
9116                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9117                 r_currentscenetype = scenetype;
9118                 // move in the new scene
9119                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9120         }
9121 }
9122
9123 /*
9124 ================
9125 R_GetScenePointer
9126 ================
9127 */
9128 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9129 {
9130         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9131         if( scenetype == r_currentscenetype ) {
9132                 return &r_refdef.scene;
9133         } else {
9134                 return &r_scenes_store[ scenetype ];
9135         }
9136 }
9137
9138 /*
9139 ================
9140 R_RenderView
9141 ================
9142 */
9143 int dpsoftrast_test;
9144 void R_RenderView(void)
9145 {
9146         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9147
9148         dpsoftrast_test = r_test.integer;
9149
9150         if (r_timereport_active)
9151                 R_TimeReport("start");
9152         r_textureframe++; // used only by R_GetCurrentTexture
9153         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9154
9155         if(R_CompileShader_CheckStaticParms())
9156                 R_GLSL_Restart_f();
9157
9158         if (!r_drawentities.integer)
9159                 r_refdef.scene.numentities = 0;
9160
9161         R_AnimCache_ClearCache();
9162         R_FrameData_NewFrame();
9163
9164         /* adjust for stereo display */
9165         if(R_Stereo_Active())
9166         {
9167                 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);
9168                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9169         }
9170
9171         if (r_refdef.view.isoverlay)
9172         {
9173                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9174                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9175                 R_TimeReport("depthclear");
9176
9177                 r_refdef.view.showdebug = false;
9178
9179                 r_waterstate.enabled = false;
9180                 r_waterstate.numwaterplanes = 0;
9181
9182                 R_RenderScene();
9183
9184                 r_refdef.view.matrix = originalmatrix;
9185
9186                 CHECKGLERROR
9187                 return;
9188         }
9189
9190         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9191         {
9192                 r_refdef.view.matrix = originalmatrix;
9193                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9194         }
9195
9196         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9197
9198         R_RenderView_UpdateViewVectors();
9199
9200         R_Shadow_UpdateWorldLightSelection();
9201
9202         R_Bloom_StartFrame();
9203         R_Water_StartFrame();
9204
9205         CHECKGLERROR
9206         if (r_timereport_active)
9207                 R_TimeReport("viewsetup");
9208
9209         R_ResetViewRendering3D();
9210
9211         if (r_refdef.view.clear || r_refdef.fogenabled)
9212         {
9213                 R_ClearScreen(r_refdef.fogenabled);
9214                 if (r_timereport_active)
9215                         R_TimeReport("viewclear");
9216         }
9217         r_refdef.view.clear = true;
9218
9219         // this produces a bloom texture to be used in R_BlendView() later
9220         if (r_hdr.integer && r_bloomstate.bloomwidth)
9221         {
9222                 R_HDR_RenderBloomTexture();
9223                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9224                 r_textureframe++; // used only by R_GetCurrentTexture
9225         }
9226
9227         r_refdef.view.showdebug = true;
9228
9229         R_View_Update();
9230         if (r_timereport_active)
9231                 R_TimeReport("visibility");
9232
9233         r_waterstate.numwaterplanes = 0;
9234         if (r_waterstate.enabled)
9235                 R_RenderWaterPlanes();
9236
9237         R_RenderScene();
9238         r_waterstate.numwaterplanes = 0;
9239
9240         R_BlendView();
9241         if (r_timereport_active)
9242                 R_TimeReport("blendview");
9243
9244         GL_Scissor(0, 0, vid.width, vid.height);
9245         GL_ScissorTest(false);
9246
9247         r_refdef.view.matrix = originalmatrix;
9248
9249         CHECKGLERROR
9250 }
9251
9252 void R_RenderWaterPlanes(void)
9253 {
9254         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9255         {
9256                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9257                 if (r_timereport_active)
9258                         R_TimeReport("waterworld");
9259         }
9260
9261         // don't let sound skip if going slow
9262         if (r_refdef.scene.extraupdate)
9263                 S_ExtraUpdate ();
9264
9265         R_DrawModelsAddWaterPlanes();
9266         if (r_timereport_active)
9267                 R_TimeReport("watermodels");
9268
9269         if (r_waterstate.numwaterplanes)
9270         {
9271                 R_Water_ProcessPlanes();
9272                 if (r_timereport_active)
9273                         R_TimeReport("waterscenes");
9274         }
9275 }
9276
9277 extern void R_DrawLightningBeams (void);
9278 extern void VM_CL_AddPolygonsToMeshQueue (void);
9279 extern void R_DrawPortals (void);
9280 extern cvar_t cl_locs_show;
9281 static void R_DrawLocs(void);
9282 static void R_DrawEntityBBoxes(void);
9283 static void R_DrawModelDecals(void);
9284 extern void R_DrawModelShadows(void);
9285 extern void R_DrawModelShadowMaps(void);
9286 extern cvar_t cl_decals_newsystem;
9287 extern qboolean r_shadow_usingdeferredprepass;
9288 void R_RenderScene(void)
9289 {
9290         qboolean shadowmapping = false;
9291
9292         if (r_timereport_active)
9293                 R_TimeReport("beginscene");
9294
9295         r_refdef.stats.renders++;
9296
9297         R_UpdateFogColor();
9298
9299         // don't let sound skip if going slow
9300         if (r_refdef.scene.extraupdate)
9301                 S_ExtraUpdate ();
9302
9303         R_MeshQueue_BeginScene();
9304
9305         R_SkyStartFrame();
9306
9307         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);
9308
9309         if (r_timereport_active)
9310                 R_TimeReport("skystartframe");
9311
9312         if (cl.csqc_vidvars.drawworld)
9313         {
9314                 // don't let sound skip if going slow
9315                 if (r_refdef.scene.extraupdate)
9316                         S_ExtraUpdate ();
9317
9318                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9319                 {
9320                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9321                         if (r_timereport_active)
9322                                 R_TimeReport("worldsky");
9323                 }
9324
9325                 if (R_DrawBrushModelsSky() && r_timereport_active)
9326                         R_TimeReport("bmodelsky");
9327
9328                 if (skyrendermasked && skyrenderlater)
9329                 {
9330                         // we have to force off the water clipping plane while rendering sky
9331                         R_SetupView(false);
9332                         R_Sky();
9333                         R_SetupView(true);
9334                         if (r_timereport_active)
9335                                 R_TimeReport("sky");
9336                 }
9337         }
9338
9339         R_AnimCache_CacheVisibleEntities();
9340         if (r_timereport_active)
9341                 R_TimeReport("animation");
9342
9343         R_Shadow_PrepareLights();
9344         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9345                 R_Shadow_PrepareModelShadows();
9346         if (r_timereport_active)
9347                 R_TimeReport("preparelights");
9348
9349         if (R_Shadow_ShadowMappingEnabled())
9350                 shadowmapping = true;
9351
9352         if (r_shadow_usingdeferredprepass)
9353                 R_Shadow_DrawPrepass();
9354
9355         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9356         {
9357                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9358                 if (r_timereport_active)
9359                         R_TimeReport("worlddepth");
9360         }
9361         if (r_depthfirst.integer >= 2)
9362         {
9363                 R_DrawModelsDepth();
9364                 if (r_timereport_active)
9365                         R_TimeReport("modeldepth");
9366         }
9367
9368         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9369         {
9370                 R_DrawModelShadowMaps();
9371                 R_ResetViewRendering3D();
9372                 // don't let sound skip if going slow
9373                 if (r_refdef.scene.extraupdate)
9374                         S_ExtraUpdate ();
9375         }
9376
9377         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9378         {
9379                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9380                 if (r_timereport_active)
9381                         R_TimeReport("world");
9382         }
9383
9384         // don't let sound skip if going slow
9385         if (r_refdef.scene.extraupdate)
9386                 S_ExtraUpdate ();
9387
9388         R_DrawModels();
9389         if (r_timereport_active)
9390                 R_TimeReport("models");
9391
9392         // don't let sound skip if going slow
9393         if (r_refdef.scene.extraupdate)
9394                 S_ExtraUpdate ();
9395
9396         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9397         {
9398                 R_DrawModelShadows();
9399                 R_ResetViewRendering3D();
9400                 // don't let sound skip if going slow
9401                 if (r_refdef.scene.extraupdate)
9402                         S_ExtraUpdate ();
9403         }
9404
9405         if (!r_shadow_usingdeferredprepass)
9406         {
9407                 R_Shadow_DrawLights();
9408                 if (r_timereport_active)
9409                         R_TimeReport("rtlights");
9410         }
9411
9412         // don't let sound skip if going slow
9413         if (r_refdef.scene.extraupdate)
9414                 S_ExtraUpdate ();
9415
9416         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9417         {
9418                 R_DrawModelShadows();
9419                 R_ResetViewRendering3D();
9420                 // don't let sound skip if going slow
9421                 if (r_refdef.scene.extraupdate)
9422                         S_ExtraUpdate ();
9423         }
9424
9425         if (cl.csqc_vidvars.drawworld)
9426         {
9427                 if (cl_decals_newsystem.integer)
9428                 {
9429                         R_DrawModelDecals();
9430                         if (r_timereport_active)
9431                                 R_TimeReport("modeldecals");
9432                 }
9433                 else
9434                 {
9435                         R_DrawDecals();
9436                         if (r_timereport_active)
9437                                 R_TimeReport("decals");
9438                 }
9439
9440                 R_DrawParticles();
9441                 if (r_timereport_active)
9442                         R_TimeReport("particles");
9443
9444                 R_DrawExplosions();
9445                 if (r_timereport_active)
9446                         R_TimeReport("explosions");
9447
9448                 R_DrawLightningBeams();
9449                 if (r_timereport_active)
9450                         R_TimeReport("lightning");
9451         }
9452
9453         VM_CL_AddPolygonsToMeshQueue();
9454
9455         if (r_refdef.view.showdebug)
9456         {
9457                 if (cl_locs_show.integer)
9458                 {
9459                         R_DrawLocs();
9460                         if (r_timereport_active)
9461                                 R_TimeReport("showlocs");
9462                 }
9463
9464                 if (r_drawportals.integer)
9465                 {
9466                         R_DrawPortals();
9467                         if (r_timereport_active)
9468                                 R_TimeReport("portals");
9469                 }
9470
9471                 if (r_showbboxes.value > 0)
9472                 {
9473                         R_DrawEntityBBoxes();
9474                         if (r_timereport_active)
9475                                 R_TimeReport("bboxes");
9476                 }
9477         }
9478
9479         R_MeshQueue_RenderTransparent();
9480         if (r_timereport_active)
9481                 R_TimeReport("drawtrans");
9482
9483         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))
9484         {
9485                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9486                 if (r_timereport_active)
9487                         R_TimeReport("worlddebug");
9488                 R_DrawModelsDebug();
9489                 if (r_timereport_active)
9490                         R_TimeReport("modeldebug");
9491         }
9492
9493         if (cl.csqc_vidvars.drawworld)
9494         {
9495                 R_Shadow_DrawCoronas();
9496                 if (r_timereport_active)
9497                         R_TimeReport("coronas");
9498         }
9499
9500 #if 0
9501         {
9502                 GL_DepthTest(false);
9503                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9504                 GL_Color(1, 1, 1, 1);
9505                 qglBegin(GL_POLYGON);
9506                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9507                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9508                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9509                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9510                 qglEnd();
9511                 qglBegin(GL_POLYGON);
9512                 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]);
9513                 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]);
9514                 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]);
9515                 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]);
9516                 qglEnd();
9517                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9518         }
9519 #endif
9520
9521         // don't let sound skip if going slow
9522         if (r_refdef.scene.extraupdate)
9523                 S_ExtraUpdate ();
9524
9525         R_ResetViewRendering2D();
9526 }
9527
9528 static const unsigned short bboxelements[36] =
9529 {
9530         5, 1, 3, 5, 3, 7,
9531         6, 2, 0, 6, 0, 4,
9532         7, 3, 2, 7, 2, 6,
9533         4, 0, 1, 4, 1, 5,
9534         4, 5, 7, 4, 7, 6,
9535         1, 0, 2, 1, 2, 3,
9536 };
9537
9538 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9539 {
9540         int i;
9541         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9542
9543         RSurf_ActiveWorldEntity();
9544
9545         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9546         GL_DepthMask(false);
9547         GL_DepthRange(0, 1);
9548         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9549 //      R_Mesh_ResetTextureState();
9550
9551         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9552         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9553         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9554         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9555         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9556         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9557         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9558         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9559         R_FillColors(color4f, 8, cr, cg, cb, ca);
9560         if (r_refdef.fogenabled)
9561         {
9562                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9563                 {
9564                         f1 = RSurf_FogVertex(v);
9565                         f2 = 1 - f1;
9566                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9567                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9568                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9569                 }
9570         }
9571         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9572         R_Mesh_ResetTextureState();
9573         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9574         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9575 }
9576
9577 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9578 {
9579         int i;
9580         float color[4];
9581         prvm_edict_t *edict;
9582         prvm_prog_t *prog_save = prog;
9583
9584         // this function draws bounding boxes of server entities
9585         if (!sv.active)
9586                 return;
9587
9588         GL_CullFace(GL_NONE);
9589         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9590
9591         prog = 0;
9592         SV_VM_Begin();
9593         for (i = 0;i < numsurfaces;i++)
9594         {
9595                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9596                 switch ((int)edict->fields.server->solid)
9597                 {
9598                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9599                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9600                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9601                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9602                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9603                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9604                 }
9605                 color[3] *= r_showbboxes.value;
9606                 color[3] = bound(0, color[3], 1);
9607                 GL_DepthTest(!r_showdisabledepthtest.integer);
9608                 GL_CullFace(r_refdef.view.cullface_front);
9609                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9610         }
9611         SV_VM_End();
9612         prog = prog_save;
9613 }
9614
9615 static void R_DrawEntityBBoxes(void)
9616 {
9617         int i;
9618         prvm_edict_t *edict;
9619         vec3_t center;
9620         prvm_prog_t *prog_save = prog;
9621
9622         // this function draws bounding boxes of server entities
9623         if (!sv.active)
9624                 return;
9625
9626         prog = 0;
9627         SV_VM_Begin();
9628         for (i = 0;i < prog->num_edicts;i++)
9629         {
9630                 edict = PRVM_EDICT_NUM(i);
9631                 if (edict->priv.server->free)
9632                         continue;
9633                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9634                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9635                         continue;
9636                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9637                         continue;
9638                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9639                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9640         }
9641         SV_VM_End();
9642         prog = prog_save;
9643 }
9644
9645 static const int nomodelelement3i[24] =
9646 {
9647         5, 2, 0,
9648         5, 1, 2,
9649         5, 0, 3,
9650         5, 3, 1,
9651         0, 2, 4,
9652         2, 1, 4,
9653         3, 0, 4,
9654         1, 3, 4
9655 };
9656
9657 static const unsigned short nomodelelement3s[24] =
9658 {
9659         5, 2, 0,
9660         5, 1, 2,
9661         5, 0, 3,
9662         5, 3, 1,
9663         0, 2, 4,
9664         2, 1, 4,
9665         3, 0, 4,
9666         1, 3, 4
9667 };
9668
9669 static const float nomodelvertex3f[6*3] =
9670 {
9671         -16,   0,   0,
9672          16,   0,   0,
9673           0, -16,   0,
9674           0,  16,   0,
9675           0,   0, -16,
9676           0,   0,  16
9677 };
9678
9679 static const float nomodelcolor4f[6*4] =
9680 {
9681         0.0f, 0.0f, 0.5f, 1.0f,
9682         0.0f, 0.0f, 0.5f, 1.0f,
9683         0.0f, 0.5f, 0.0f, 1.0f,
9684         0.0f, 0.5f, 0.0f, 1.0f,
9685         0.5f, 0.0f, 0.0f, 1.0f,
9686         0.5f, 0.0f, 0.0f, 1.0f
9687 };
9688
9689 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9690 {
9691         int i;
9692         float f1, f2, *c;
9693         float color4f[6*4];
9694
9695         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);
9696
9697         // this is only called once per entity so numsurfaces is always 1, and
9698         // surfacelist is always {0}, so this code does not handle batches
9699
9700         if (rsurface.ent_flags & RENDER_ADDITIVE)
9701         {
9702                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9703                 GL_DepthMask(false);
9704         }
9705         else if (rsurface.colormod[3] < 1)
9706         {
9707                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9708                 GL_DepthMask(false);
9709         }
9710         else
9711         {
9712                 GL_BlendFunc(GL_ONE, GL_ZERO);
9713                 GL_DepthMask(true);
9714         }
9715         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9716         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9717         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9718         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9719         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9720         for (i = 0, c = color4f;i < 6;i++, c += 4)
9721         {
9722                 c[0] *= rsurface.colormod[0];
9723                 c[1] *= rsurface.colormod[1];
9724                 c[2] *= rsurface.colormod[2];
9725                 c[3] *= rsurface.colormod[3];
9726         }
9727         if (r_refdef.fogenabled)
9728         {
9729                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9730                 {
9731                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9732                         f2 = 1 - f1;
9733                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9734                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9735                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9736                 }
9737         }
9738 //      R_Mesh_ResetTextureState();
9739         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9740         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9741         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9742 }
9743
9744 void R_DrawNoModel(entity_render_t *ent)
9745 {
9746         vec3_t org;
9747         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9748         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9749                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9750         else
9751                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9752 }
9753
9754 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9755 {
9756         vec3_t right1, right2, diff, normal;
9757
9758         VectorSubtract (org2, org1, normal);
9759
9760         // calculate 'right' vector for start
9761         VectorSubtract (r_refdef.view.origin, org1, diff);
9762         CrossProduct (normal, diff, right1);
9763         VectorNormalize (right1);
9764
9765         // calculate 'right' vector for end
9766         VectorSubtract (r_refdef.view.origin, org2, diff);
9767         CrossProduct (normal, diff, right2);
9768         VectorNormalize (right2);
9769
9770         vert[ 0] = org1[0] + width * right1[0];
9771         vert[ 1] = org1[1] + width * right1[1];
9772         vert[ 2] = org1[2] + width * right1[2];
9773         vert[ 3] = org1[0] - width * right1[0];
9774         vert[ 4] = org1[1] - width * right1[1];
9775         vert[ 5] = org1[2] - width * right1[2];
9776         vert[ 6] = org2[0] - width * right2[0];
9777         vert[ 7] = org2[1] - width * right2[1];
9778         vert[ 8] = org2[2] - width * right2[2];
9779         vert[ 9] = org2[0] + width * right2[0];
9780         vert[10] = org2[1] + width * right2[1];
9781         vert[11] = org2[2] + width * right2[2];
9782 }
9783
9784 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)
9785 {
9786         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9787         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9788         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9789         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9790         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9791         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9792         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9793         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9794         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9795         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9796         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9797         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9798 }
9799
9800 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9801 {
9802         int i;
9803         float *vertex3f;
9804         float v[3];
9805         VectorSet(v, x, y, z);
9806         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9807                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9808                         break;
9809         if (i == mesh->numvertices)
9810         {
9811                 if (mesh->numvertices < mesh->maxvertices)
9812                 {
9813                         VectorCopy(v, vertex3f);
9814                         mesh->numvertices++;
9815                 }
9816                 return mesh->numvertices;
9817         }
9818         else
9819                 return i;
9820 }
9821
9822 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9823 {
9824         int i;
9825         int *e, element[3];
9826         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9827         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9828         e = mesh->element3i + mesh->numtriangles * 3;
9829         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9830         {
9831                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9832                 if (mesh->numtriangles < mesh->maxtriangles)
9833                 {
9834                         *e++ = element[0];
9835                         *e++ = element[1];
9836                         *e++ = element[2];
9837                         mesh->numtriangles++;
9838                 }
9839                 element[1] = element[2];
9840         }
9841 }
9842
9843 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9844 {
9845         int i;
9846         int *e, element[3];
9847         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9848         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9849         e = mesh->element3i + mesh->numtriangles * 3;
9850         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9851         {
9852                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9853                 if (mesh->numtriangles < mesh->maxtriangles)
9854                 {
9855                         *e++ = element[0];
9856                         *e++ = element[1];
9857                         *e++ = element[2];
9858                         mesh->numtriangles++;
9859                 }
9860                 element[1] = element[2];
9861         }
9862 }
9863
9864 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9865 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9866 {
9867         int planenum, planenum2;
9868         int w;
9869         int tempnumpoints;
9870         mplane_t *plane, *plane2;
9871         double maxdist;
9872         double temppoints[2][256*3];
9873         // figure out how large a bounding box we need to properly compute this brush
9874         maxdist = 0;
9875         for (w = 0;w < numplanes;w++)
9876                 maxdist = max(maxdist, fabs(planes[w].dist));
9877         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9878         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9879         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9880         {
9881                 w = 0;
9882                 tempnumpoints = 4;
9883                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9884                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9885                 {
9886                         if (planenum2 == planenum)
9887                                 continue;
9888                         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);
9889                         w = !w;
9890                 }
9891                 if (tempnumpoints < 3)
9892                         continue;
9893                 // generate elements forming a triangle fan for this polygon
9894                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9895         }
9896 }
9897
9898 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)
9899 {
9900         texturelayer_t *layer;
9901         layer = t->currentlayers + t->currentnumlayers++;
9902         layer->type = type;
9903         layer->depthmask = depthmask;
9904         layer->blendfunc1 = blendfunc1;
9905         layer->blendfunc2 = blendfunc2;
9906         layer->texture = texture;
9907         layer->texmatrix = *matrix;
9908         layer->color[0] = r;
9909         layer->color[1] = g;
9910         layer->color[2] = b;
9911         layer->color[3] = a;
9912 }
9913
9914 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
9915 {
9916         if(parms[0] == 0 && parms[1] == 0)
9917                 return false;
9918         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9919                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
9920                         return false;
9921         return true;
9922 }
9923
9924 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
9925 {
9926         double index, f;
9927         index = parms[2] + r_refdef.scene.time * parms[3];
9928         index -= floor(index);
9929         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
9930         {
9931         default:
9932         case Q3WAVEFUNC_NONE:
9933         case Q3WAVEFUNC_NOISE:
9934         case Q3WAVEFUNC_COUNT:
9935                 f = 0;
9936                 break;
9937         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
9938         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
9939         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
9940         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
9941         case Q3WAVEFUNC_TRIANGLE:
9942                 index *= 4;
9943                 f = index - floor(index);
9944                 if (index < 1)
9945                         f = f;
9946                 else if (index < 2)
9947                         f = 1 - f;
9948                 else if (index < 3)
9949                         f = -f;
9950                 else
9951                         f = -(1 - f);
9952                 break;
9953         }
9954         f = parms[0] + parms[1] * f;
9955         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
9956                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
9957         return (float) f;
9958 }
9959
9960 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
9961 {
9962         int w, h, idx;
9963         float f;
9964         float tcmat[12];
9965         matrix4x4_t matrix, temp;
9966         switch(tcmod->tcmod)
9967         {
9968                 case Q3TCMOD_COUNT:
9969                 case Q3TCMOD_NONE:
9970                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
9971                                 matrix = r_waterscrollmatrix;
9972                         else
9973                                 matrix = identitymatrix;
9974                         break;
9975                 case Q3TCMOD_ENTITYTRANSLATE:
9976                         // this is used in Q3 to allow the gamecode to control texcoord
9977                         // scrolling on the entity, which is not supported in darkplaces yet.
9978                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
9979                         break;
9980                 case Q3TCMOD_ROTATE:
9981                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
9982                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
9983                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
9984                         break;
9985                 case Q3TCMOD_SCALE:
9986                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
9987                         break;
9988                 case Q3TCMOD_SCROLL:
9989                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
9990                         break;
9991                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
9992                         w = (int) tcmod->parms[0];
9993                         h = (int) tcmod->parms[1];
9994                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
9995                         f = f - floor(f);
9996                         idx = (int) floor(f * w * h);
9997                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
9998                         break;
9999                 case Q3TCMOD_STRETCH:
10000                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10001                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10002                         break;
10003                 case Q3TCMOD_TRANSFORM:
10004                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10005                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10006                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10007                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10008                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10009                         break;
10010                 case Q3TCMOD_TURBULENT:
10011                         // this is handled in the RSurf_PrepareVertices function
10012                         matrix = identitymatrix;
10013                         break;
10014         }
10015         temp = *texmatrix;
10016         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10017 }
10018
10019 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10020 {
10021         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10022         char name[MAX_QPATH];
10023         skinframe_t *skinframe;
10024         unsigned char pixels[296*194];
10025         strlcpy(cache->name, skinname, sizeof(cache->name));
10026         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10027         if (developer_loading.integer)
10028                 Con_Printf("loading %s\n", name);
10029         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10030         if (!skinframe || !skinframe->base)
10031         {
10032                 unsigned char *f;
10033                 fs_offset_t filesize;
10034                 skinframe = NULL;
10035                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10036                 if (f)
10037                 {
10038                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10039                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10040                         Mem_Free(f);
10041                 }
10042         }
10043         cache->skinframe = skinframe;
10044 }
10045
10046 texture_t *R_GetCurrentTexture(texture_t *t)
10047 {
10048         int i;
10049         const entity_render_t *ent = rsurface.entity;
10050         dp_model_t *model = ent->model;
10051         q3shaderinfo_layer_tcmod_t *tcmod;
10052
10053         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10054                 return t->currentframe;
10055         t->update_lastrenderframe = r_textureframe;
10056         t->update_lastrenderentity = (void *)ent;
10057
10058         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10059                 t->camera_entity = ent->entitynumber;
10060         else
10061                 t->camera_entity = 0;
10062
10063         // switch to an alternate material if this is a q1bsp animated material
10064         {
10065                 texture_t *texture = t;
10066                 int s = rsurface.ent_skinnum;
10067                 if ((unsigned int)s >= (unsigned int)model->numskins)
10068                         s = 0;
10069                 if (model->skinscenes)
10070                 {
10071                         if (model->skinscenes[s].framecount > 1)
10072                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10073                         else
10074                                 s = model->skinscenes[s].firstframe;
10075                 }
10076                 if (s > 0)
10077                         t = t + s * model->num_surfaces;
10078                 if (t->animated)
10079                 {
10080                         // use an alternate animation if the entity's frame is not 0,
10081                         // and only if the texture has an alternate animation
10082                         if (rsurface.ent_alttextures && t->anim_total[1])
10083                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10084                         else
10085                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10086                 }
10087                 texture->currentframe = t;
10088         }
10089
10090         // update currentskinframe to be a qw skin or animation frame
10091         if (rsurface.ent_qwskin >= 0)
10092         {
10093                 i = rsurface.ent_qwskin;
10094                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10095                 {
10096                         r_qwskincache_size = cl.maxclients;
10097                         if (r_qwskincache)
10098                                 Mem_Free(r_qwskincache);
10099                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10100                 }
10101                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10102                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10103                 t->currentskinframe = r_qwskincache[i].skinframe;
10104                 if (t->currentskinframe == NULL)
10105                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10106         }
10107         else if (t->numskinframes >= 2)
10108                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10109         if (t->backgroundnumskinframes >= 2)
10110                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10111
10112         t->currentmaterialflags = t->basematerialflags;
10113         t->currentalpha = rsurface.colormod[3];
10114         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10115                 t->currentalpha *= r_wateralpha.value;
10116         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10117                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10118         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10119                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10120         if (!(rsurface.ent_flags & RENDER_LIGHT))
10121                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10122         else if (FAKELIGHT_ENABLED)
10123         {
10124                         // no modellight if using fakelight for the map
10125         }
10126         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10127         {
10128                 // pick a model lighting mode
10129                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10130                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10131                 else
10132                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10133         }
10134         if (rsurface.ent_flags & RENDER_ADDITIVE)
10135                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10136         else if (t->currentalpha < 1)
10137                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10138         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10139                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10140         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10141                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10142         if (t->backgroundnumskinframes)
10143                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10144         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10145         {
10146                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10147                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10148         }
10149         else
10150                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10151         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10152                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10153
10154         // there is no tcmod
10155         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10156         {
10157                 t->currenttexmatrix = r_waterscrollmatrix;
10158                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10159         }
10160         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10161         {
10162                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10163                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10164         }
10165
10166         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10167                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10168         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10169                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10170
10171         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10172         if (t->currentskinframe->qpixels)
10173                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10174         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10175         if (!t->basetexture)
10176                 t->basetexture = r_texture_notexture;
10177         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10178         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10179         t->nmaptexture = t->currentskinframe->nmap;
10180         if (!t->nmaptexture)
10181                 t->nmaptexture = r_texture_blanknormalmap;
10182         t->glosstexture = r_texture_black;
10183         t->glowtexture = t->currentskinframe->glow;
10184         t->fogtexture = t->currentskinframe->fog;
10185         t->reflectmasktexture = t->currentskinframe->reflect;
10186         if (t->backgroundnumskinframes)
10187         {
10188                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10189                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10190                 t->backgroundglosstexture = r_texture_black;
10191                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10192                 if (!t->backgroundnmaptexture)
10193                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10194         }
10195         else
10196         {
10197                 t->backgroundbasetexture = r_texture_white;
10198                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10199                 t->backgroundglosstexture = r_texture_black;
10200                 t->backgroundglowtexture = NULL;
10201         }
10202         t->specularpower = r_shadow_glossexponent.value;
10203         // TODO: store reference values for these in the texture?
10204         t->specularscale = 0;
10205         if (r_shadow_gloss.integer > 0)
10206         {
10207                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10208                 {
10209                         if (r_shadow_glossintensity.value > 0)
10210                         {
10211                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10212                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10213                                 t->specularscale = r_shadow_glossintensity.value;
10214                         }
10215                 }
10216                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10217                 {
10218                         t->glosstexture = r_texture_white;
10219                         t->backgroundglosstexture = r_texture_white;
10220                         t->specularscale = r_shadow_gloss2intensity.value;
10221                         t->specularpower = r_shadow_gloss2exponent.value;
10222                 }
10223         }
10224         t->specularscale *= t->specularscalemod;
10225         t->specularpower *= t->specularpowermod;
10226
10227         // lightmaps mode looks bad with dlights using actual texturing, so turn
10228         // off the colormap and glossmap, but leave the normalmap on as it still
10229         // accurately represents the shading involved
10230         if (gl_lightmaps.integer)
10231         {
10232                 t->basetexture = r_texture_grey128;
10233                 t->pantstexture = r_texture_black;
10234                 t->shirttexture = r_texture_black;
10235                 t->nmaptexture = r_texture_blanknormalmap;
10236                 t->glosstexture = r_texture_black;
10237                 t->glowtexture = NULL;
10238                 t->fogtexture = NULL;
10239                 t->reflectmasktexture = NULL;
10240                 t->backgroundbasetexture = NULL;
10241                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10242                 t->backgroundglosstexture = r_texture_black;
10243                 t->backgroundglowtexture = NULL;
10244                 t->specularscale = 0;
10245                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10246         }
10247
10248         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10249         VectorClear(t->dlightcolor);
10250         t->currentnumlayers = 0;
10251         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10252         {
10253                 int blendfunc1, blendfunc2;
10254                 qboolean depthmask;
10255                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10256                 {
10257                         blendfunc1 = GL_SRC_ALPHA;
10258                         blendfunc2 = GL_ONE;
10259                 }
10260                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10261                 {
10262                         blendfunc1 = GL_SRC_ALPHA;
10263                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10264                 }
10265                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10266                 {
10267                         blendfunc1 = t->customblendfunc[0];
10268                         blendfunc2 = t->customblendfunc[1];
10269                 }
10270                 else
10271                 {
10272                         blendfunc1 = GL_ONE;
10273                         blendfunc2 = GL_ZERO;
10274                 }
10275                 // don't colormod evilblend textures
10276                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10277                         VectorSet(t->lightmapcolor, 1, 1, 1);
10278                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10279                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10280                 {
10281                         // fullbright is not affected by r_refdef.lightmapintensity
10282                         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]);
10283                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10284                                 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]);
10285                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10286                                 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]);
10287                 }
10288                 else
10289                 {
10290                         vec3_t ambientcolor;
10291                         float colorscale;
10292                         // set the color tint used for lights affecting this surface
10293                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10294                         colorscale = 2;
10295                         // q3bsp has no lightmap updates, so the lightstylevalue that
10296                         // would normally be baked into the lightmap must be
10297                         // applied to the color
10298                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10299                         if (model->type == mod_brushq3)
10300                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10301                         colorscale *= r_refdef.lightmapintensity;
10302                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10303                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10304                         // basic lit geometry
10305                         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]);
10306                         // add pants/shirt if needed
10307                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10308                                 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]);
10309                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10310                                 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]);
10311                         // now add ambient passes if needed
10312                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10313                         {
10314                                 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]);
10315                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10316                                         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]);
10317                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10318                                         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]);
10319                         }
10320                 }
10321                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10322                         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]);
10323                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10324                 {
10325                         // if this is opaque use alpha blend which will darken the earlier
10326                         // passes cheaply.
10327                         //
10328                         // if this is an alpha blended material, all the earlier passes
10329                         // were darkened by fog already, so we only need to add the fog
10330                         // color ontop through the fog mask texture
10331                         //
10332                         // if this is an additive blended material, all the earlier passes
10333                         // were darkened by fog already, and we should not add fog color
10334                         // (because the background was not darkened, there is no fog color
10335                         // that was lost behind it).
10336                         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]);
10337                 }
10338         }
10339
10340         return t->currentframe;
10341 }
10342
10343 rsurfacestate_t rsurface;
10344
10345 void RSurf_ActiveWorldEntity(void)
10346 {
10347         dp_model_t *model = r_refdef.scene.worldmodel;
10348         //if (rsurface.entity == r_refdef.scene.worldentity)
10349         //      return;
10350         rsurface.entity = r_refdef.scene.worldentity;
10351         rsurface.skeleton = NULL;
10352         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10353         rsurface.ent_skinnum = 0;
10354         rsurface.ent_qwskin = -1;
10355         rsurface.ent_shadertime = 0;
10356         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10357         rsurface.matrix = identitymatrix;
10358         rsurface.inversematrix = identitymatrix;
10359         rsurface.matrixscale = 1;
10360         rsurface.inversematrixscale = 1;
10361         R_EntityMatrix(&identitymatrix);
10362         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10363         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10364         rsurface.fograngerecip = r_refdef.fograngerecip;
10365         rsurface.fogheightfade = r_refdef.fogheightfade;
10366         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10367         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10368         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10369         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10370         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10371         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10372         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10373         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10374         rsurface.colormod[3] = 1;
10375         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);
10376         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10377         rsurface.frameblend[0].lerp = 1;
10378         rsurface.ent_alttextures = false;
10379         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10380         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10381         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10382         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10383         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10384         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10385         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10386         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10387         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10388         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10389         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10390         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10391         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10392         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10393         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10394         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10395         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10396         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10397         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10398         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10399         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10400         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10401         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10402         rsurface.modelelement3i = model->surfmesh.data_element3i;
10403         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10404         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10405         rsurface.modelelement3s = model->surfmesh.data_element3s;
10406         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10407         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10408         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10409         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10410         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10411         rsurface.modelsurfaces = model->data_surfaces;
10412         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10413         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10414         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10415         rsurface.modelgeneratedvertex = false;
10416         rsurface.batchgeneratedvertex = false;
10417         rsurface.batchfirstvertex = 0;
10418         rsurface.batchnumvertices = 0;
10419         rsurface.batchfirsttriangle = 0;
10420         rsurface.batchnumtriangles = 0;
10421         rsurface.batchvertex3f  = NULL;
10422         rsurface.batchvertex3f_vertexbuffer = NULL;
10423         rsurface.batchvertex3f_bufferoffset = 0;
10424         rsurface.batchsvector3f = NULL;
10425         rsurface.batchsvector3f_vertexbuffer = NULL;
10426         rsurface.batchsvector3f_bufferoffset = 0;
10427         rsurface.batchtvector3f = NULL;
10428         rsurface.batchtvector3f_vertexbuffer = NULL;
10429         rsurface.batchtvector3f_bufferoffset = 0;
10430         rsurface.batchnormal3f  = NULL;
10431         rsurface.batchnormal3f_vertexbuffer = NULL;
10432         rsurface.batchnormal3f_bufferoffset = 0;
10433         rsurface.batchlightmapcolor4f = NULL;
10434         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10435         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10436         rsurface.batchtexcoordtexture2f = NULL;
10437         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10438         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10439         rsurface.batchtexcoordlightmap2f = NULL;
10440         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10441         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10442         rsurface.batchvertexmesh = NULL;
10443         rsurface.batchvertexmeshbuffer = NULL;
10444         rsurface.batchvertex3fbuffer = NULL;
10445         rsurface.batchelement3i = NULL;
10446         rsurface.batchelement3i_indexbuffer = NULL;
10447         rsurface.batchelement3i_bufferoffset = 0;
10448         rsurface.batchelement3s = NULL;
10449         rsurface.batchelement3s_indexbuffer = NULL;
10450         rsurface.batchelement3s_bufferoffset = 0;
10451         rsurface.passcolor4f = NULL;
10452         rsurface.passcolor4f_vertexbuffer = NULL;
10453         rsurface.passcolor4f_bufferoffset = 0;
10454 }
10455
10456 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10457 {
10458         dp_model_t *model = ent->model;
10459         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10460         //      return;
10461         rsurface.entity = (entity_render_t *)ent;
10462         rsurface.skeleton = ent->skeleton;
10463         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10464         rsurface.ent_skinnum = ent->skinnum;
10465         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;
10466         rsurface.ent_shadertime = ent->shadertime;
10467         rsurface.ent_flags = ent->flags;
10468         rsurface.matrix = ent->matrix;
10469         rsurface.inversematrix = ent->inversematrix;
10470         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10471         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10472         R_EntityMatrix(&rsurface.matrix);
10473         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10474         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10475         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10476         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10477         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10478         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10479         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10480         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10481         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10482         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10483         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10484         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10485         rsurface.colormod[3] = ent->alpha;
10486         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10487         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10488         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10489         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10490         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10491         if (ent->model->brush.submodel && !prepass)
10492         {
10493                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10494                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10495         }
10496         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10497         {
10498                 if (ent->animcache_vertex3f)
10499                 {
10500                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10501                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10502                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10503                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10504                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10505                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10506                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10507                 }
10508                 else if (wanttangents)
10509                 {
10510                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10511                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10512                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10513                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10514                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10515                         rsurface.modelvertexmesh = NULL;
10516                         rsurface.modelvertexmeshbuffer = NULL;
10517                         rsurface.modelvertex3fbuffer = NULL;
10518                 }
10519                 else if (wantnormals)
10520                 {
10521                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10522                         rsurface.modelsvector3f = NULL;
10523                         rsurface.modeltvector3f = NULL;
10524                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10525                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10526                         rsurface.modelvertexmesh = NULL;
10527                         rsurface.modelvertexmeshbuffer = NULL;
10528                         rsurface.modelvertex3fbuffer = NULL;
10529                 }
10530                 else
10531                 {
10532                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10533                         rsurface.modelsvector3f = NULL;
10534                         rsurface.modeltvector3f = NULL;
10535                         rsurface.modelnormal3f = NULL;
10536                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10537                         rsurface.modelvertexmesh = NULL;
10538                         rsurface.modelvertexmeshbuffer = NULL;
10539                         rsurface.modelvertex3fbuffer = NULL;
10540                 }
10541                 rsurface.modelvertex3f_vertexbuffer = 0;
10542                 rsurface.modelvertex3f_bufferoffset = 0;
10543                 rsurface.modelsvector3f_vertexbuffer = 0;
10544                 rsurface.modelsvector3f_bufferoffset = 0;
10545                 rsurface.modeltvector3f_vertexbuffer = 0;
10546                 rsurface.modeltvector3f_bufferoffset = 0;
10547                 rsurface.modelnormal3f_vertexbuffer = 0;
10548                 rsurface.modelnormal3f_bufferoffset = 0;
10549                 rsurface.modelgeneratedvertex = true;
10550         }
10551         else
10552         {
10553                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10554                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10555                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10556                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10557                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10558                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10559                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10560                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10561                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10562                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10563                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10564                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10565                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10566                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10567                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10568                 rsurface.modelgeneratedvertex = false;
10569         }
10570         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10571         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10572         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10573         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10574         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10575         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10576         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10577         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10578         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10579         rsurface.modelelement3i = model->surfmesh.data_element3i;
10580         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10581         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10582         rsurface.modelelement3s = model->surfmesh.data_element3s;
10583         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10584         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10585         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10586         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10587         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10588         rsurface.modelsurfaces = model->data_surfaces;
10589         rsurface.batchgeneratedvertex = false;
10590         rsurface.batchfirstvertex = 0;
10591         rsurface.batchnumvertices = 0;
10592         rsurface.batchfirsttriangle = 0;
10593         rsurface.batchnumtriangles = 0;
10594         rsurface.batchvertex3f  = NULL;
10595         rsurface.batchvertex3f_vertexbuffer = NULL;
10596         rsurface.batchvertex3f_bufferoffset = 0;
10597         rsurface.batchsvector3f = NULL;
10598         rsurface.batchsvector3f_vertexbuffer = NULL;
10599         rsurface.batchsvector3f_bufferoffset = 0;
10600         rsurface.batchtvector3f = NULL;
10601         rsurface.batchtvector3f_vertexbuffer = NULL;
10602         rsurface.batchtvector3f_bufferoffset = 0;
10603         rsurface.batchnormal3f  = NULL;
10604         rsurface.batchnormal3f_vertexbuffer = NULL;
10605         rsurface.batchnormal3f_bufferoffset = 0;
10606         rsurface.batchlightmapcolor4f = NULL;
10607         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10608         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10609         rsurface.batchtexcoordtexture2f = NULL;
10610         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10611         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10612         rsurface.batchtexcoordlightmap2f = NULL;
10613         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10614         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10615         rsurface.batchvertexmesh = NULL;
10616         rsurface.batchvertexmeshbuffer = NULL;
10617         rsurface.batchvertex3fbuffer = NULL;
10618         rsurface.batchelement3i = NULL;
10619         rsurface.batchelement3i_indexbuffer = NULL;
10620         rsurface.batchelement3i_bufferoffset = 0;
10621         rsurface.batchelement3s = NULL;
10622         rsurface.batchelement3s_indexbuffer = NULL;
10623         rsurface.batchelement3s_bufferoffset = 0;
10624         rsurface.passcolor4f = NULL;
10625         rsurface.passcolor4f_vertexbuffer = NULL;
10626         rsurface.passcolor4f_bufferoffset = 0;
10627 }
10628
10629 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)
10630 {
10631         rsurface.entity = r_refdef.scene.worldentity;
10632         rsurface.skeleton = NULL;
10633         rsurface.ent_skinnum = 0;
10634         rsurface.ent_qwskin = -1;
10635         rsurface.ent_shadertime = shadertime;
10636         rsurface.ent_flags = entflags;
10637         rsurface.modelnumvertices = numvertices;
10638         rsurface.modelnumtriangles = numtriangles;
10639         rsurface.matrix = *matrix;
10640         rsurface.inversematrix = *inversematrix;
10641         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10642         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10643         R_EntityMatrix(&rsurface.matrix);
10644         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10645         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10646         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10647         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10648         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10649         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10650         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10651         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10652         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10653         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10654         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10655         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10656         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);
10657         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10658         rsurface.frameblend[0].lerp = 1;
10659         rsurface.ent_alttextures = false;
10660         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10661         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10662         if (wanttangents)
10663         {
10664                 rsurface.modelvertex3f = (float *)vertex3f;
10665                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10666                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10667                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10668         }
10669         else if (wantnormals)
10670         {
10671                 rsurface.modelvertex3f = (float *)vertex3f;
10672                 rsurface.modelsvector3f = NULL;
10673                 rsurface.modeltvector3f = NULL;
10674                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10675         }
10676         else
10677         {
10678                 rsurface.modelvertex3f = (float *)vertex3f;
10679                 rsurface.modelsvector3f = NULL;
10680                 rsurface.modeltvector3f = NULL;
10681                 rsurface.modelnormal3f = NULL;
10682         }
10683         rsurface.modelvertexmesh = NULL;
10684         rsurface.modelvertexmeshbuffer = NULL;
10685         rsurface.modelvertex3fbuffer = NULL;
10686         rsurface.modelvertex3f_vertexbuffer = 0;
10687         rsurface.modelvertex3f_bufferoffset = 0;
10688         rsurface.modelsvector3f_vertexbuffer = 0;
10689         rsurface.modelsvector3f_bufferoffset = 0;
10690         rsurface.modeltvector3f_vertexbuffer = 0;
10691         rsurface.modeltvector3f_bufferoffset = 0;
10692         rsurface.modelnormal3f_vertexbuffer = 0;
10693         rsurface.modelnormal3f_bufferoffset = 0;
10694         rsurface.modelgeneratedvertex = true;
10695         rsurface.modellightmapcolor4f  = (float *)color4f;
10696         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10697         rsurface.modellightmapcolor4f_bufferoffset = 0;
10698         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
10699         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10700         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10701         rsurface.modeltexcoordlightmap2f  = NULL;
10702         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10703         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10704         rsurface.modelelement3i = (int *)element3i;
10705         rsurface.modelelement3i_indexbuffer = NULL;
10706         rsurface.modelelement3i_bufferoffset = 0;
10707         rsurface.modelelement3s = (unsigned short *)element3s;
10708         rsurface.modelelement3s_indexbuffer = NULL;
10709         rsurface.modelelement3s_bufferoffset = 0;
10710         rsurface.modellightmapoffsets = NULL;
10711         rsurface.modelsurfaces = NULL;
10712         rsurface.batchgeneratedvertex = false;
10713         rsurface.batchfirstvertex = 0;
10714         rsurface.batchnumvertices = 0;
10715         rsurface.batchfirsttriangle = 0;
10716         rsurface.batchnumtriangles = 0;
10717         rsurface.batchvertex3f  = NULL;
10718         rsurface.batchvertex3f_vertexbuffer = NULL;
10719         rsurface.batchvertex3f_bufferoffset = 0;
10720         rsurface.batchsvector3f = NULL;
10721         rsurface.batchsvector3f_vertexbuffer = NULL;
10722         rsurface.batchsvector3f_bufferoffset = 0;
10723         rsurface.batchtvector3f = NULL;
10724         rsurface.batchtvector3f_vertexbuffer = NULL;
10725         rsurface.batchtvector3f_bufferoffset = 0;
10726         rsurface.batchnormal3f  = NULL;
10727         rsurface.batchnormal3f_vertexbuffer = NULL;
10728         rsurface.batchnormal3f_bufferoffset = 0;
10729         rsurface.batchlightmapcolor4f = NULL;
10730         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10731         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10732         rsurface.batchtexcoordtexture2f = NULL;
10733         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10734         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10735         rsurface.batchtexcoordlightmap2f = NULL;
10736         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10737         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10738         rsurface.batchvertexmesh = NULL;
10739         rsurface.batchvertexmeshbuffer = NULL;
10740         rsurface.batchvertex3fbuffer = NULL;
10741         rsurface.batchelement3i = NULL;
10742         rsurface.batchelement3i_indexbuffer = NULL;
10743         rsurface.batchelement3i_bufferoffset = 0;
10744         rsurface.batchelement3s = NULL;
10745         rsurface.batchelement3s_indexbuffer = NULL;
10746         rsurface.batchelement3s_bufferoffset = 0;
10747         rsurface.passcolor4f = NULL;
10748         rsurface.passcolor4f_vertexbuffer = NULL;
10749         rsurface.passcolor4f_bufferoffset = 0;
10750
10751         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10752         {
10753                 if ((wantnormals || wanttangents) && !normal3f)
10754                 {
10755                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10756                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10757                 }
10758                 if (wanttangents && !svector3f)
10759                 {
10760                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10761                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10762                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10763                 }
10764         }
10765 }
10766
10767 float RSurf_FogPoint(const float *v)
10768 {
10769         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10770         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10771         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10772         float FogHeightFade = r_refdef.fogheightfade;
10773         float fogfrac;
10774         unsigned int fogmasktableindex;
10775         if (r_refdef.fogplaneviewabove)
10776                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10777         else
10778                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10779         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10780         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10781 }
10782
10783 float RSurf_FogVertex(const float *v)
10784 {
10785         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10786         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10787         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10788         float FogHeightFade = rsurface.fogheightfade;
10789         float fogfrac;
10790         unsigned int fogmasktableindex;
10791         if (r_refdef.fogplaneviewabove)
10792                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10793         else
10794                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10795         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10796         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10797 }
10798
10799 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10800 {
10801         int i;
10802         for (i = 0;i < numelements;i++)
10803                 outelement3i[i] = inelement3i[i] + adjust;
10804 }
10805
10806 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10807 extern cvar_t gl_vbo;
10808 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10809 {
10810         int deformindex;
10811         int firsttriangle;
10812         int numtriangles;
10813         int firstvertex;
10814         int endvertex;
10815         int numvertices;
10816         int surfacefirsttriangle;
10817         int surfacenumtriangles;
10818         int surfacefirstvertex;
10819         int surfaceendvertex;
10820         int surfacenumvertices;
10821         int batchnumvertices;
10822         int batchnumtriangles;
10823         int needsupdate;
10824         int i, j;
10825         qboolean gaps;
10826         qboolean dynamicvertex;
10827         float amplitude;
10828         float animpos;
10829         float scale;
10830         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10831         float waveparms[4];
10832         q3shaderinfo_deform_t *deform;
10833         const msurface_t *surface, *firstsurface;
10834         r_vertexmesh_t *vertexmesh;
10835         if (!texturenumsurfaces)
10836                 return;
10837         // find vertex range of this surface batch
10838         gaps = false;
10839         firstsurface = texturesurfacelist[0];
10840         firsttriangle = firstsurface->num_firsttriangle;
10841         batchnumvertices = 0;
10842         batchnumtriangles = 0;
10843         firstvertex = endvertex = firstsurface->num_firstvertex;
10844         for (i = 0;i < texturenumsurfaces;i++)
10845         {
10846                 surface = texturesurfacelist[i];
10847                 if (surface != firstsurface + i)
10848                         gaps = true;
10849                 surfacefirstvertex = surface->num_firstvertex;
10850                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10851                 surfacenumvertices = surface->num_vertices;
10852                 surfacenumtriangles = surface->num_triangles;
10853                 if (firstvertex > surfacefirstvertex)
10854                         firstvertex = surfacefirstvertex;
10855                 if (endvertex < surfaceendvertex)
10856                         endvertex = surfaceendvertex;
10857                 batchnumvertices += surfacenumvertices;
10858                 batchnumtriangles += surfacenumtriangles;
10859         }
10860
10861         // we now know the vertex range used, and if there are any gaps in it
10862         rsurface.batchfirstvertex = firstvertex;
10863         rsurface.batchnumvertices = endvertex - firstvertex;
10864         rsurface.batchfirsttriangle = firsttriangle;
10865         rsurface.batchnumtriangles = batchnumtriangles;
10866
10867         // this variable holds flags for which properties have been updated that
10868         // may require regenerating vertexmesh array...
10869         needsupdate = 0;
10870
10871         // check if any dynamic vertex processing must occur
10872         dynamicvertex = false;
10873
10874         // if there is a chance of animated vertex colors, it's a dynamic batch
10875         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10876         {
10877                 dynamicvertex = true;
10878                 batchneed |= BATCHNEED_NOGAPS;
10879                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10880         }
10881
10882         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10883         {
10884                 switch (deform->deform)
10885                 {
10886                 default:
10887                 case Q3DEFORM_PROJECTIONSHADOW:
10888                 case Q3DEFORM_TEXT0:
10889                 case Q3DEFORM_TEXT1:
10890                 case Q3DEFORM_TEXT2:
10891                 case Q3DEFORM_TEXT3:
10892                 case Q3DEFORM_TEXT4:
10893                 case Q3DEFORM_TEXT5:
10894                 case Q3DEFORM_TEXT6:
10895                 case Q3DEFORM_TEXT7:
10896                 case Q3DEFORM_NONE:
10897                         break;
10898                 case Q3DEFORM_AUTOSPRITE:
10899                         dynamicvertex = true;
10900                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10901                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10902                         break;
10903                 case Q3DEFORM_AUTOSPRITE2:
10904                         dynamicvertex = true;
10905                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10906                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10907                         break;
10908                 case Q3DEFORM_NORMAL:
10909                         dynamicvertex = true;
10910                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10911                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10912                         break;
10913                 case Q3DEFORM_WAVE:
10914                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10915                                 break; // if wavefunc is a nop, ignore this transform
10916                         dynamicvertex = true;
10917                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10918                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10919                         break;
10920                 case Q3DEFORM_BULGE:
10921                         dynamicvertex = true;
10922                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10923                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10924                         break;
10925                 case Q3DEFORM_MOVE:
10926                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10927                                 break; // if wavefunc is a nop, ignore this transform
10928                         dynamicvertex = true;
10929                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10930                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
10931                         break;
10932                 }
10933         }
10934         switch(rsurface.texture->tcgen.tcgen)
10935         {
10936         default:
10937         case Q3TCGEN_TEXTURE:
10938                 break;
10939         case Q3TCGEN_LIGHTMAP:
10940                 dynamicvertex = true;
10941                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
10942                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
10943                 break;
10944         case Q3TCGEN_VECTOR:
10945                 dynamicvertex = true;
10946                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
10947                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10948                 break;
10949         case Q3TCGEN_ENVIRONMENT:
10950                 dynamicvertex = true;
10951                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
10952                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10953                 break;
10954         }
10955         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10956         {
10957                 dynamicvertex = true;
10958                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10959                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
10960         }
10961
10962         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10963         {
10964                 dynamicvertex = true;
10965                 batchneed |= BATCHNEED_NOGAPS;
10966                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
10967         }
10968
10969         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
10970         {
10971                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
10972                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
10973                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
10974                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
10975                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
10976                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
10977                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
10978         }
10979
10980         // when the model data has no vertex buffer (dynamic mesh), we need to
10981         // eliminate gaps
10982         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
10983                 batchneed |= BATCHNEED_NOGAPS;
10984
10985         // if needsupdate, we have to do a dynamic vertex batch for sure
10986         if (needsupdate & batchneed)
10987                 dynamicvertex = true;
10988
10989         // see if we need to build vertexmesh from arrays
10990         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
10991                 dynamicvertex = true;
10992
10993         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
10994         // also some drivers strongly dislike firstvertex
10995         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
10996                 dynamicvertex = true;
10997
10998         rsurface.batchvertex3f = rsurface.modelvertex3f;
10999         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11000         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11001         rsurface.batchsvector3f = rsurface.modelsvector3f;
11002         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11003         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11004         rsurface.batchtvector3f = rsurface.modeltvector3f;
11005         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11006         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11007         rsurface.batchnormal3f = rsurface.modelnormal3f;
11008         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11009         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11010         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11011         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11012         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11013         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11014         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11015         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11016         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11017         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11018         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11019         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11020         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11021         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11022         rsurface.batchelement3i = rsurface.modelelement3i;
11023         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11024         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11025         rsurface.batchelement3s = rsurface.modelelement3s;
11026         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11027         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11028
11029         // if any dynamic vertex processing has to occur in software, we copy the
11030         // entire surface list together before processing to rebase the vertices
11031         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11032         //
11033         // if any gaps exist and we do not have a static vertex buffer, we have to
11034         // copy the surface list together to avoid wasting upload bandwidth on the
11035         // vertices in the gaps.
11036         //
11037         // if gaps exist and we have a static vertex buffer, we still have to
11038         // combine the index buffer ranges into one dynamic index buffer.
11039         //
11040         // in all cases we end up with data that can be drawn in one call.
11041
11042         if (!dynamicvertex)
11043         {
11044                 // static vertex data, just set pointers...
11045                 rsurface.batchgeneratedvertex = false;
11046                 // if there are gaps, we want to build a combined index buffer,
11047                 // otherwise use the original static buffer with an appropriate offset
11048                 if (gaps)
11049                 {
11050                         // build a new triangle elements array for this batch
11051                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11052                         rsurface.batchfirsttriangle = 0;
11053                         numtriangles = 0;
11054                         for (i = 0;i < texturenumsurfaces;i++)
11055                         {
11056                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11057                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11058                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11059                                 numtriangles += surfacenumtriangles;
11060                         }
11061                         rsurface.batchelement3i_indexbuffer = NULL;
11062                         rsurface.batchelement3i_bufferoffset = 0;
11063                         rsurface.batchelement3s = NULL;
11064                         rsurface.batchelement3s_indexbuffer = NULL;
11065                         rsurface.batchelement3s_bufferoffset = 0;
11066                         if (endvertex <= 65536)
11067                         {
11068                                 // make a 16bit (unsigned short) index array if possible
11069                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11070                                 for (i = 0;i < numtriangles*3;i++)
11071                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11072                         }
11073                 }
11074                 return;
11075         }
11076
11077         // something needs software processing, do it for real...
11078         // we only directly handle separate array data in this case and then
11079         // generate interleaved data if needed...
11080         rsurface.batchgeneratedvertex = true;
11081
11082         // now copy the vertex data into a combined array and make an index array
11083         // (this is what Quake3 does all the time)
11084         //if (gaps || rsurface.batchfirstvertex)
11085         {
11086                 rsurface.batchvertex3fbuffer = NULL;
11087                 rsurface.batchvertexmesh = NULL;
11088                 rsurface.batchvertexmeshbuffer = NULL;
11089                 rsurface.batchvertex3f = NULL;
11090                 rsurface.batchvertex3f_vertexbuffer = NULL;
11091                 rsurface.batchvertex3f_bufferoffset = 0;
11092                 rsurface.batchsvector3f = NULL;
11093                 rsurface.batchsvector3f_vertexbuffer = NULL;
11094                 rsurface.batchsvector3f_bufferoffset = 0;
11095                 rsurface.batchtvector3f = NULL;
11096                 rsurface.batchtvector3f_vertexbuffer = NULL;
11097                 rsurface.batchtvector3f_bufferoffset = 0;
11098                 rsurface.batchnormal3f = NULL;
11099                 rsurface.batchnormal3f_vertexbuffer = NULL;
11100                 rsurface.batchnormal3f_bufferoffset = 0;
11101                 rsurface.batchlightmapcolor4f = NULL;
11102                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11103                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11104                 rsurface.batchtexcoordtexture2f = NULL;
11105                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11106                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11107                 rsurface.batchtexcoordlightmap2f = NULL;
11108                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11109                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11110                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11111                 rsurface.batchelement3i_indexbuffer = NULL;
11112                 rsurface.batchelement3i_bufferoffset = 0;
11113                 rsurface.batchelement3s = NULL;
11114                 rsurface.batchelement3s_indexbuffer = NULL;
11115                 rsurface.batchelement3s_bufferoffset = 0;
11116                 // we'll only be setting up certain arrays as needed
11117                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11118                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11119                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11120                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11121                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11122                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11123                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11124                 {
11125                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11126                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11127                 }
11128                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11129                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11130                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11131                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11132                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11133                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11134                 numvertices = 0;
11135                 numtriangles = 0;
11136                 for (i = 0;i < texturenumsurfaces;i++)
11137                 {
11138                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11139                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11140                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11141                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11142                         // copy only the data requested
11143                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11144                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11145                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11146                         {
11147                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11148                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11149                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11150                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11151                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11152                                 {
11153                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11154                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11155                                 }
11156                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11157                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11158                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11159                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11160                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11161                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11162                         }
11163                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11164                         numvertices += surfacenumvertices;
11165                         numtriangles += surfacenumtriangles;
11166                 }
11167
11168                 // generate a 16bit index array as well if possible
11169                 // (in general, dynamic batches fit)
11170                 if (numvertices <= 65536)
11171                 {
11172                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11173                         for (i = 0;i < numtriangles*3;i++)
11174                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11175                 }
11176
11177                 // since we've copied everything, the batch now starts at 0
11178                 rsurface.batchfirstvertex = 0;
11179                 rsurface.batchnumvertices = batchnumvertices;
11180                 rsurface.batchfirsttriangle = 0;
11181                 rsurface.batchnumtriangles = batchnumtriangles;
11182         }
11183
11184         // q1bsp surfaces rendered in vertex color mode have to have colors
11185         // calculated based on lightstyles
11186         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11187         {
11188                 // generate color arrays for the surfaces in this list
11189                 int c[4];
11190                 int scale;
11191                 int size3;
11192                 const int *offsets;
11193                 const unsigned char *lm;
11194                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11195                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11196                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11197                 numvertices = 0;
11198                 for (i = 0;i < texturenumsurfaces;i++)
11199                 {
11200                         surface = texturesurfacelist[i];
11201                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11202                         surfacenumvertices = surface->num_vertices;
11203                         if (surface->lightmapinfo->samples)
11204                         {
11205                                 for (j = 0;j < surfacenumvertices;j++)
11206                                 {
11207                                         lm = surface->lightmapinfo->samples + offsets[j];
11208                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11209                                         VectorScale(lm, scale, c);
11210                                         if (surface->lightmapinfo->styles[1] != 255)
11211                                         {
11212                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11213                                                 lm += size3;
11214                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11215                                                 VectorMA(c, scale, lm, c);
11216                                                 if (surface->lightmapinfo->styles[2] != 255)
11217                                                 {
11218                                                         lm += size3;
11219                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11220                                                         VectorMA(c, scale, lm, c);
11221                                                         if (surface->lightmapinfo->styles[3] != 255)
11222                                                         {
11223                                                                 lm += size3;
11224                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11225                                                                 VectorMA(c, scale, lm, c);
11226                                                         }
11227                                                 }
11228                                         }
11229                                         c[0] >>= 7;
11230                                         c[1] >>= 7;
11231                                         c[2] >>= 7;
11232                                         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);
11233                                         numvertices++;
11234                                 }
11235                         }
11236                         else
11237                         {
11238                                 for (j = 0;j < surfacenumvertices;j++)
11239                                 {
11240                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11241                                         numvertices++;
11242                                 }
11243                         }
11244                 }
11245         }
11246
11247         // if vertices are deformed (sprite flares and things in maps, possibly
11248         // water waves, bulges and other deformations), modify the copied vertices
11249         // in place
11250         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11251         {
11252                 switch (deform->deform)
11253                 {
11254                 default:
11255                 case Q3DEFORM_PROJECTIONSHADOW:
11256                 case Q3DEFORM_TEXT0:
11257                 case Q3DEFORM_TEXT1:
11258                 case Q3DEFORM_TEXT2:
11259                 case Q3DEFORM_TEXT3:
11260                 case Q3DEFORM_TEXT4:
11261                 case Q3DEFORM_TEXT5:
11262                 case Q3DEFORM_TEXT6:
11263                 case Q3DEFORM_TEXT7:
11264                 case Q3DEFORM_NONE:
11265                         break;
11266                 case Q3DEFORM_AUTOSPRITE:
11267                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11268                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11269                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11270                         VectorNormalize(newforward);
11271                         VectorNormalize(newright);
11272                         VectorNormalize(newup);
11273 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11274 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11275 //                      rsurface.batchvertex3f_bufferoffset = 0;
11276 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11277 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
11278 //                      rsurface.batchsvector3f_bufferoffset = 0;
11279 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11280 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
11281 //                      rsurface.batchtvector3f_bufferoffset = 0;
11282 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11283 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11284 //                      rsurface.batchnormal3f_bufferoffset = 0;
11285                         // a single autosprite surface can contain multiple sprites...
11286                         for (j = 0;j < batchnumvertices - 3;j += 4)
11287                         {
11288                                 VectorClear(center);
11289                                 for (i = 0;i < 4;i++)
11290                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11291                                 VectorScale(center, 0.25f, center);
11292                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11293                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11294                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11295                                 for (i = 0;i < 4;i++)
11296                                 {
11297                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11298                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11299                                 }
11300                         }
11301                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11302                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11303                         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);
11304                         break;
11305                 case Q3DEFORM_AUTOSPRITE2:
11306                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11307                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11308                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11309                         VectorNormalize(newforward);
11310                         VectorNormalize(newright);
11311                         VectorNormalize(newup);
11312 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11313 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11314 //                      rsurface.batchvertex3f_bufferoffset = 0;
11315                         {
11316                                 const float *v1, *v2;
11317                                 vec3_t start, end;
11318                                 float f, l;
11319                                 struct
11320                                 {
11321                                         float length2;
11322                                         const float *v1;
11323                                         const float *v2;
11324                                 }
11325                                 shortest[2];
11326                                 memset(shortest, 0, sizeof(shortest));
11327                                 // a single autosprite surface can contain multiple sprites...
11328                                 for (j = 0;j < batchnumvertices - 3;j += 4)
11329                                 {
11330                                         VectorClear(center);
11331                                         for (i = 0;i < 4;i++)
11332                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11333                                         VectorScale(center, 0.25f, center);
11334                                         // find the two shortest edges, then use them to define the
11335                                         // axis vectors for rotating around the central axis
11336                                         for (i = 0;i < 6;i++)
11337                                         {
11338                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11339                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11340                                                 l = VectorDistance2(v1, v2);
11341                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11342                                                 if (v1[2] != v2[2])
11343                                                         l += (1.0f / 1024.0f);
11344                                                 if (shortest[0].length2 > l || i == 0)
11345                                                 {
11346                                                         shortest[1] = shortest[0];
11347                                                         shortest[0].length2 = l;
11348                                                         shortest[0].v1 = v1;
11349                                                         shortest[0].v2 = v2;
11350                                                 }
11351                                                 else if (shortest[1].length2 > l || i == 1)
11352                                                 {
11353                                                         shortest[1].length2 = l;
11354                                                         shortest[1].v1 = v1;
11355                                                         shortest[1].v2 = v2;
11356                                                 }
11357                                         }
11358                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11359                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11360                                         // this calculates the right vector from the shortest edge
11361                                         // and the up vector from the edge midpoints
11362                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11363                                         VectorNormalize(right);
11364                                         VectorSubtract(end, start, up);
11365                                         VectorNormalize(up);
11366                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11367                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11368                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11369                                         VectorNegate(forward, forward);
11370                                         VectorReflect(forward, 0, up, forward);
11371                                         VectorNormalize(forward);
11372                                         CrossProduct(up, forward, newright);
11373                                         VectorNormalize(newright);
11374                                         // rotate the quad around the up axis vector, this is made
11375                                         // especially easy by the fact we know the quad is flat,
11376                                         // so we only have to subtract the center position and
11377                                         // measure distance along the right vector, and then
11378                                         // multiply that by the newright vector and add back the
11379                                         // center position
11380                                         // we also need to subtract the old position to undo the
11381                                         // displacement from the center, which we do with a
11382                                         // DotProduct, the subtraction/addition of center is also
11383                                         // optimized into DotProducts here
11384                                         l = DotProduct(right, center);
11385                                         for (i = 0;i < 4;i++)
11386                                         {
11387                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11388                                                 f = DotProduct(right, v1) - l;
11389                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11390                                         }
11391                                 }
11392                         }
11393                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11394                         {
11395 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11396 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
11397 //                              rsurface.batchnormal3f_bufferoffset = 0;
11398                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11399                         }
11400                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11401                         {
11402 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11403 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11404 //                              rsurface.batchsvector3f_bufferoffset = 0;
11405 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11406 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11407 //                              rsurface.batchtvector3f_bufferoffset = 0;
11408                                 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);
11409                         }
11410                         break;
11411                 case Q3DEFORM_NORMAL:
11412                         // deform the normals to make reflections wavey
11413                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11414                         rsurface.batchnormal3f_vertexbuffer = NULL;
11415                         rsurface.batchnormal3f_bufferoffset = 0;
11416                         for (j = 0;j < batchnumvertices;j++)
11417                         {
11418                                 float vertex[3];
11419                                 float *normal = rsurface.batchnormal3f + 3*j;
11420                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11421                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11422                                 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]);
11423                                 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]);
11424                                 VectorNormalize(normal);
11425                         }
11426                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11427                         {
11428 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11429 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11430 //                              rsurface.batchsvector3f_bufferoffset = 0;
11431 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11432 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11433 //                              rsurface.batchtvector3f_bufferoffset = 0;
11434                                 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);
11435                         }
11436                         break;
11437                 case Q3DEFORM_WAVE:
11438                         // deform vertex array to make wavey water and flags and such
11439                         waveparms[0] = deform->waveparms[0];
11440                         waveparms[1] = deform->waveparms[1];
11441                         waveparms[2] = deform->waveparms[2];
11442                         waveparms[3] = deform->waveparms[3];
11443                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11444                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11445                         // this is how a divisor of vertex influence on deformation
11446                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11447                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11448 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11449 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11450 //                      rsurface.batchvertex3f_bufferoffset = 0;
11451 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11452 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11453 //                      rsurface.batchnormal3f_bufferoffset = 0;
11454                         for (j = 0;j < batchnumvertices;j++)
11455                         {
11456                                 // if the wavefunc depends on time, evaluate it per-vertex
11457                                 if (waveparms[3])
11458                                 {
11459                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11460                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11461                                 }
11462                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11463                         }
11464                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11465                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11466                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11467                         {
11468 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11469 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11470 //                              rsurface.batchsvector3f_bufferoffset = 0;
11471 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11472 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11473 //                              rsurface.batchtvector3f_bufferoffset = 0;
11474                                 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);
11475                         }
11476                         break;
11477                 case Q3DEFORM_BULGE:
11478                         // deform vertex array to make the surface have moving bulges
11479 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11480 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11481 //                      rsurface.batchvertex3f_bufferoffset = 0;
11482 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11483 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11484 //                      rsurface.batchnormal3f_bufferoffset = 0;
11485                         for (j = 0;j < batchnumvertices;j++)
11486                         {
11487                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11488                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11489                         }
11490                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11491                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11492                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11493                         {
11494 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11495 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11496 //                              rsurface.batchsvector3f_bufferoffset = 0;
11497 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11498 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11499 //                              rsurface.batchtvector3f_bufferoffset = 0;
11500                                 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);
11501                         }
11502                         break;
11503                 case Q3DEFORM_MOVE:
11504                         // deform vertex array
11505                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11506                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11507                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11508                         VectorScale(deform->parms, scale, waveparms);
11509 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11510 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11511 //                      rsurface.batchvertex3f_bufferoffset = 0;
11512                         for (j = 0;j < batchnumvertices;j++)
11513                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11514                         break;
11515                 }
11516         }
11517
11518         // generate texcoords based on the chosen texcoord source
11519         switch(rsurface.texture->tcgen.tcgen)
11520         {
11521         default:
11522         case Q3TCGEN_TEXTURE:
11523                 break;
11524         case Q3TCGEN_LIGHTMAP:
11525 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11526 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11527 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11528                 if (rsurface.batchtexcoordlightmap2f)
11529                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11530                 break;
11531         case Q3TCGEN_VECTOR:
11532 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11533 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11534 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11535                 for (j = 0;j < batchnumvertices;j++)
11536                 {
11537                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11538                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11539                 }
11540                 break;
11541         case Q3TCGEN_ENVIRONMENT:
11542                 // make environment reflections using a spheremap
11543                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11544                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11545                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11546                 for (j = 0;j < batchnumvertices;j++)
11547                 {
11548                         // identical to Q3A's method, but executed in worldspace so
11549                         // carried models can be shiny too
11550
11551                         float viewer[3], d, reflected[3], worldreflected[3];
11552
11553                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11554                         // VectorNormalize(viewer);
11555
11556                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11557
11558                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11559                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11560                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11561                         // note: this is proportinal to viewer, so we can normalize later
11562
11563                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11564                         VectorNormalize(worldreflected);
11565
11566                         // note: this sphere map only uses world x and z!
11567                         // so positive and negative y will LOOK THE SAME.
11568                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11569                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11570                 }
11571                 break;
11572         }
11573         // the only tcmod that needs software vertex processing is turbulent, so
11574         // check for it here and apply the changes if needed
11575         // and we only support that as the first one
11576         // (handling a mixture of turbulent and other tcmods would be problematic
11577         //  without punting it entirely to a software path)
11578         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11579         {
11580                 amplitude = rsurface.texture->tcmods[0].parms[1];
11581                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11582 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11583 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11584 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11585                 for (j = 0;j < batchnumvertices;j++)
11586                 {
11587                         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);
11588                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11589                 }
11590         }
11591
11592         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11593         {
11594                 // convert the modified arrays to vertex structs
11595 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11596 //              rsurface.batchvertexmeshbuffer = NULL;
11597                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11598                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11599                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11600                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11601                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11602                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11603                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11604                 {
11605                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11606                         {
11607                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11608                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11609                         }
11610                 }
11611                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11612                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11613                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11614                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11615                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11616                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11617                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11618                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11619                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11620         }
11621 }
11622
11623 void RSurf_DrawBatch(void)
11624 {
11625         // sometimes a zero triangle surface (usually a degenerate patch) makes it
11626         // through the pipeline, killing it earlier in the pipeline would have
11627         // per-surface overhead rather than per-batch overhead, so it's best to
11628         // reject it here, before it hits glDraw.
11629         if (rsurface.batchnumtriangles == 0)
11630                 return;
11631 #if 0
11632         // batch debugging code
11633         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11634         {
11635                 int i;
11636                 int j;
11637                 int c;
11638                 const int *e;
11639                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11640                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11641                 {
11642                         c = e[i];
11643                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11644                         {
11645                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11646                                 {
11647                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11648                                                 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);
11649                                         break;
11650                                 }
11651                         }
11652                 }
11653         }
11654 #endif
11655         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);
11656 }
11657
11658 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11659 {
11660         // pick the closest matching water plane
11661         int planeindex, vertexindex, bestplaneindex = -1;
11662         float d, bestd;
11663         vec3_t vert;
11664         const float *v;
11665         r_waterstate_waterplane_t *p;
11666         qboolean prepared = false;
11667         bestd = 0;
11668         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11669         {
11670                 if(p->camera_entity != rsurface.texture->camera_entity)
11671                         continue;
11672                 d = 0;
11673                 if(!prepared)
11674                 {
11675                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11676                         prepared = true;
11677                         if(rsurface.batchnumvertices == 0)
11678                                 break;
11679                 }
11680                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11681                 {
11682                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11683                         d += fabs(PlaneDiff(vert, &p->plane));
11684                 }
11685                 if (bestd > d || bestplaneindex < 0)
11686                 {
11687                         bestd = d;
11688                         bestplaneindex = planeindex;
11689                 }
11690         }
11691         return bestplaneindex;
11692         // NOTE: this MAY return a totally unrelated water plane; we can ignore
11693         // this situation though, as it might be better to render single larger
11694         // batches with useless stuff (backface culled for example) than to
11695         // render multiple smaller batches
11696 }
11697
11698 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11699 {
11700         int i;
11701         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11702         rsurface.passcolor4f_vertexbuffer = 0;
11703         rsurface.passcolor4f_bufferoffset = 0;
11704         for (i = 0;i < rsurface.batchnumvertices;i++)
11705                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11706 }
11707
11708 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11709 {
11710         int i;
11711         float f;
11712         const float *v;
11713         const float *c;
11714         float *c2;
11715         if (rsurface.passcolor4f)
11716         {
11717                 // generate color arrays
11718                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11719                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11720                 rsurface.passcolor4f_vertexbuffer = 0;
11721                 rsurface.passcolor4f_bufferoffset = 0;
11722                 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)
11723                 {
11724                         f = RSurf_FogVertex(v);
11725                         c2[0] = c[0] * f;
11726                         c2[1] = c[1] * f;
11727                         c2[2] = c[2] * f;
11728                         c2[3] = c[3];
11729                 }
11730         }
11731         else
11732         {
11733                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11734                 rsurface.passcolor4f_vertexbuffer = 0;
11735                 rsurface.passcolor4f_bufferoffset = 0;
11736                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11737                 {
11738                         f = RSurf_FogVertex(v);
11739                         c2[0] = f;
11740                         c2[1] = f;
11741                         c2[2] = f;
11742                         c2[3] = 1;
11743                 }
11744         }
11745 }
11746
11747 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11748 {
11749         int i;
11750         float f;
11751         const float *v;
11752         const float *c;
11753         float *c2;
11754         if (!rsurface.passcolor4f)
11755                 return;
11756         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11757         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11758         rsurface.passcolor4f_vertexbuffer = 0;
11759         rsurface.passcolor4f_bufferoffset = 0;
11760         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)
11761         {
11762                 f = RSurf_FogVertex(v);
11763                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11764                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11765                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11766                 c2[3] = c[3];
11767         }
11768 }
11769
11770 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11771 {
11772         int i;
11773         const float *c;
11774         float *c2;
11775         if (!rsurface.passcolor4f)
11776                 return;
11777         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11778         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11779         rsurface.passcolor4f_vertexbuffer = 0;
11780         rsurface.passcolor4f_bufferoffset = 0;
11781         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11782         {
11783                 c2[0] = c[0] * r;
11784                 c2[1] = c[1] * g;
11785                 c2[2] = c[2] * b;
11786                 c2[3] = c[3] * a;
11787         }
11788 }
11789
11790 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11791 {
11792         int i;
11793         const float *c;
11794         float *c2;
11795         if (!rsurface.passcolor4f)
11796                 return;
11797         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11798         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11799         rsurface.passcolor4f_vertexbuffer = 0;
11800         rsurface.passcolor4f_bufferoffset = 0;
11801         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11802         {
11803                 c2[0] = c[0] + r_refdef.scene.ambient;
11804                 c2[1] = c[1] + r_refdef.scene.ambient;
11805                 c2[2] = c[2] + r_refdef.scene.ambient;
11806                 c2[3] = c[3];
11807         }
11808 }
11809
11810 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11811 {
11812         // TODO: optimize
11813         rsurface.passcolor4f = NULL;
11814         rsurface.passcolor4f_vertexbuffer = 0;
11815         rsurface.passcolor4f_bufferoffset = 0;
11816         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11817         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11818         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11819         GL_Color(r, g, b, a);
11820         R_Mesh_TexBind(0, rsurface.lightmaptexture);
11821         RSurf_DrawBatch();
11822 }
11823
11824 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11825 {
11826         // TODO: optimize applyfog && applycolor case
11827         // just apply fog if necessary, and tint the fog color array if necessary
11828         rsurface.passcolor4f = NULL;
11829         rsurface.passcolor4f_vertexbuffer = 0;
11830         rsurface.passcolor4f_bufferoffset = 0;
11831         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11832         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11833         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11834         GL_Color(r, g, b, a);
11835         RSurf_DrawBatch();
11836 }
11837
11838 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11839 {
11840         // TODO: optimize
11841         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11842         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11843         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11844         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11845         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11846         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11847         GL_Color(r, g, b, a);
11848         RSurf_DrawBatch();
11849 }
11850
11851 static void RSurf_DrawBatch_GL11_ClampColor(void)
11852 {
11853         int i;
11854         const float *c1;
11855         float *c2;
11856         if (!rsurface.passcolor4f)
11857                 return;
11858         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11859         {
11860                 c2[0] = bound(0.0f, c1[0], 1.0f);
11861                 c2[1] = bound(0.0f, c1[1], 1.0f);
11862                 c2[2] = bound(0.0f, c1[2], 1.0f);
11863                 c2[3] = bound(0.0f, c1[3], 1.0f);
11864         }
11865 }
11866
11867 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11868 {
11869         int i;
11870         float f;
11871         const float *v;
11872         const float *n;
11873         float *c;
11874         //vec3_t eyedir;
11875
11876         // fake shading
11877         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11878         rsurface.passcolor4f_vertexbuffer = 0;
11879         rsurface.passcolor4f_bufferoffset = 0;
11880         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)
11881         {
11882                 f = -DotProduct(r_refdef.view.forward, n);
11883                 f = max(0, f);
11884                 f = f * 0.85 + 0.15; // work around so stuff won't get black
11885                 f *= r_refdef.lightmapintensity;
11886                 Vector4Set(c, f, f, f, 1);
11887         }
11888 }
11889
11890 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11891 {
11892         RSurf_DrawBatch_GL11_ApplyFakeLight();
11893         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11894         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11895         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11896         GL_Color(r, g, b, a);
11897         RSurf_DrawBatch();
11898 }
11899
11900 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11901 {
11902         int i;
11903         float f;
11904         float alpha;
11905         const float *v;
11906         const float *n;
11907         float *c;
11908         vec3_t ambientcolor;
11909         vec3_t diffusecolor;
11910         vec3_t lightdir;
11911         // TODO: optimize
11912         // model lighting
11913         VectorCopy(rsurface.modellight_lightdir, lightdir);
11914         f = 0.5f * r_refdef.lightmapintensity;
11915         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
11916         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
11917         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
11918         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
11919         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
11920         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
11921         alpha = *a;
11922         if (VectorLength2(diffusecolor) > 0)
11923         {
11924                 // q3-style directional shading
11925                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11926                 rsurface.passcolor4f_vertexbuffer = 0;
11927                 rsurface.passcolor4f_bufferoffset = 0;
11928                 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)
11929                 {
11930                         if ((f = DotProduct(n, lightdir)) > 0)
11931                                 VectorMA(ambientcolor, f, diffusecolor, c);
11932                         else
11933                                 VectorCopy(ambientcolor, c);
11934                         c[3] = alpha;
11935                 }
11936                 *r = 1;
11937                 *g = 1;
11938                 *b = 1;
11939                 *a = 1;
11940                 *applycolor = false;
11941         }
11942         else
11943         {
11944                 *r = ambientcolor[0];
11945                 *g = ambientcolor[1];
11946                 *b = ambientcolor[2];
11947                 rsurface.passcolor4f = NULL;
11948                 rsurface.passcolor4f_vertexbuffer = 0;
11949                 rsurface.passcolor4f_bufferoffset = 0;
11950         }
11951 }
11952
11953 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11954 {
11955         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
11956         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11957         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11958         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11959         GL_Color(r, g, b, a);
11960         RSurf_DrawBatch();
11961 }
11962
11963 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
11964 {
11965         int i;
11966         float f;
11967         const float *v;
11968         float *c;
11969         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
11970         {
11971                 f = 1 - RSurf_FogVertex(v);
11972                 c[0] = r;
11973                 c[1] = g;
11974                 c[2] = b;
11975                 c[3] = f * a;
11976         }
11977 }
11978
11979 void RSurf_SetupDepthAndCulling(void)
11980 {
11981         // submodels are biased to avoid z-fighting with world surfaces that they
11982         // may be exactly overlapping (avoids z-fighting artifacts on certain
11983         // doors and things in Quake maps)
11984         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
11985         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
11986         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
11987         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11988 }
11989
11990 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11991 {
11992         // transparent sky would be ridiculous
11993         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11994                 return;
11995         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
11996         skyrenderlater = true;
11997         RSurf_SetupDepthAndCulling();
11998         GL_DepthMask(true);
11999         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12000         // skymasking on them, and Quake3 never did sky masking (unlike
12001         // software Quake and software Quake2), so disable the sky masking
12002         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12003         // and skymasking also looks very bad when noclipping outside the
12004         // level, so don't use it then either.
12005         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12006         {
12007                 R_Mesh_ResetTextureState();
12008                 if (skyrendermasked)
12009                 {
12010                         R_SetupShader_DepthOrShadow();
12011                         // depth-only (masking)
12012                         GL_ColorMask(0,0,0,0);
12013                         // just to make sure that braindead drivers don't draw
12014                         // anything despite that colormask...
12015                         GL_BlendFunc(GL_ZERO, GL_ONE);
12016                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12017                         if (rsurface.batchvertex3fbuffer)
12018                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12019                         else
12020                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12021                 }
12022                 else
12023                 {
12024                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12025                         // fog sky
12026                         GL_BlendFunc(GL_ONE, GL_ZERO);
12027                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12028                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12029                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12030                 }
12031                 RSurf_DrawBatch();
12032                 if (skyrendermasked)
12033                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12034         }
12035         R_Mesh_ResetTextureState();
12036         GL_Color(1, 1, 1, 1);
12037 }
12038
12039 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12040 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12041 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12042 {
12043         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12044                 return;
12045         if (prepass)
12046         {
12047                 // render screenspace normalmap to texture
12048                 GL_DepthMask(true);
12049                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12050                 RSurf_DrawBatch();
12051                 return;
12052         }
12053
12054         // bind lightmap texture
12055
12056         // water/refraction/reflection/camera surfaces have to be handled specially
12057         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12058         {
12059                 int start, end, startplaneindex;
12060                 for (start = 0;start < texturenumsurfaces;start = end)
12061                 {
12062                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12063                         if(startplaneindex < 0)
12064                         {
12065                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12066                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12067                                 end = start + 1;
12068                                 continue;
12069                         }
12070                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12071                                 ;
12072                         // now that we have a batch using the same planeindex, render it
12073                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12074                         {
12075                                 // render water or distortion background
12076                                 GL_DepthMask(true);
12077                                 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));
12078                                 RSurf_DrawBatch();
12079                                 // blend surface on top
12080                                 GL_DepthMask(false);
12081                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12082                                 RSurf_DrawBatch();
12083                         }
12084                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12085                         {
12086                                 // render surface with reflection texture as input
12087                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12088                                 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));
12089                                 RSurf_DrawBatch();
12090                         }
12091                 }
12092                 return;
12093         }
12094
12095         // render surface batch normally
12096         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12097         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12098         RSurf_DrawBatch();
12099 }
12100
12101 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12102 {
12103         // OpenGL 1.3 path - anything not completely ancient
12104         qboolean applycolor;
12105         qboolean applyfog;
12106         int layerindex;
12107         const texturelayer_t *layer;
12108         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);
12109         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12110
12111         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12112         {
12113                 vec4_t layercolor;
12114                 int layertexrgbscale;
12115                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12116                 {
12117                         if (layerindex == 0)
12118                                 GL_AlphaTest(true);
12119                         else
12120                         {
12121                                 GL_AlphaTest(false);
12122                                 GL_DepthFunc(GL_EQUAL);
12123                         }
12124                 }
12125                 GL_DepthMask(layer->depthmask && writedepth);
12126                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12127                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12128                 {
12129                         layertexrgbscale = 4;
12130                         VectorScale(layer->color, 0.25f, layercolor);
12131                 }
12132                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12133                 {
12134                         layertexrgbscale = 2;
12135                         VectorScale(layer->color, 0.5f, layercolor);
12136                 }
12137                 else
12138                 {
12139                         layertexrgbscale = 1;
12140                         VectorScale(layer->color, 1.0f, layercolor);
12141                 }
12142                 layercolor[3] = layer->color[3];
12143                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12144                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12145                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12146                 switch (layer->type)
12147                 {
12148                 case TEXTURELAYERTYPE_LITTEXTURE:
12149                         // single-pass lightmapped texture with 2x rgbscale
12150                         R_Mesh_TexBind(0, r_texture_white);
12151                         R_Mesh_TexMatrix(0, NULL);
12152                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12153                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12154                         R_Mesh_TexBind(1, layer->texture);
12155                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12156                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12157                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12158                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12159                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12160                         else if (FAKELIGHT_ENABLED)
12161                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12162                         else if (rsurface.uselightmaptexture)
12163                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12164                         else
12165                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12166                         break;
12167                 case TEXTURELAYERTYPE_TEXTURE:
12168                         // singletexture unlit texture with transparency support
12169                         R_Mesh_TexBind(0, layer->texture);
12170                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12171                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12172                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12173                         R_Mesh_TexBind(1, 0);
12174                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12175                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12176                         break;
12177                 case TEXTURELAYERTYPE_FOG:
12178                         // singletexture fogging
12179                         if (layer->texture)
12180                         {
12181                                 R_Mesh_TexBind(0, layer->texture);
12182                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12183                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12184                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12185                         }
12186                         else
12187                         {
12188                                 R_Mesh_TexBind(0, 0);
12189                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12190                         }
12191                         R_Mesh_TexBind(1, 0);
12192                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12193                         // generate a color array for the fog pass
12194                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12195                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12196                         RSurf_DrawBatch();
12197                         break;
12198                 default:
12199                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12200                 }
12201         }
12202         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12203         {
12204                 GL_DepthFunc(GL_LEQUAL);
12205                 GL_AlphaTest(false);
12206         }
12207 }
12208
12209 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12210 {
12211         // OpenGL 1.1 - crusty old voodoo path
12212         qboolean applyfog;
12213         int layerindex;
12214         const texturelayer_t *layer;
12215         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);
12216         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12217
12218         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12219         {
12220                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12221                 {
12222                         if (layerindex == 0)
12223                                 GL_AlphaTest(true);
12224                         else
12225                         {
12226                                 GL_AlphaTest(false);
12227                                 GL_DepthFunc(GL_EQUAL);
12228                         }
12229                 }
12230                 GL_DepthMask(layer->depthmask && writedepth);
12231                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12232                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12233                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12234                 switch (layer->type)
12235                 {
12236                 case TEXTURELAYERTYPE_LITTEXTURE:
12237                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12238                         {
12239                                 // two-pass lit texture with 2x rgbscale
12240                                 // first the lightmap pass
12241                                 R_Mesh_TexBind(0, r_texture_white);
12242                                 R_Mesh_TexMatrix(0, NULL);
12243                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12244                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12245                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12246                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12247                                 else if (FAKELIGHT_ENABLED)
12248                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12249                                 else if (rsurface.uselightmaptexture)
12250                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12251                                 else
12252                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12253                                 // then apply the texture to it
12254                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12255                                 R_Mesh_TexBind(0, layer->texture);
12256                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12257                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12258                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12259                                 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);
12260                         }
12261                         else
12262                         {
12263                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12264                                 R_Mesh_TexBind(0, layer->texture);
12265                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12266                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12267                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12268                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12269                                         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);
12270                                 else
12271                                         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);
12272                         }
12273                         break;
12274                 case TEXTURELAYERTYPE_TEXTURE:
12275                         // singletexture unlit texture with transparency support
12276                         R_Mesh_TexBind(0, layer->texture);
12277                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12278                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12279                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12280                         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);
12281                         break;
12282                 case TEXTURELAYERTYPE_FOG:
12283                         // singletexture fogging
12284                         if (layer->texture)
12285                         {
12286                                 R_Mesh_TexBind(0, layer->texture);
12287                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12288                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12289                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12290                         }
12291                         else
12292                         {
12293                                 R_Mesh_TexBind(0, 0);
12294                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12295                         }
12296                         // generate a color array for the fog pass
12297                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12298                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12299                         RSurf_DrawBatch();
12300                         break;
12301                 default:
12302                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12303                 }
12304         }
12305         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12306         {
12307                 GL_DepthFunc(GL_LEQUAL);
12308                 GL_AlphaTest(false);
12309         }
12310 }
12311
12312 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12313 {
12314         int vi;
12315         int j;
12316         r_vertexgeneric_t *batchvertex;
12317         float c[4];
12318
12319 //      R_Mesh_ResetTextureState();
12320         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12321
12322         if(rsurface.texture && rsurface.texture->currentskinframe)
12323         {
12324                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12325                 c[3] *= rsurface.texture->currentalpha;
12326         }
12327         else
12328         {
12329                 c[0] = 1;
12330                 c[1] = 0;
12331                 c[2] = 1;
12332                 c[3] = 1;
12333         }
12334
12335         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12336         {
12337                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12338                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12339                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12340         }
12341
12342         // brighten it up (as texture value 127 means "unlit")
12343         c[0] *= 2 * r_refdef.view.colorscale;
12344         c[1] *= 2 * r_refdef.view.colorscale;
12345         c[2] *= 2 * r_refdef.view.colorscale;
12346
12347         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12348                 c[3] *= r_wateralpha.value;
12349
12350         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12351         {
12352                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12353                 GL_DepthMask(false);
12354         }
12355         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12356         {
12357                 GL_BlendFunc(GL_ONE, GL_ONE);
12358                 GL_DepthMask(false);
12359         }
12360         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12361         {
12362                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12363                 GL_DepthMask(false);
12364         }
12365         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12366         {
12367                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12368                 GL_DepthMask(false);
12369         }
12370         else
12371         {
12372                 GL_BlendFunc(GL_ONE, GL_ZERO);
12373                 GL_DepthMask(writedepth);
12374         }
12375
12376         if (r_showsurfaces.integer == 3)
12377         {
12378                 rsurface.passcolor4f = NULL;
12379
12380                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12381                 {
12382                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12383
12384                         rsurface.passcolor4f = NULL;
12385                         rsurface.passcolor4f_vertexbuffer = 0;
12386                         rsurface.passcolor4f_bufferoffset = 0;
12387                 }
12388                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12389                 {
12390                         qboolean applycolor = true;
12391                         float one = 1.0;
12392
12393                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12394
12395                         r_refdef.lightmapintensity = 1;
12396                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12397                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12398                 }
12399                 else if (FAKELIGHT_ENABLED)
12400                 {
12401                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12402
12403                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12404                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12405                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12406                 }
12407                 else
12408                 {
12409                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12410
12411                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12412                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12413                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12414                 }
12415
12416                 if(!rsurface.passcolor4f)
12417                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12418
12419                 RSurf_DrawBatch_GL11_ApplyAmbient();
12420                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12421                 if(r_refdef.fogenabled)
12422                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12423                 RSurf_DrawBatch_GL11_ClampColor();
12424
12425                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12426                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12427                 RSurf_DrawBatch();
12428         }
12429         else if (!r_refdef.view.showdebug)
12430         {
12431                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12432                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12433                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12434                 {
12435                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12436                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12437                 }
12438                 R_Mesh_PrepareVertices_Generic_Unlock();
12439                 RSurf_DrawBatch();
12440         }
12441         else if (r_showsurfaces.integer == 4)
12442         {
12443                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12444                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12445                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12446                 {
12447                         unsigned char c = vi << 3;
12448                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12449                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12450                 }
12451                 R_Mesh_PrepareVertices_Generic_Unlock();
12452                 RSurf_DrawBatch();
12453         }
12454         else if (r_showsurfaces.integer == 2)
12455         {
12456                 const int *e;
12457                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12458                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12459                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12460                 {
12461                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12462                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12463                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12464                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12465                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12466                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12467                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12468                 }
12469                 R_Mesh_PrepareVertices_Generic_Unlock();
12470                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12471         }
12472         else
12473         {
12474                 int texturesurfaceindex;
12475                 int k;
12476                 const msurface_t *surface;
12477                 unsigned char surfacecolor4ub[4];
12478                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12479                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12480                 vi = 0;
12481                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12482                 {
12483                         surface = texturesurfacelist[texturesurfaceindex];
12484                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12485                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12486                         for (j = 0;j < surface->num_vertices;j++)
12487                         {
12488                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12489                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12490                                 vi++;
12491                         }
12492                 }
12493                 R_Mesh_PrepareVertices_Generic_Unlock();
12494                 RSurf_DrawBatch();
12495         }
12496 }
12497
12498 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12499 {
12500         CHECKGLERROR
12501         RSurf_SetupDepthAndCulling();
12502         if (r_showsurfaces.integer)
12503         {
12504                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12505                 return;
12506         }
12507         switch (vid.renderpath)
12508         {
12509         case RENDERPATH_GL20:
12510         case RENDERPATH_D3D9:
12511         case RENDERPATH_D3D10:
12512         case RENDERPATH_D3D11:
12513         case RENDERPATH_SOFT:
12514         case RENDERPATH_GLES2:
12515                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12516                 break;
12517         case RENDERPATH_GL13:
12518                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12519                 break;
12520         case RENDERPATH_GL11:
12521                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12522                 break;
12523         }
12524         CHECKGLERROR
12525 }
12526
12527 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12528 {
12529         CHECKGLERROR
12530         RSurf_SetupDepthAndCulling();
12531         if (r_showsurfaces.integer)
12532         {
12533                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12534                 return;
12535         }
12536         switch (vid.renderpath)
12537         {
12538         case RENDERPATH_GL20:
12539         case RENDERPATH_D3D9:
12540         case RENDERPATH_D3D10:
12541         case RENDERPATH_D3D11:
12542         case RENDERPATH_SOFT:
12543         case RENDERPATH_GLES2:
12544                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12545                 break;
12546         case RENDERPATH_GL13:
12547                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12548                 break;
12549         case RENDERPATH_GL11:
12550                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12551                 break;
12552         }
12553         CHECKGLERROR
12554 }
12555
12556 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12557 {
12558         int i, j;
12559         int texturenumsurfaces, endsurface;
12560         texture_t *texture;
12561         const msurface_t *surface;
12562 #define MAXBATCH_TRANSPARENTSURFACES 256
12563         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12564
12565         // if the model is static it doesn't matter what value we give for
12566         // wantnormals and wanttangents, so this logic uses only rules applicable
12567         // to a model, knowing that they are meaningless otherwise
12568         if (ent == r_refdef.scene.worldentity)
12569                 RSurf_ActiveWorldEntity();
12570         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12571                 RSurf_ActiveModelEntity(ent, false, false, false);
12572         else
12573         {
12574                 switch (vid.renderpath)
12575                 {
12576                 case RENDERPATH_GL20:
12577                 case RENDERPATH_D3D9:
12578                 case RENDERPATH_D3D10:
12579                 case RENDERPATH_D3D11:
12580                 case RENDERPATH_SOFT:
12581                 case RENDERPATH_GLES2:
12582                         RSurf_ActiveModelEntity(ent, true, true, false);
12583                         break;
12584                 case RENDERPATH_GL13:
12585                 case RENDERPATH_GL11:
12586                         RSurf_ActiveModelEntity(ent, true, false, false);
12587                         break;
12588                 }
12589         }
12590
12591         if (r_transparentdepthmasking.integer)
12592         {
12593                 qboolean setup = false;
12594                 for (i = 0;i < numsurfaces;i = j)
12595                 {
12596                         j = i + 1;
12597                         surface = rsurface.modelsurfaces + surfacelist[i];
12598                         texture = surface->texture;
12599                         rsurface.texture = R_GetCurrentTexture(texture);
12600                         rsurface.lightmaptexture = NULL;
12601                         rsurface.deluxemaptexture = NULL;
12602                         rsurface.uselightmaptexture = false;
12603                         // scan ahead until we find a different texture
12604                         endsurface = min(i + 1024, numsurfaces);
12605                         texturenumsurfaces = 0;
12606                         texturesurfacelist[texturenumsurfaces++] = surface;
12607                         for (;j < endsurface;j++)
12608                         {
12609                                 surface = rsurface.modelsurfaces + surfacelist[j];
12610                                 if (texture != surface->texture)
12611                                         break;
12612                                 texturesurfacelist[texturenumsurfaces++] = surface;
12613                         }
12614                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12615                                 continue;
12616                         // render the range of surfaces as depth
12617                         if (!setup)
12618                         {
12619                                 setup = true;
12620                                 GL_ColorMask(0,0,0,0);
12621                                 GL_Color(1,1,1,1);
12622                                 GL_DepthTest(true);
12623                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12624                                 GL_DepthMask(true);
12625 //                              R_Mesh_ResetTextureState();
12626                                 R_SetupShader_DepthOrShadow();
12627                         }
12628                         RSurf_SetupDepthAndCulling();
12629                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12630                         if (rsurface.batchvertex3fbuffer)
12631                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12632                         else
12633                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12634                         RSurf_DrawBatch();
12635                 }
12636                 if (setup)
12637                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12638         }
12639
12640         for (i = 0;i < numsurfaces;i = j)
12641         {
12642                 j = i + 1;
12643                 surface = rsurface.modelsurfaces + surfacelist[i];
12644                 texture = surface->texture;
12645                 rsurface.texture = R_GetCurrentTexture(texture);
12646                 // scan ahead until we find a different texture
12647                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12648                 texturenumsurfaces = 0;
12649                 texturesurfacelist[texturenumsurfaces++] = surface;
12650                 if(FAKELIGHT_ENABLED)
12651                 {
12652                         rsurface.lightmaptexture = NULL;
12653                         rsurface.deluxemaptexture = NULL;
12654                         rsurface.uselightmaptexture = false;
12655                         for (;j < endsurface;j++)
12656                         {
12657                                 surface = rsurface.modelsurfaces + surfacelist[j];
12658                                 if (texture != surface->texture)
12659                                         break;
12660                                 texturesurfacelist[texturenumsurfaces++] = surface;
12661                         }
12662                 }
12663                 else
12664                 {
12665                         rsurface.lightmaptexture = surface->lightmaptexture;
12666                         rsurface.deluxemaptexture = surface->deluxemaptexture;
12667                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12668                         for (;j < endsurface;j++)
12669                         {
12670                                 surface = rsurface.modelsurfaces + surfacelist[j];
12671                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12672                                         break;
12673                                 texturesurfacelist[texturenumsurfaces++] = surface;
12674                         }
12675                 }
12676                 // render the range of surfaces
12677                 if (ent == r_refdef.scene.worldentity)
12678                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12679                 else
12680                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12681         }
12682         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12683 }
12684
12685 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12686 {
12687         // transparent surfaces get pushed off into the transparent queue
12688         int surfacelistindex;
12689         const msurface_t *surface;
12690         vec3_t tempcenter, center;
12691         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12692         {
12693                 surface = texturesurfacelist[surfacelistindex];
12694                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12695                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12696                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12697                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12698                 if (queueentity->transparent_offset) // transparent offset
12699                 {
12700                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12701                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12702                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12703                 }
12704                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12705         }
12706 }
12707
12708 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12709 {
12710         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12711                 return;
12712         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12713                 return;
12714         RSurf_SetupDepthAndCulling();
12715         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12716         if (rsurface.batchvertex3fbuffer)
12717                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12718         else
12719                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12720         RSurf_DrawBatch();
12721 }
12722
12723 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12724 {
12725         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12726         CHECKGLERROR
12727         if (depthonly)
12728                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12729         else if (prepass)
12730         {
12731                 if (!rsurface.texture->currentnumlayers)
12732                         return;
12733                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12734                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12735                 else
12736                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12737         }
12738         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12739                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12740         else if (!rsurface.texture->currentnumlayers)
12741                 return;
12742         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12743         {
12744                 // in the deferred case, transparent surfaces were queued during prepass
12745                 if (!r_shadow_usingdeferredprepass)
12746                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12747         }
12748         else
12749         {
12750                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12751                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12752         }
12753         CHECKGLERROR
12754 }
12755
12756 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12757 {
12758         int i, j;
12759         texture_t *texture;
12760         R_FrameData_SetMark();
12761         // break the surface list down into batches by texture and use of lightmapping
12762         for (i = 0;i < numsurfaces;i = j)
12763         {
12764                 j = i + 1;
12765                 // texture is the base texture pointer, rsurface.texture is the
12766                 // current frame/skin the texture is directing us to use (for example
12767                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12768                 // use skin 1 instead)
12769                 texture = surfacelist[i]->texture;
12770                 rsurface.texture = R_GetCurrentTexture(texture);
12771                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12772                 {
12773                         // if this texture is not the kind we want, skip ahead to the next one
12774                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12775                                 ;
12776                         continue;
12777                 }
12778                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12779                 {
12780                         rsurface.lightmaptexture = NULL;
12781                         rsurface.deluxemaptexture = NULL;
12782                         rsurface.uselightmaptexture = false;
12783                         // simply scan ahead until we find a different texture or lightmap state
12784                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12785                                 ;
12786                 }
12787                 else
12788                 {
12789                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12790                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12791                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12792                         // simply scan ahead until we find a different texture or lightmap state
12793                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12794                                 ;
12795                 }
12796                 // render the range of surfaces
12797                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12798         }
12799         R_FrameData_ReturnToMark();
12800 }
12801
12802 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12803 {
12804         CHECKGLERROR
12805         if (depthonly)
12806                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12807         else if (prepass)
12808         {
12809                 if (!rsurface.texture->currentnumlayers)
12810                         return;
12811                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12812                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12813                 else
12814                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12815         }
12816         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12817                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12818         else if (!rsurface.texture->currentnumlayers)
12819                 return;
12820         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12821         {
12822                 // in the deferred case, transparent surfaces were queued during prepass
12823                 if (!r_shadow_usingdeferredprepass)
12824                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12825         }
12826         else
12827         {
12828                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12829                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12830         }
12831         CHECKGLERROR
12832 }
12833
12834 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12835 {
12836         int i, j;
12837         texture_t *texture;
12838         R_FrameData_SetMark();
12839         // break the surface list down into batches by texture and use of lightmapping
12840         for (i = 0;i < numsurfaces;i = j)
12841         {
12842                 j = i + 1;
12843                 // texture is the base texture pointer, rsurface.texture is the
12844                 // current frame/skin the texture is directing us to use (for example
12845                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12846                 // use skin 1 instead)
12847                 texture = surfacelist[i]->texture;
12848                 rsurface.texture = R_GetCurrentTexture(texture);
12849                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12850                 {
12851                         // if this texture is not the kind we want, skip ahead to the next one
12852                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12853                                 ;
12854                         continue;
12855                 }
12856                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12857                 {
12858                         rsurface.lightmaptexture = NULL;
12859                         rsurface.deluxemaptexture = NULL;
12860                         rsurface.uselightmaptexture = false;
12861                         // simply scan ahead until we find a different texture or lightmap state
12862                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12863                                 ;
12864                 }
12865                 else
12866                 {
12867                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12868                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12869                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12870                         // simply scan ahead until we find a different texture or lightmap state
12871                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12872                                 ;
12873                 }
12874                 // render the range of surfaces
12875                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12876         }
12877         R_FrameData_ReturnToMark();
12878 }
12879
12880 float locboxvertex3f[6*4*3] =
12881 {
12882         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12883         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12884         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12885         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12886         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12887         1,0,0, 0,0,0, 0,1,0, 1,1,0
12888 };
12889
12890 unsigned short locboxelements[6*2*3] =
12891 {
12892          0, 1, 2, 0, 2, 3,
12893          4, 5, 6, 4, 6, 7,
12894          8, 9,10, 8,10,11,
12895         12,13,14, 12,14,15,
12896         16,17,18, 16,18,19,
12897         20,21,22, 20,22,23
12898 };
12899
12900 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12901 {
12902         int i, j;
12903         cl_locnode_t *loc = (cl_locnode_t *)ent;
12904         vec3_t mins, size;
12905         float vertex3f[6*4*3];
12906         CHECKGLERROR
12907         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12908         GL_DepthMask(false);
12909         GL_DepthRange(0, 1);
12910         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12911         GL_DepthTest(true);
12912         GL_CullFace(GL_NONE);
12913         R_EntityMatrix(&identitymatrix);
12914
12915 //      R_Mesh_ResetTextureState();
12916
12917         i = surfacelist[0];
12918         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12919                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12920                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
12921                         surfacelist[0] < 0 ? 0.5f : 0.125f);
12922
12923         if (VectorCompare(loc->mins, loc->maxs))
12924         {
12925                 VectorSet(size, 2, 2, 2);
12926                 VectorMA(loc->mins, -0.5f, size, mins);
12927         }
12928         else
12929         {
12930                 VectorCopy(loc->mins, mins);
12931                 VectorSubtract(loc->maxs, loc->mins, size);
12932         }
12933
12934         for (i = 0;i < 6*4*3;)
12935                 for (j = 0;j < 3;j++, i++)
12936                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
12937
12938         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
12939         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12940         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
12941 }
12942
12943 void R_DrawLocs(void)
12944 {
12945         int index;
12946         cl_locnode_t *loc, *nearestloc;
12947         vec3_t center;
12948         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
12949         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
12950         {
12951                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
12952                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
12953         }
12954 }
12955
12956 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
12957 {
12958         if (decalsystem->decals)
12959                 Mem_Free(decalsystem->decals);
12960         memset(decalsystem, 0, sizeof(*decalsystem));
12961 }
12962
12963 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)
12964 {
12965         tridecal_t *decal;
12966         tridecal_t *decals;
12967         int i;
12968
12969         // expand or initialize the system
12970         if (decalsystem->maxdecals <= decalsystem->numdecals)
12971         {
12972                 decalsystem_t old = *decalsystem;
12973                 qboolean useshortelements;
12974                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
12975                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
12976                 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)));
12977                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
12978                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
12979                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
12980                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
12981                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
12982                 if (decalsystem->numdecals)
12983                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
12984                 if (old.decals)
12985                         Mem_Free(old.decals);
12986                 for (i = 0;i < decalsystem->maxdecals*3;i++)
12987                         decalsystem->element3i[i] = i;
12988                 if (useshortelements)
12989                         for (i = 0;i < decalsystem->maxdecals*3;i++)
12990                                 decalsystem->element3s[i] = i;
12991         }
12992
12993         // grab a decal and search for another free slot for the next one
12994         decals = decalsystem->decals;
12995         decal = decalsystem->decals + (i = decalsystem->freedecal++);
12996         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
12997                 ;
12998         decalsystem->freedecal = i;
12999         if (decalsystem->numdecals <= i)
13000                 decalsystem->numdecals = i + 1;
13001
13002         // initialize the decal
13003         decal->lived = 0;
13004         decal->triangleindex = triangleindex;
13005         decal->surfaceindex = surfaceindex;
13006         decal->decalsequence = decalsequence;
13007         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13008         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13009         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13010         decal->color4ub[0][3] = 255;
13011         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13012         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13013         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13014         decal->color4ub[1][3] = 255;
13015         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13016         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13017         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13018         decal->color4ub[2][3] = 255;
13019         decal->vertex3f[0][0] = v0[0];
13020         decal->vertex3f[0][1] = v0[1];
13021         decal->vertex3f[0][2] = v0[2];
13022         decal->vertex3f[1][0] = v1[0];
13023         decal->vertex3f[1][1] = v1[1];
13024         decal->vertex3f[1][2] = v1[2];
13025         decal->vertex3f[2][0] = v2[0];
13026         decal->vertex3f[2][1] = v2[1];
13027         decal->vertex3f[2][2] = v2[2];
13028         decal->texcoord2f[0][0] = t0[0];
13029         decal->texcoord2f[0][1] = t0[1];
13030         decal->texcoord2f[1][0] = t1[0];
13031         decal->texcoord2f[1][1] = t1[1];
13032         decal->texcoord2f[2][0] = t2[0];
13033         decal->texcoord2f[2][1] = t2[1];
13034 }
13035
13036 extern cvar_t cl_decals_bias;
13037 extern cvar_t cl_decals_models;
13038 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13039 // baseparms, parms, temps
13040 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)
13041 {
13042         int cornerindex;
13043         int index;
13044         float v[9][3];
13045         const float *vertex3f;
13046         int numpoints;
13047         float points[2][9][3];
13048         float temp[3];
13049         float tc[9][2];
13050         float f;
13051         float c[9][4];
13052         const int *e;
13053
13054         e = rsurface.modelelement3i + 3*triangleindex;
13055
13056         vertex3f = rsurface.modelvertex3f;
13057
13058         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13059         {
13060                 index = 3*e[cornerindex];
13061                 VectorCopy(vertex3f + index, v[cornerindex]);
13062         }
13063         // cull backfaces
13064         //TriangleNormal(v[0], v[1], v[2], normal);
13065         //if (DotProduct(normal, localnormal) < 0.0f)
13066         //      continue;
13067         // clip by each of the box planes formed from the projection matrix
13068         // if anything survives, we emit the decal
13069         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]);
13070         if (numpoints < 3)
13071                 return;
13072         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]);
13073         if (numpoints < 3)
13074                 return;
13075         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]);
13076         if (numpoints < 3)
13077                 return;
13078         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]);
13079         if (numpoints < 3)
13080                 return;
13081         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]);
13082         if (numpoints < 3)
13083                 return;
13084         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]);
13085         if (numpoints < 3)
13086                 return;
13087         // some part of the triangle survived, so we have to accept it...
13088         if (dynamic)
13089         {
13090                 // dynamic always uses the original triangle
13091                 numpoints = 3;
13092                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13093                 {
13094                         index = 3*e[cornerindex];
13095                         VectorCopy(vertex3f + index, v[cornerindex]);
13096                 }
13097         }
13098         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13099         {
13100                 // convert vertex positions to texcoords
13101                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13102                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13103                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13104                 // calculate distance fade from the projection origin
13105                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13106                 f = bound(0.0f, f, 1.0f);
13107                 c[cornerindex][0] = r * f;
13108                 c[cornerindex][1] = g * f;
13109                 c[cornerindex][2] = b * f;
13110                 c[cornerindex][3] = 1.0f;
13111                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13112         }
13113         if (dynamic)
13114                 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);
13115         else
13116                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13117                         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);
13118 }
13119 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)
13120 {
13121         matrix4x4_t projection;
13122         decalsystem_t *decalsystem;
13123         qboolean dynamic;
13124         dp_model_t *model;
13125         const msurface_t *surface;
13126         const msurface_t *surfaces;
13127         const int *surfacelist;
13128         const texture_t *texture;
13129         int numtriangles;
13130         int numsurfacelist;
13131         int surfacelistindex;
13132         int surfaceindex;
13133         int triangleindex;
13134         float localorigin[3];
13135         float localnormal[3];
13136         float localmins[3];
13137         float localmaxs[3];
13138         float localsize;
13139         //float normal[3];
13140         float planes[6][4];
13141         float angles[3];
13142         bih_t *bih;
13143         int bih_triangles_count;
13144         int bih_triangles[256];
13145         int bih_surfaces[256];
13146
13147         decalsystem = &ent->decalsystem;
13148         model = ent->model;
13149         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13150         {
13151                 R_DecalSystem_Reset(&ent->decalsystem);
13152                 return;
13153         }
13154
13155         if (!model->brush.data_leafs && !cl_decals_models.integer)
13156         {
13157                 if (decalsystem->model)
13158                         R_DecalSystem_Reset(decalsystem);
13159                 return;
13160         }
13161
13162         if (decalsystem->model != model)
13163                 R_DecalSystem_Reset(decalsystem);
13164         decalsystem->model = model;
13165
13166         RSurf_ActiveModelEntity(ent, false, false, false);
13167
13168         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13169         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13170         VectorNormalize(localnormal);
13171         localsize = worldsize*rsurface.inversematrixscale;
13172         localmins[0] = localorigin[0] - localsize;
13173         localmins[1] = localorigin[1] - localsize;
13174         localmins[2] = localorigin[2] - localsize;
13175         localmaxs[0] = localorigin[0] + localsize;
13176         localmaxs[1] = localorigin[1] + localsize;
13177         localmaxs[2] = localorigin[2] + localsize;
13178
13179         //VectorCopy(localnormal, planes[4]);
13180         //VectorVectors(planes[4], planes[2], planes[0]);
13181         AnglesFromVectors(angles, localnormal, NULL, false);
13182         AngleVectors(angles, planes[0], planes[2], planes[4]);
13183         VectorNegate(planes[0], planes[1]);
13184         VectorNegate(planes[2], planes[3]);
13185         VectorNegate(planes[4], planes[5]);
13186         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13187         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13188         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13189         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13190         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13191         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13192
13193 #if 1
13194 // works
13195 {
13196         matrix4x4_t forwardprojection;
13197         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13198         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13199 }
13200 #else
13201 // broken
13202 {
13203         float projectionvector[4][3];
13204         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13205         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13206         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13207         projectionvector[0][0] = planes[0][0] * ilocalsize;
13208         projectionvector[0][1] = planes[1][0] * ilocalsize;
13209         projectionvector[0][2] = planes[2][0] * ilocalsize;
13210         projectionvector[1][0] = planes[0][1] * ilocalsize;
13211         projectionvector[1][1] = planes[1][1] * ilocalsize;
13212         projectionvector[1][2] = planes[2][1] * ilocalsize;
13213         projectionvector[2][0] = planes[0][2] * ilocalsize;
13214         projectionvector[2][1] = planes[1][2] * ilocalsize;
13215         projectionvector[2][2] = planes[2][2] * ilocalsize;
13216         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13217         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13218         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13219         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13220 }
13221 #endif
13222
13223         dynamic = model->surfmesh.isanimated;
13224         numsurfacelist = model->nummodelsurfaces;
13225         surfacelist = model->sortedmodelsurfaces;
13226         surfaces = model->data_surfaces;
13227
13228         bih = NULL;
13229         bih_triangles_count = -1;
13230         if(!dynamic)
13231         {
13232                 if(model->render_bih.numleafs)
13233                         bih = &model->render_bih;
13234                 else if(model->collision_bih.numleafs)
13235                         bih = &model->collision_bih;
13236         }
13237         if(bih)
13238                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13239         if(bih_triangles_count == 0)
13240                 return;
13241         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13242                 return;
13243         if(bih_triangles_count > 0)
13244         {
13245                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13246                 {
13247                         surfaceindex = bih_surfaces[triangleindex];
13248                         surface = surfaces + surfaceindex;
13249                         texture = surface->texture;
13250                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13251                                 continue;
13252                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13253                                 continue;
13254                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13255                 }
13256         }
13257         else
13258         {
13259                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13260                 {
13261                         surfaceindex = surfacelist[surfacelistindex];
13262                         surface = surfaces + surfaceindex;
13263                         // check cull box first because it rejects more than any other check
13264                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13265                                 continue;
13266                         // skip transparent surfaces
13267                         texture = surface->texture;
13268                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13269                                 continue;
13270                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13271                                 continue;
13272                         numtriangles = surface->num_triangles;
13273                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13274                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13275                 }
13276         }
13277 }
13278
13279 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13280 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)
13281 {
13282         int renderentityindex;
13283         float worldmins[3];
13284         float worldmaxs[3];
13285         entity_render_t *ent;
13286
13287         if (!cl_decals_newsystem.integer)
13288                 return;
13289
13290         worldmins[0] = worldorigin[0] - worldsize;
13291         worldmins[1] = worldorigin[1] - worldsize;
13292         worldmins[2] = worldorigin[2] - worldsize;
13293         worldmaxs[0] = worldorigin[0] + worldsize;
13294         worldmaxs[1] = worldorigin[1] + worldsize;
13295         worldmaxs[2] = worldorigin[2] + worldsize;
13296
13297         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13298
13299         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13300         {
13301                 ent = r_refdef.scene.entities[renderentityindex];
13302                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13303                         continue;
13304
13305                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13306         }
13307 }
13308
13309 typedef struct r_decalsystem_splatqueue_s
13310 {
13311         vec3_t worldorigin;
13312         vec3_t worldnormal;
13313         float color[4];
13314         float tcrange[4];
13315         float worldsize;
13316         int decalsequence;
13317 }
13318 r_decalsystem_splatqueue_t;
13319
13320 int r_decalsystem_numqueued = 0;
13321 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13322
13323 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)
13324 {
13325         r_decalsystem_splatqueue_t *queue;
13326
13327         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13328                 return;
13329
13330         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13331         VectorCopy(worldorigin, queue->worldorigin);
13332         VectorCopy(worldnormal, queue->worldnormal);
13333         Vector4Set(queue->color, r, g, b, a);
13334         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13335         queue->worldsize = worldsize;
13336         queue->decalsequence = cl.decalsequence++;
13337 }
13338
13339 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13340 {
13341         int i;
13342         r_decalsystem_splatqueue_t *queue;
13343
13344         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13345                 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);
13346         r_decalsystem_numqueued = 0;
13347 }
13348
13349 extern cvar_t cl_decals_max;
13350 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13351 {
13352         int i;
13353         decalsystem_t *decalsystem = &ent->decalsystem;
13354         int numdecals;
13355         int killsequence;
13356         tridecal_t *decal;
13357         float frametime;
13358         float lifetime;
13359
13360         if (!decalsystem->numdecals)
13361                 return;
13362
13363         if (r_showsurfaces.integer)
13364                 return;
13365
13366         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13367         {
13368                 R_DecalSystem_Reset(decalsystem);
13369                 return;
13370         }
13371
13372         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13373         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13374
13375         if (decalsystem->lastupdatetime)
13376                 frametime = (cl.time - decalsystem->lastupdatetime);
13377         else
13378                 frametime = 0;
13379         decalsystem->lastupdatetime = cl.time;
13380         decal = decalsystem->decals;
13381         numdecals = decalsystem->numdecals;
13382
13383         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13384         {
13385                 if (decal->color4ub[0][3])
13386                 {
13387                         decal->lived += frametime;
13388                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13389                         {
13390                                 memset(decal, 0, sizeof(*decal));
13391                                 if (decalsystem->freedecal > i)
13392                                         decalsystem->freedecal = i;
13393                         }
13394                 }
13395         }
13396         decal = decalsystem->decals;
13397         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13398                 numdecals--;
13399
13400         // collapse the array by shuffling the tail decals into the gaps
13401         for (;;)
13402         {
13403                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13404                         decalsystem->freedecal++;
13405                 if (decalsystem->freedecal == numdecals)
13406                         break;
13407                 decal[decalsystem->freedecal] = decal[--numdecals];
13408         }
13409
13410         decalsystem->numdecals = numdecals;
13411
13412         if (numdecals <= 0)
13413         {
13414                 // if there are no decals left, reset decalsystem
13415                 R_DecalSystem_Reset(decalsystem);
13416         }
13417 }
13418
13419 extern skinframe_t *decalskinframe;
13420 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13421 {
13422         int i;
13423         decalsystem_t *decalsystem = &ent->decalsystem;
13424         int numdecals;
13425         tridecal_t *decal;
13426         float faderate;
13427         float alpha;
13428         float *v3f;
13429         float *c4f;
13430         float *t2f;
13431         const int *e;
13432         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13433         int numtris = 0;
13434
13435         numdecals = decalsystem->numdecals;
13436         if (!numdecals)
13437                 return;
13438
13439         if (r_showsurfaces.integer)
13440                 return;
13441
13442         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13443         {
13444                 R_DecalSystem_Reset(decalsystem);
13445                 return;
13446         }
13447
13448         // if the model is static it doesn't matter what value we give for
13449         // wantnormals and wanttangents, so this logic uses only rules applicable
13450         // to a model, knowing that they are meaningless otherwise
13451         if (ent == r_refdef.scene.worldentity)
13452                 RSurf_ActiveWorldEntity();
13453         else
13454                 RSurf_ActiveModelEntity(ent, false, false, false);
13455
13456         decalsystem->lastupdatetime = cl.time;
13457         decal = decalsystem->decals;
13458
13459         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13460
13461         // update vertex positions for animated models
13462         v3f = decalsystem->vertex3f;
13463         c4f = decalsystem->color4f;
13464         t2f = decalsystem->texcoord2f;
13465         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13466         {
13467                 if (!decal->color4ub[0][3])
13468                         continue;
13469
13470                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13471                         continue;
13472
13473                 // update color values for fading decals
13474                 if (decal->lived >= cl_decals_time.value)
13475                 {
13476                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13477                         alpha *= (1.0f/255.0f);
13478                 }
13479                 else
13480                         alpha = 1.0f/255.0f;
13481
13482                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13483                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13484                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13485                 c4f[ 3] = 1;
13486                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13487                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13488                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13489                 c4f[ 7] = 1;
13490                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13491                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13492                 c4f[10] = decal->color4ub[2][2] * alpha;
13493                 c4f[11] = 1;
13494
13495                 t2f[0] = decal->texcoord2f[0][0];
13496                 t2f[1] = decal->texcoord2f[0][1];
13497                 t2f[2] = decal->texcoord2f[1][0];
13498                 t2f[3] = decal->texcoord2f[1][1];
13499                 t2f[4] = decal->texcoord2f[2][0];
13500                 t2f[5] = decal->texcoord2f[2][1];
13501
13502                 // update vertex positions for animated models
13503                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13504                 {
13505                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13506                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13507                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13508                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13509                 }
13510                 else
13511                 {
13512                         VectorCopy(decal->vertex3f[0], v3f);
13513                         VectorCopy(decal->vertex3f[1], v3f + 3);
13514                         VectorCopy(decal->vertex3f[2], v3f + 6);
13515                 }
13516
13517                 if (r_refdef.fogenabled)
13518                 {
13519                         alpha = RSurf_FogVertex(v3f);
13520                         VectorScale(c4f, alpha, c4f);
13521                         alpha = RSurf_FogVertex(v3f + 3);
13522                         VectorScale(c4f + 4, alpha, c4f + 4);
13523                         alpha = RSurf_FogVertex(v3f + 6);
13524                         VectorScale(c4f + 8, alpha, c4f + 8);
13525                 }
13526
13527                 v3f += 9;
13528                 c4f += 12;
13529                 t2f += 6;
13530                 numtris++;
13531         }
13532
13533         if (numtris > 0)
13534         {
13535                 r_refdef.stats.drawndecals += numtris;
13536
13537                 // now render the decals all at once
13538                 // (this assumes they all use one particle font texture!)
13539                 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);
13540 //              R_Mesh_ResetTextureState();
13541                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13542                 GL_DepthMask(false);
13543                 GL_DepthRange(0, 1);
13544                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13545                 GL_DepthTest(true);
13546                 GL_CullFace(GL_NONE);
13547                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13548                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13549                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13550         }
13551 }
13552
13553 static void R_DrawModelDecals(void)
13554 {
13555         int i, numdecals;
13556
13557         // fade faster when there are too many decals
13558         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13559         for (i = 0;i < r_refdef.scene.numentities;i++)
13560                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13561
13562         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13563         for (i = 0;i < r_refdef.scene.numentities;i++)
13564                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13565                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13566
13567         R_DecalSystem_ApplySplatEntitiesQueue();
13568
13569         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13570         for (i = 0;i < r_refdef.scene.numentities;i++)
13571                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13572
13573         r_refdef.stats.totaldecals += numdecals;
13574
13575         if (r_showsurfaces.integer)
13576                 return;
13577
13578         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13579
13580         for (i = 0;i < r_refdef.scene.numentities;i++)
13581         {
13582                 if (!r_refdef.viewcache.entityvisible[i])
13583                         continue;
13584                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13585                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13586         }
13587 }
13588
13589 extern cvar_t mod_collision_bih;
13590 void R_DrawDebugModel(void)
13591 {
13592         entity_render_t *ent = rsurface.entity;
13593         int i, j, k, l, flagsmask;
13594         const msurface_t *surface;
13595         dp_model_t *model = ent->model;
13596         vec3_t v;
13597
13598         switch(vid.renderpath)
13599         {
13600         case RENDERPATH_GL11:
13601         case RENDERPATH_GL13:
13602         case RENDERPATH_GL20:
13603                 break;
13604         case RENDERPATH_D3D9:
13605                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13606                 return;
13607         case RENDERPATH_D3D10:
13608                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13609                 return;
13610         case RENDERPATH_D3D11:
13611                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13612                 return;
13613         case RENDERPATH_SOFT:
13614                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13615                 return;
13616         case RENDERPATH_GLES2:
13617                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13618                 return;
13619         }
13620
13621         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13622
13623 //      R_Mesh_ResetTextureState();
13624         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13625         GL_DepthRange(0, 1);
13626         GL_DepthTest(!r_showdisabledepthtest.integer);
13627         GL_DepthMask(false);
13628         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13629
13630         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13631         {
13632                 int triangleindex;
13633                 int bihleafindex;
13634                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13635                 const q3mbrush_t *brush;
13636                 const bih_t *bih = &model->collision_bih;
13637                 const bih_leaf_t *bihleaf;
13638                 float vertex3f[3][3];
13639                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13640                 cullbox = false;
13641                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13642                 {
13643                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13644                                 continue;
13645                         switch (bihleaf->type)
13646                         {
13647                         case BIH_BRUSH:
13648                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13649                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13650                                 {
13651                                         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);
13652                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13653                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13654                                 }
13655                                 break;
13656                         case BIH_COLLISIONTRIANGLE:
13657                                 triangleindex = bihleaf->itemindex;
13658                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13659                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13660                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13661                                 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);
13662                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13663                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13664                                 break;
13665                         case BIH_RENDERTRIANGLE:
13666                                 triangleindex = bihleaf->itemindex;
13667                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13668                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13669                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13670                                 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);
13671                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13672                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13673                                 break;
13674                         }
13675                 }
13676         }
13677
13678         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13679
13680         if (r_showtris.integer || (r_shownormals.value != 0))
13681         {
13682                 if (r_showdisabledepthtest.integer)
13683                 {
13684                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13685                         GL_DepthMask(false);
13686                 }
13687                 else
13688                 {
13689                         GL_BlendFunc(GL_ONE, GL_ZERO);
13690                         GL_DepthMask(true);
13691                 }
13692                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13693                 {
13694                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13695                                 continue;
13696                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13697                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13698                         {
13699                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13700                                 if (r_showtris.value > 0)
13701                                 {
13702                                         if (!rsurface.texture->currentlayers->depthmask)
13703                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13704                                         else if (ent == r_refdef.scene.worldentity)
13705                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13706                                         else
13707                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13708                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13709                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13710                                         RSurf_DrawBatch();
13711                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13712                                         CHECKGLERROR
13713                                 }
13714                                 if (r_shownormals.value < 0)
13715                                 {
13716                                         qglBegin(GL_LINES);
13717                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13718                                         {
13719                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13720                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13721                                                 qglVertex3f(v[0], v[1], v[2]);
13722                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13723                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13724                                                 qglVertex3f(v[0], v[1], v[2]);
13725                                         }
13726                                         qglEnd();
13727                                         CHECKGLERROR
13728                                 }
13729                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13730                                 {
13731                                         qglBegin(GL_LINES);
13732                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13733                                         {
13734                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13735                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13736                                                 qglVertex3f(v[0], v[1], v[2]);
13737                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13738                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13739                                                 qglVertex3f(v[0], v[1], v[2]);
13740                                         }
13741                                         qglEnd();
13742                                         CHECKGLERROR
13743                                         qglBegin(GL_LINES);
13744                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13745                                         {
13746                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13747                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13748                                                 qglVertex3f(v[0], v[1], v[2]);
13749                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13750                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13751                                                 qglVertex3f(v[0], v[1], v[2]);
13752                                         }
13753                                         qglEnd();
13754                                         CHECKGLERROR
13755                                         qglBegin(GL_LINES);
13756                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13757                                         {
13758                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13759                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13760                                                 qglVertex3f(v[0], v[1], v[2]);
13761                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13762                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13763                                                 qglVertex3f(v[0], v[1], v[2]);
13764                                         }
13765                                         qglEnd();
13766                                         CHECKGLERROR
13767                                 }
13768                         }
13769                 }
13770                 rsurface.texture = NULL;
13771         }
13772 }
13773
13774 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13775 int r_maxsurfacelist = 0;
13776 const msurface_t **r_surfacelist = NULL;
13777 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13778 {
13779         int i, j, endj, flagsmask;
13780         dp_model_t *model = r_refdef.scene.worldmodel;
13781         msurface_t *surfaces;
13782         unsigned char *update;
13783         int numsurfacelist = 0;
13784         if (model == NULL)
13785                 return;
13786
13787         if (r_maxsurfacelist < model->num_surfaces)
13788         {
13789                 r_maxsurfacelist = model->num_surfaces;
13790                 if (r_surfacelist)
13791                         Mem_Free((msurface_t**)r_surfacelist);
13792                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13793         }
13794
13795         RSurf_ActiveWorldEntity();
13796
13797         surfaces = model->data_surfaces;
13798         update = model->brushq1.lightmapupdateflags;
13799
13800         // update light styles on this submodel
13801         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13802         {
13803                 model_brush_lightstyleinfo_t *style;
13804                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13805                 {
13806                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13807                         {
13808                                 int *list = style->surfacelist;
13809                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13810                                 for (j = 0;j < style->numsurfaces;j++)
13811                                         update[list[j]] = true;
13812                         }
13813                 }
13814         }
13815
13816         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13817
13818         if (debug)
13819         {
13820                 R_DrawDebugModel();
13821                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13822                 return;
13823         }
13824
13825         rsurface.lightmaptexture = NULL;
13826         rsurface.deluxemaptexture = NULL;
13827         rsurface.uselightmaptexture = false;
13828         rsurface.texture = NULL;
13829         rsurface.rtlight = NULL;
13830         numsurfacelist = 0;
13831         // add visible surfaces to draw list
13832         for (i = 0;i < model->nummodelsurfaces;i++)
13833         {
13834                 j = model->sortedmodelsurfaces[i];
13835                 if (r_refdef.viewcache.world_surfacevisible[j])
13836                         r_surfacelist[numsurfacelist++] = surfaces + j;
13837         }
13838         // update lightmaps if needed
13839         if (model->brushq1.firstrender)
13840         {
13841                 model->brushq1.firstrender = false;
13842                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13843                         if (update[j])
13844                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13845         }
13846         else if (update)
13847         {
13848                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13849                         if (r_refdef.viewcache.world_surfacevisible[j])
13850                                 if (update[j])
13851                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13852         }
13853         // don't do anything if there were no surfaces
13854         if (!numsurfacelist)
13855         {
13856                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13857                 return;
13858         }
13859         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13860
13861         // add to stats if desired
13862         if (r_speeds.integer && !skysurfaces && !depthonly)
13863         {
13864                 r_refdef.stats.world_surfaces += numsurfacelist;
13865                 for (j = 0;j < numsurfacelist;j++)
13866                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13867         }
13868
13869         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13870 }
13871
13872 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13873 {
13874         int i, j, endj, flagsmask;
13875         dp_model_t *model = ent->model;
13876         msurface_t *surfaces;
13877         unsigned char *update;
13878         int numsurfacelist = 0;
13879         if (model == NULL)
13880                 return;
13881
13882         if (r_maxsurfacelist < model->num_surfaces)
13883         {
13884                 r_maxsurfacelist = model->num_surfaces;
13885                 if (r_surfacelist)
13886                         Mem_Free((msurface_t **)r_surfacelist);
13887                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13888         }
13889
13890         // if the model is static it doesn't matter what value we give for
13891         // wantnormals and wanttangents, so this logic uses only rules applicable
13892         // to a model, knowing that they are meaningless otherwise
13893         if (ent == r_refdef.scene.worldentity)
13894                 RSurf_ActiveWorldEntity();
13895         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13896                 RSurf_ActiveModelEntity(ent, false, false, false);
13897         else if (prepass)
13898                 RSurf_ActiveModelEntity(ent, true, true, true);
13899         else if (depthonly)
13900         {
13901                 switch (vid.renderpath)
13902                 {
13903                 case RENDERPATH_GL20:
13904                 case RENDERPATH_D3D9:
13905                 case RENDERPATH_D3D10:
13906                 case RENDERPATH_D3D11:
13907                 case RENDERPATH_SOFT:
13908                 case RENDERPATH_GLES2:
13909                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
13910                         break;
13911                 case RENDERPATH_GL13:
13912                 case RENDERPATH_GL11:
13913                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
13914                         break;
13915                 }
13916         }
13917         else
13918         {
13919                 switch (vid.renderpath)
13920                 {
13921                 case RENDERPATH_GL20:
13922                 case RENDERPATH_D3D9:
13923                 case RENDERPATH_D3D10:
13924                 case RENDERPATH_D3D11:
13925                 case RENDERPATH_SOFT:
13926                 case RENDERPATH_GLES2:
13927                         RSurf_ActiveModelEntity(ent, true, true, false);
13928                         break;
13929                 case RENDERPATH_GL13:
13930                 case RENDERPATH_GL11:
13931                         RSurf_ActiveModelEntity(ent, true, false, false);
13932                         break;
13933                 }
13934         }
13935
13936         surfaces = model->data_surfaces;
13937         update = model->brushq1.lightmapupdateflags;
13938
13939         // update light styles
13940         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13941         {
13942                 model_brush_lightstyleinfo_t *style;
13943                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13944                 {
13945                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13946                         {
13947                                 int *list = style->surfacelist;
13948                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13949                                 for (j = 0;j < style->numsurfaces;j++)
13950                                         update[list[j]] = true;
13951                         }
13952                 }
13953         }
13954
13955         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13956
13957         if (debug)
13958         {
13959                 R_DrawDebugModel();
13960                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13961                 return;
13962         }
13963
13964         rsurface.lightmaptexture = NULL;
13965         rsurface.deluxemaptexture = NULL;
13966         rsurface.uselightmaptexture = false;
13967         rsurface.texture = NULL;
13968         rsurface.rtlight = NULL;
13969         numsurfacelist = 0;
13970         // add visible surfaces to draw list
13971         for (i = 0;i < model->nummodelsurfaces;i++)
13972                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
13973         // don't do anything if there were no surfaces
13974         if (!numsurfacelist)
13975         {
13976                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13977                 return;
13978         }
13979         // update lightmaps if needed
13980         if (update)
13981         {
13982                 int updated = 0;
13983                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13984                 {
13985                         if (update[j])
13986                         {
13987                                 updated++;
13988                                 R_BuildLightMap(ent, surfaces + j);
13989                         }
13990                 }
13991         }
13992         if (update)
13993                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13994                         if (update[j])
13995                                 R_BuildLightMap(ent, surfaces + j);
13996         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13997
13998         // add to stats if desired
13999         if (r_speeds.integer && !skysurfaces && !depthonly)
14000         {
14001                 r_refdef.stats.entities_surfaces += numsurfacelist;
14002                 for (j = 0;j < numsurfacelist;j++)
14003                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14004         }
14005
14006         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14007 }
14008
14009 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14010 {
14011         static texture_t texture;
14012         static msurface_t surface;
14013         const msurface_t *surfacelist = &surface;
14014
14015         // fake enough texture and surface state to render this geometry
14016
14017         texture.update_lastrenderframe = -1; // regenerate this texture
14018         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14019         texture.currentskinframe = skinframe;
14020         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14021         texture.offsetmapping = OFFSETMAPPING_OFF;
14022         texture.offsetscale = 1;
14023         texture.specularscalemod = 1;
14024         texture.specularpowermod = 1;
14025
14026         surface.texture = &texture;
14027         surface.num_triangles = numtriangles;
14028         surface.num_firsttriangle = firsttriangle;
14029         surface.num_vertices = numvertices;
14030         surface.num_firstvertex = firstvertex;
14031
14032         // now render it
14033         rsurface.texture = R_GetCurrentTexture(surface.texture);
14034         rsurface.lightmaptexture = NULL;
14035         rsurface.deluxemaptexture = NULL;
14036         rsurface.uselightmaptexture = false;
14037         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14038 }
14039
14040 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)
14041 {
14042         static msurface_t surface;
14043         const msurface_t *surfacelist = &surface;
14044
14045         // fake enough texture and surface state to render this geometry
14046         surface.texture = texture;
14047         surface.num_triangles = numtriangles;
14048         surface.num_firsttriangle = firsttriangle;
14049         surface.num_vertices = numvertices;
14050         surface.num_firstvertex = firstvertex;
14051
14052         // now render it
14053         rsurface.texture = R_GetCurrentTexture(surface.texture);
14054         rsurface.lightmaptexture = NULL;
14055         rsurface.deluxemaptexture = NULL;
14056         rsurface.uselightmaptexture = false;
14057         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14058 }