]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
d76503790227fe0da685f8b3f717006843cb7a68
[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 "#ifdef MODE_DEFERREDBOUNCELIGHT\n"
1062 "varying highp vec4 ModelViewPosition;\n"
1063 "varying highp vec4 LightOriginInvRadius;\n"
1064 "varying mediump vec4 LightColor;\n"
1065 "#endif\n"
1066 "\n"
1067 "#ifdef MODE_LIGHTSOURCE\n"
1068 "uniform highp vec3 LightPosition;\n"
1069 "#endif\n"
1070 "uniform highp vec3 EyePosition;\n"
1071 "#ifdef MODE_LIGHTDIRECTION\n"
1072 "uniform highp vec3 LightDir;\n"
1073 "#endif\n"
1074 "uniform highp vec4 FogPlane;\n"
1075 "\n"
1076 "#ifdef USESHADOWMAPORTHO\n"
1077 "varying mediump vec3 ShadowMapTC;\n"
1078 "#endif\n"
1079 "\n"
1080 "#ifdef USEBOUNCEGRID\n"
1081 "varying mediump vec3 BounceGridTexCoord;\n"
1082 "#endif\n"
1083 "\n"
1084 "\n"
1085 "\n"
1086 "\n"
1087 "\n"
1088 "\n"
1089 "// 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"
1090 "\n"
1091 "// fragment shader specific:\n"
1092 "#ifdef FRAGMENT_SHADER\n"
1093 "\n"
1094 "uniform sampler2D Texture_Normal;\n"
1095 "uniform sampler2D Texture_Color;\n"
1096 "uniform sampler2D Texture_Gloss;\n"
1097 "#ifdef USEGLOW\n"
1098 "uniform sampler2D Texture_Glow;\n"
1099 "#endif\n"
1100 "#ifdef USEVERTEXTEXTUREBLEND\n"
1101 "uniform sampler2D Texture_SecondaryNormal;\n"
1102 "uniform sampler2D Texture_SecondaryColor;\n"
1103 "uniform sampler2D Texture_SecondaryGloss;\n"
1104 "#ifdef USEGLOW\n"
1105 "uniform sampler2D Texture_SecondaryGlow;\n"
1106 "#endif\n"
1107 "#endif\n"
1108 "#ifdef USECOLORMAPPING\n"
1109 "uniform sampler2D Texture_Pants;\n"
1110 "uniform sampler2D Texture_Shirt;\n"
1111 "#endif\n"
1112 "#ifdef USEFOG\n"
1113 "#ifdef USEFOGHEIGHTTEXTURE\n"
1114 "uniform sampler2D Texture_FogHeightTexture;\n"
1115 "#endif\n"
1116 "uniform sampler2D Texture_FogMask;\n"
1117 "#endif\n"
1118 "#ifdef USELIGHTMAP\n"
1119 "uniform sampler2D Texture_Lightmap;\n"
1120 "#endif\n"
1121 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1122 "uniform sampler2D Texture_Deluxemap;\n"
1123 "#endif\n"
1124 "#ifdef USEREFLECTION\n"
1125 "uniform sampler2D Texture_Reflection;\n"
1126 "#endif\n"
1127 "\n"
1128 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1129 "uniform sampler2D Texture_ScreenDepth;\n"
1130 "uniform sampler2D Texture_ScreenNormalMap;\n"
1131 "#endif\n"
1132 "#ifdef USEDEFERREDLIGHTMAP\n"
1133 "uniform sampler2D Texture_ScreenDiffuse;\n"
1134 "uniform sampler2D Texture_ScreenSpecular;\n"
1135 "#endif\n"
1136 "#ifdef MODE_DEFERREDBOUNCELIGHT\n"
1137 "uniform sampler2D Texture_ScreenDepth;\n"
1138 "#endif\n"
1139 "\n"
1140 "uniform lowp vec3 Color_Pants;\n"
1141 "uniform lowp vec3 Color_Shirt;\n"
1142 "uniform lowp vec3 FogColor;\n"
1143 "\n"
1144 "#ifdef USEFOG\n"
1145 "uniform highp float FogRangeRecip;\n"
1146 "uniform highp float FogPlaneViewDist;\n"
1147 "uniform highp float FogHeightFade;\n"
1148 "vec3 FogVertex(vec3 surfacecolor)\n"
1149 "{\n"
1150 "       vec3 EyeVectorModelSpace = EyeVectorModelSpaceFogPlaneVertexDist.xyz;\n"
1151 "       float FogPlaneVertexDist = EyeVectorModelSpaceFogPlaneVertexDist.w;\n"
1152 "       float fogfrac;\n"
1153 "#ifdef USEFOGHEIGHTTEXTURE\n"
1154 "       vec4 fogheightpixel = texture2D(Texture_FogHeightTexture, vec2(1,1) + vec2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
1155 "       fogfrac = fogheightpixel.a;\n"
1156 "       return mix(fogheightpixel.rgb * FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1157 "#else\n"
1158 "# ifdef USEFOGOUTSIDE\n"
1159 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
1160 "# else\n"
1161 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
1162 "# endif\n"
1163 "       return mix(FogColor, surfacecolor, texture2D(Texture_FogMask, myhalf2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
1164 "#endif\n"
1165 "}\n"
1166 "#endif\n"
1167 "\n"
1168 "#ifdef USEOFFSETMAPPING\n"
1169 "uniform mediump float OffsetMapping_Scale;\n"
1170 "vec2 OffsetMapping(vec2 TexCoord)\n"
1171 "{\n"
1172 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
1173 "       // 14 sample relief mapping: linear search and then binary search\n"
1174 "       // this basically steps forward a small amount repeatedly until it finds\n"
1175 "       // itself inside solid, then jitters forward and back using decreasing\n"
1176 "       // amounts to find the impact\n"
1177 "       //vec3 OffsetVector = vec3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1), -1);\n"
1178 "       //vec3 OffsetVector = vec3(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1179 "       vec3 OffsetVector = vec3(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1), -1);\n"
1180 "       vec3 RT = vec3(TexCoord, 1);\n"
1181 "       OffsetVector *= 0.1;\n"
1182 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1183 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1184 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1185 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1186 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1187 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1188 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1189 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1190 "       RT += OffsetVector *  step(texture2D(Texture_Normal, RT.xy).a, RT.z);\n"
1191 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
1192 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
1193 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
1194 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
1195 "       RT += OffsetVector * (step(texture2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
1196 "       return RT.xy;\n"
1197 "#else\n"
1198 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
1199 "       //vec2 OffsetVector = vec2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * vec2(-1, 1));\n"
1200 "       //vec2 OffsetVector = vec2(normalize(EyeVector.xy) * OffsetMapping_Scale * vec2(-1, 1));\n"
1201 "       vec2 OffsetVector = vec2(normalize(EyeVector).xy * OffsetMapping_Scale * vec2(-1, 1));\n"
1202 "       OffsetVector *= 0.5;\n"
1203 "       TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1204 "       TexCoord += OffsetVector * (1.0 - texture2D(Texture_Normal, TexCoord).a);\n"
1205 "       return TexCoord;\n"
1206 "#endif\n"
1207 "}\n"
1208 "#endif // USEOFFSETMAPPING\n"
1209 "\n"
1210 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
1211 "uniform sampler2D Texture_Attenuation;\n"
1212 "uniform samplerCube Texture_Cube;\n"
1213 "#endif\n"
1214 "\n"
1215 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
1216 "\n"
1217 "#ifdef USESHADOWMAP2D\n"
1218 "# ifdef USESHADOWSAMPLER\n"
1219 "uniform sampler2DShadow Texture_ShadowMap2D;\n"
1220 "# else\n"
1221 "uniform sampler2D Texture_ShadowMap2D;\n"
1222 "# endif\n"
1223 "#endif\n"
1224 "\n"
1225 "#ifdef USESHADOWMAPVSDCT\n"
1226 "uniform samplerCube Texture_CubeProjection;\n"
1227 "#endif\n"
1228 "\n"
1229 "#if defined(USESHADOWMAP2D)\n"
1230 "uniform mediump vec2 ShadowMap_TextureScale;\n"
1231 "uniform mediump vec4 ShadowMap_Parameters;\n"
1232 "#endif\n"
1233 "\n"
1234 "#if defined(USESHADOWMAP2D)\n"
1235 "# ifdef USESHADOWMAPORTHO\n"
1236 "#  define GetShadowMapTC2D(dir) (min(dir, ShadowMap_Parameters.xyz))\n"
1237 "# else\n"
1238 "#  ifdef USESHADOWMAPVSDCT\n"
1239 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1240 "{\n"
1241 "       vec3 adir = abs(dir);\n"
1242 "       vec2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
1243 "       vec4 proj = textureCube(Texture_CubeProjection, dir);\n"
1244 "       return vec3(mix(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
1245 "}\n"
1246 "#  else\n"
1247 "vec3 GetShadowMapTC2D(vec3 dir)\n"
1248 "{\n"
1249 "       vec3 adir = abs(dir);\n"
1250 "       float ma = adir.z;\n"
1251 "       vec4 proj = vec4(dir, 2.5);\n"
1252 "       if (adir.x > ma) { ma = adir.x; proj = vec4(dir.zyx, 0.5); }\n"
1253 "       if (adir.y > ma) { ma = adir.y; proj = vec4(dir.xzy, 1.5); }\n"
1254 "       vec2 aparams = ShadowMap_Parameters.xy / ma;\n"
1255 "       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"
1256 "}\n"
1257 "#  endif\n"
1258 "# endif\n"
1259 "#endif // defined(USESHADOWMAP2D)\n"
1260 "\n"
1261 "# ifdef USESHADOWMAP2D\n"
1262 "float ShadowMapCompare(vec3 dir)\n"
1263 "{\n"
1264 "       vec3 shadowmaptc = GetShadowMapTC2D(dir);\n"
1265 "       float f;\n"
1266 "\n"
1267 "#  ifdef USESHADOWSAMPLER\n"
1268 "#    ifdef USESHADOWMAPPCF\n"
1269 "#      define texval(x, y) shadow2D(Texture_ShadowMap2D, vec3(center + vec2(x, y)*ShadowMap_TextureScale, shadowmaptc.z)).r  \n"
1270 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
1271 "       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"
1272 "#    else\n"
1273 "       f = shadow2D(Texture_ShadowMap2D, vec3(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z)).r;\n"
1274 "#    endif\n"
1275 "#  else\n"
1276 "#    ifdef USESHADOWMAPPCF\n"
1277 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
1278 "#      ifdef GL_ARB_texture_gather\n"
1279 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, ivec2(x, y))\n"
1280 "#      else\n"
1281 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale)\n"
1282 "#      endif\n"
1283 "       vec2 offset = fract(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
1284 "#      if USESHADOWMAPPCF > 1\n"
1285 "   vec4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
1286 "   vec4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
1287 "   vec4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
1288 "   vec4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
1289 "   vec4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
1290 "   vec4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
1291 "   vec4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
1292 "   vec4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
1293 "   vec4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
1294 "       vec4 locols = vec4(group1.ab, group3.ab);\n"
1295 "       vec4 hicols = vec4(group7.rg, group9.rg);\n"
1296 "       locols.yz += group2.ab;\n"
1297 "       hicols.yz += group8.rg;\n"
1298 "       vec4 midcols = vec4(group1.rg, group3.rg) + vec4(group7.ab, group9.ab) +\n"
1299 "                               vec4(group4.rg, group6.rg) + vec4(group4.ab, group6.ab) +\n"
1300 "                               mix(locols, hicols, offset.y);\n"
1301 "       vec4 cols = group5 + vec4(group2.rg, group8.ab);\n"
1302 "       cols.xyz += mix(midcols.xyz, midcols.yzw, offset.x);\n"
1303 "       f = dot(cols, vec4(1.0/25.0));\n"
1304 "#      else\n"
1305 "       vec4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
1306 "       vec4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
1307 "       vec4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
1308 "       vec4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
1309 "       vec4 cols = vec4(group1.rg, group2.rg) + vec4(group3.ab, group4.ab) +\n"
1310 "                               mix(vec4(group1.ab, group2.ab), vec4(group3.rg, group4.rg), offset.y);\n"
1311 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1312 "#      endif\n"
1313 "#     else\n"
1314 "#      ifdef GL_EXT_gpu_shader4\n"
1315 "#        define texval(x, y) texture2DOffset(Texture_ShadowMap2D, center, ivec2(x, y)).r\n"
1316 "#      else\n"
1317 "#        define texval(x, y) texture2D(Texture_ShadowMap2D, center + vec2(x, y)*ShadowMap_TextureScale).r  \n"
1318 "#      endif\n"
1319 "#      if USESHADOWMAPPCF > 1\n"
1320 "       vec2 center = shadowmaptc.xy - 0.5, offset = fract(center);\n"
1321 "       center *= ShadowMap_TextureScale;\n"
1322 "       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"
1323 "       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"
1324 "       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"
1325 "       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"
1326 "       vec4 cols = row2 + row3 + mix(row1, row4, offset.y);\n"
1327 "       f = dot(mix(cols.xyz, cols.yzw, offset.x), vec3(1.0/9.0));\n"
1328 "#      else\n"
1329 "       vec2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = fract(shadowmaptc.xy);\n"
1330 "       vec3 row1 = step(shadowmaptc.z, vec3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
1331 "       vec3 row2 = step(shadowmaptc.z, vec3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
1332 "       vec3 row3 = step(shadowmaptc.z, vec3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
1333 "       vec3 cols = row2 + mix(row1, row3, offset.y);\n"
1334 "       f = dot(mix(cols.xy, cols.yz, offset.x), vec2(0.25));\n"
1335 "#      endif\n"
1336 "#     endif\n"
1337 "#    else\n"
1338 "       f = step(shadowmaptc.z, texture2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
1339 "#    endif\n"
1340 "#  endif\n"
1341 "#  ifdef USESHADOWMAPORTHO\n"
1342 "       return mix(ShadowMap_Parameters.w, 1.0, f);\n"
1343 "#  else\n"
1344 "       return f;\n"
1345 "#  endif\n"
1346 "}\n"
1347 "# endif\n"
1348 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
1349 "#endif // FRAGMENT_SHADER\n"
1350 "\n"
1351 "\n"
1352 "\n"
1353 "\n"
1354 "#ifdef MODE_DEFERREDGEOMETRY\n"
1355 "#ifdef VERTEX_SHADER\n"
1356 "uniform highp mat4 TexMatrix;\n"
1357 "#ifdef USEVERTEXTEXTUREBLEND\n"
1358 "uniform highp mat4 BackgroundTexMatrix;\n"
1359 "#endif\n"
1360 "uniform highp mat4 ModelViewMatrix;\n"
1361 "void main(void)\n"
1362 "{\n"
1363 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1364 "#ifdef USEVERTEXTEXTUREBLEND\n"
1365 "       VertexColor = Attrib_Color;\n"
1366 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1367 "#endif\n"
1368 "\n"
1369 "       // transform unnormalized eye direction into tangent space\n"
1370 "#ifdef USEOFFSETMAPPING\n"
1371 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1372 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1373 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1374 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1375 "#endif\n"
1376 "\n"
1377 "       VectorS = (ModelViewMatrix * vec4(Attrib_TexCoord1.xyz, 0)).xyz;\n"
1378 "       VectorT = (ModelViewMatrix * vec4(Attrib_TexCoord2.xyz, 0)).xyz;\n"
1379 "       VectorR = (ModelViewMatrix * vec4(Attrib_TexCoord3.xyz, 0)).xyz;\n"
1380 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1381 "}\n"
1382 "#endif // VERTEX_SHADER\n"
1383 "\n"
1384 "#ifdef FRAGMENT_SHADER\n"
1385 "void main(void)\n"
1386 "{\n"
1387 "#ifdef USEOFFSETMAPPING\n"
1388 "       // apply offsetmapping\n"
1389 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1390 "#define TexCoord TexCoordOffset\n"
1391 "#endif\n"
1392 "\n"
1393 "#ifdef USEALPHAKILL\n"
1394 "       if (texture2D(Texture_Color, TexCoord).a < 0.5)\n"
1395 "               discard;\n"
1396 "#endif\n"
1397 "\n"
1398 "#ifdef USEVERTEXTEXTUREBLEND\n"
1399 "       float alpha = texture2D(Texture_Color, TexCoord).a;\n"
1400 "       float terrainblend = clamp(float(VertexColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
1401 "       //float terrainblend = min(float(VertexColor.a) * alpha * 2.0, float(1.0));\n"
1402 "       //float terrainblend = float(VertexColor.a) * alpha > 0.5;\n"
1403 "#endif\n"
1404 "\n"
1405 "#ifdef USEVERTEXTEXTUREBLEND\n"
1406 "       vec3 surfacenormal = mix(vec3(texture2D(Texture_SecondaryNormal, TexCoord2)), vec3(texture2D(Texture_Normal, TexCoord)), terrainblend) - vec3(0.5, 0.5, 0.5);\n"
1407 "       float a = mix(texture2D(Texture_SecondaryGloss, TexCoord2).a, texture2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
1408 "#else\n"
1409 "       vec3 surfacenormal = vec3(texture2D(Texture_Normal, TexCoord)) - vec3(0.5, 0.5, 0.5);\n"
1410 "       float a = texture2D(Texture_Gloss, TexCoord).a;\n"
1411 "#endif\n"
1412 "\n"
1413 "       gl_FragColor = vec4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + vec3(0.5, 0.5, 0.5), a);\n"
1414 "}\n"
1415 "#endif // FRAGMENT_SHADER\n"
1416 "#else // !MODE_DEFERREDGEOMETRY\n"
1417 "\n"
1418 "\n"
1419 "\n"
1420 "\n"
1421 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
1422 "#ifdef VERTEX_SHADER\n"
1423 "uniform highp mat4 ModelViewMatrix;\n"
1424 "void main(void)\n"
1425 "{\n"
1426 "       ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1427 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1428 "}\n"
1429 "#endif // VERTEX_SHADER\n"
1430 "\n"
1431 "#ifdef FRAGMENT_SHADER\n"
1432 "uniform highp mat4 ViewToLight;\n"
1433 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1434 "uniform highp vec2 ScreenToDepth;\n"
1435 "uniform myhalf3 DeferredColor_Ambient;\n"
1436 "uniform myhalf3 DeferredColor_Diffuse;\n"
1437 "#ifdef USESPECULAR\n"
1438 "uniform myhalf3 DeferredColor_Specular;\n"
1439 "uniform myhalf SpecularPower;\n"
1440 "#endif\n"
1441 "uniform myhalf2 PixelToScreenTexCoord;\n"
1442 "void main(void)\n"
1443 "{\n"
1444 "       // calculate viewspace pixel position\n"
1445 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1446 "       vec3 position;\n"
1447 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1448 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1449 "       // decode viewspace pixel normal\n"
1450 "       myhalf4 normalmap = texture2D(Texture_ScreenNormalMap, ScreenTexCoord);\n"
1451 "       myhalf3 surfacenormal = normalize(normalmap.rgb - myhalf3(0.5,0.5,0.5));\n"
1452 "       // surfacenormal = pixel normal in viewspace\n"
1453 "       // LightVector = pixel to light in viewspace\n"
1454 "       // CubeVector = position in lightspace\n"
1455 "       // eyevector = pixel to view in viewspace\n"
1456 "       vec3 CubeVector = vec3(ViewToLight * vec4(position,1));\n"
1457 "       myhalf fade = myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1458 "#ifdef USEDIFFUSE\n"
1459 "       // calculate diffuse shading\n"
1460 "       myhalf3 lightnormal = myhalf3(normalize(LightPosition - position));\n"
1461 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1462 "#endif\n"
1463 "#ifdef USESPECULAR\n"
1464 "       // calculate directional shading\n"
1465 "       vec3 eyevector = position * -1.0;\n"
1466 "#  ifdef USEEXACTSPECULARMATH\n"
1467 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a);\n"
1468 "#  else\n"
1469 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(eyevector)));\n"
1470 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a);\n"
1471 "#  endif\n"
1472 "#endif\n"
1473 "\n"
1474 "#if defined(USESHADOWMAP2D)\n"
1475 "       fade *= ShadowMapCompare(CubeVector);\n"
1476 "#endif\n"
1477 "\n"
1478 "#ifdef USEDIFFUSE\n"
1479 "       gl_FragData[0] = vec4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
1480 "#else\n"
1481 "       gl_FragData[0] = vec4(DeferredColor_Ambient * fade, 1.0);\n"
1482 "#endif\n"
1483 "#ifdef USESPECULAR\n"
1484 "       gl_FragData[1] = vec4(DeferredColor_Specular * (specular * fade), 1.0);\n"
1485 "#else\n"
1486 "       gl_FragData[1] = vec4(0.0, 0.0, 0.0, 1.0);\n"
1487 "#endif\n"
1488 "\n"
1489 "# ifdef USECUBEFILTER\n"
1490 "       vec3 cubecolor = textureCube(Texture_Cube, CubeVector).rgb;\n"
1491 "       gl_FragData[0].rgb *= cubecolor;\n"
1492 "       gl_FragData[1].rgb *= cubecolor;\n"
1493 "# endif\n"
1494 "}\n"
1495 "#endif // FRAGMENT_SHADER\n"
1496 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
1497 "\n"
1498 "\n"
1499 "\n"
1500 "\n"
1501 "#ifdef MODE_DEFERREDBOUNCELIGHT\n"
1502 "#ifdef VERTEX_SHADER\n"
1503 "uniform highp mat4 ModelViewMatrix;\n"
1504 "void main(void)\n"
1505 "{\n"
1506 "       ModelViewPosition = ModelViewMatrix * Attrib_Position;\n"
1507 "       LightOriginInvRadius.xyz = (ModelViewMatrix * vec4(Attrib_TexCoord0.xyz, 1.0)).xyz;\n"
1508 "       LightOriginInvRadius.w = Attrib_TexCoord0.w;\n"
1509 "       LightColor = Attrib_Color;\n"
1510 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1511 "}\n"
1512 "#endif // VERTEX_SHADER\n"
1513 "\n"
1514 "#ifdef FRAGMENT_SHADER\n"
1515 "// ScreenToDepth = vec2(Far / (Far - Near), Far * Near / (Near - Far));\n"
1516 "uniform highp vec2 ScreenToDepth;\n"
1517 "uniform myhalf2 PixelToScreenTexCoord;\n"
1518 "void main(void)\n"
1519 "{\n"
1520 "       // calculate viewspace pixel position\n"
1521 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1522 "       vec3 position;\n"
1523 "       position.z = ScreenToDepth.y / (texture2D(Texture_ScreenDepth, ScreenTexCoord).r + ScreenToDepth.x);\n"
1524 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
1525 "       vec3 CubeVector = (position - LightOriginInvRadius.xyz) * LightOriginInvRadius.w;\n"
1526 "       gl_FragData[0] = vec4(LightColor.rgb * max(0.0, 1.0 - length(CubeVector)), 1.0);\n"
1527 "}\n"
1528 "#endif // FRAGMENT_SHADER\n"
1529 "#else // !MODE_DEFERREDBOUNCELIGHT\n"
1530 "\n"
1531 "\n"
1532 "\n"
1533 "\n"
1534 "#ifdef VERTEX_SHADER\n"
1535 "uniform highp mat4 TexMatrix;\n"
1536 "#ifdef USEVERTEXTEXTUREBLEND\n"
1537 "uniform highp mat4 BackgroundTexMatrix;\n"
1538 "#endif\n"
1539 "#ifdef MODE_LIGHTSOURCE\n"
1540 "uniform highp mat4 ModelToLight;\n"
1541 "#endif\n"
1542 "#ifdef USESHADOWMAPORTHO\n"
1543 "uniform highp mat4 ShadowMapMatrix;\n"
1544 "#endif\n"
1545 "#ifdef USEBOUNCEGRID\n"
1546 "uniform highp mat4 BounceGridMatrix;\n"
1547 "#endif\n"
1548 "void main(void)\n"
1549 "{\n"
1550 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
1551 "       VertexColor = Attrib_Color;\n"
1552 "#endif\n"
1553 "       // copy the surface texcoord\n"
1554 "       TexCoord = vec2(TexMatrix * Attrib_TexCoord0);\n"
1555 "#ifdef USEVERTEXTEXTUREBLEND\n"
1556 "       TexCoord2 = vec2(BackgroundTexMatrix * Attrib_TexCoord0);\n"
1557 "#endif\n"
1558 "#ifdef USELIGHTMAP\n"
1559 "       TexCoordLightmap = vec2(Attrib_TexCoord4);\n"
1560 "#endif\n"
1561 "\n"
1562 "#ifdef USEBOUNCEGRID\n"
1563 "       BounceGridTexCoord = vec3(BounceGridMatrix * Attrib_Position);\n"
1564 "#endif\n"
1565 "\n"
1566 "#ifdef MODE_LIGHTSOURCE\n"
1567 "       // transform vertex position into light attenuation/cubemap space\n"
1568 "       // (-1 to +1 across the light box)\n"
1569 "       CubeVector = vec3(ModelToLight * Attrib_Position);\n"
1570 "\n"
1571 "# ifdef USEDIFFUSE\n"
1572 "       // transform unnormalized light direction into tangent space\n"
1573 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
1574 "       //  normalize it per pixel)\n"
1575 "       vec3 lightminusvertex = LightPosition - Attrib_Position.xyz;\n"
1576 "       LightVector.x = dot(lightminusvertex, Attrib_TexCoord1.xyz);\n"
1577 "       LightVector.y = dot(lightminusvertex, Attrib_TexCoord2.xyz);\n"
1578 "       LightVector.z = dot(lightminusvertex, Attrib_TexCoord3.xyz);\n"
1579 "# endif\n"
1580 "#endif\n"
1581 "\n"
1582 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
1583 "       LightVector.x = dot(LightDir, Attrib_TexCoord1.xyz);\n"
1584 "       LightVector.y = dot(LightDir, Attrib_TexCoord2.xyz);\n"
1585 "       LightVector.z = dot(LightDir, Attrib_TexCoord3.xyz);\n"
1586 "#endif\n"
1587 "\n"
1588 "       // transform unnormalized eye direction into tangent space\n"
1589 "#ifdef USEEYEVECTOR\n"
1590 "       vec3 EyeVectorModelSpace = EyePosition - Attrib_Position.xyz;\n"
1591 "       EyeVector.x = dot(EyeVectorModelSpace, Attrib_TexCoord1.xyz);\n"
1592 "       EyeVector.y = dot(EyeVectorModelSpace, Attrib_TexCoord2.xyz);\n"
1593 "       EyeVector.z = dot(EyeVectorModelSpace, Attrib_TexCoord3.xyz);\n"
1594 "#endif\n"
1595 "\n"
1596 "#ifdef USEFOG\n"
1597 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - Attrib_Position.xyz;\n"
1598 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, Attrib_Position);\n"
1599 "#endif\n"
1600 "\n"
1601 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(USEREFLECTCUBE)\n"
1602 "       VectorS = Attrib_TexCoord1.xyz;\n"
1603 "       VectorT = Attrib_TexCoord2.xyz;\n"
1604 "       VectorR = Attrib_TexCoord3.xyz;\n"
1605 "#endif\n"
1606 "\n"
1607 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
1608 "       gl_Position = ModelViewProjectionMatrix * Attrib_Position;\n"
1609 "\n"
1610 "#ifdef USESHADOWMAPORTHO\n"
1611 "       ShadowMapTC = vec3(ShadowMapMatrix * gl_Position);\n"
1612 "#endif\n"
1613 "\n"
1614 "#ifdef USEREFLECTION\n"
1615 "       ModelViewProjectionPosition = gl_Position;\n"
1616 "#endif\n"
1617 "}\n"
1618 "#endif // VERTEX_SHADER\n"
1619 "\n"
1620 "\n"
1621 "\n"
1622 "\n"
1623 "#ifdef FRAGMENT_SHADER\n"
1624 "#ifdef USEDEFERREDLIGHTMAP\n"
1625 "uniform myhalf2 PixelToScreenTexCoord;\n"
1626 "uniform myhalf3 DeferredMod_Diffuse;\n"
1627 "uniform myhalf3 DeferredMod_Specular;\n"
1628 "#endif\n"
1629 "uniform myhalf3 Color_Ambient;\n"
1630 "uniform myhalf3 Color_Diffuse;\n"
1631 "uniform myhalf3 Color_Specular;\n"
1632 "uniform myhalf SpecularPower;\n"
1633 "#ifdef USEGLOW\n"
1634 "uniform myhalf3 Color_Glow;\n"
1635 "#endif\n"
1636 "uniform myhalf Alpha;\n"
1637 "#ifdef USEREFLECTION\n"
1638 "uniform mediump vec4 DistortScaleRefractReflect;\n"
1639 "uniform mediump vec4 ScreenScaleRefractReflect;\n"
1640 "uniform mediump vec4 ScreenCenterRefractReflect;\n"
1641 "uniform lowp vec4 ReflectColor;\n"
1642 "#endif\n"
1643 "#ifdef USEREFLECTCUBE\n"
1644 "uniform highp mat4 ModelToReflectCube;\n"
1645 "uniform sampler2D Texture_ReflectMask;\n"
1646 "uniform samplerCube Texture_ReflectCube;\n"
1647 "#endif\n"
1648 "#ifdef MODE_LIGHTDIRECTION\n"
1649 "uniform myhalf3 LightColor;\n"
1650 "#endif\n"
1651 "#ifdef MODE_LIGHTSOURCE\n"
1652 "uniform myhalf3 LightColor;\n"
1653 "#endif\n"
1654 "#ifdef USEBOUNCEGRID\n"
1655 "uniform sampler3D Texture_BounceGrid;\n"
1656 "uniform float BounceGridIntensity;\n"
1657 "#endif\n"
1658 "void main(void)\n"
1659 "{\n"
1660 "#ifdef USEOFFSETMAPPING\n"
1661 "       // apply offsetmapping\n"
1662 "       vec2 TexCoordOffset = OffsetMapping(TexCoord);\n"
1663 "#define TexCoord TexCoordOffset\n"
1664 "#endif\n"
1665 "\n"
1666 "       // combine the diffuse textures (base, pants, shirt)\n"
1667 "       myhalf4 color = myhalf4(texture2D(Texture_Color, TexCoord));\n"
1668 "#ifdef USEALPHAKILL\n"
1669 "       if (color.a < 0.5)\n"
1670 "               discard;\n"
1671 "#endif\n"
1672 "       color.a *= Alpha;\n"
1673 "#ifdef USECOLORMAPPING\n"
1674 "       color.rgb += myhalf3(texture2D(Texture_Pants, TexCoord)) * Color_Pants + myhalf3(texture2D(Texture_Shirt, TexCoord)) * Color_Shirt;\n"
1675 "#endif\n"
1676 "#ifdef USEVERTEXTEXTUREBLEND\n"
1677 "       myhalf terrainblend = clamp(myhalf(VertexColor.a) * color.a * 2.0 - 0.5, myhalf(0.0), myhalf(1.0));\n"
1678 "       //myhalf terrainblend = min(myhalf(VertexColor.a) * color.a * 2.0, myhalf(1.0));\n"
1679 "       //myhalf terrainblend = myhalf(VertexColor.a) * color.a > 0.5;\n"
1680 "       color.rgb = mix(myhalf3(texture2D(Texture_SecondaryColor, TexCoord2)), color.rgb, terrainblend);\n"
1681 "       color.a = 1.0;\n"
1682 "       //color = mix(myhalf4(1, 0, 0, 1), color, terrainblend);\n"
1683 "#endif\n"
1684 "\n"
1685 "       // get the surface normal\n"
1686 "#ifdef USEVERTEXTEXTUREBLEND\n"
1687 "       myhalf3 surfacenormal = normalize(mix(myhalf3(texture2D(Texture_SecondaryNormal, TexCoord2)), myhalf3(texture2D(Texture_Normal, TexCoord)), terrainblend) - myhalf3(0.5, 0.5, 0.5));\n"
1688 "#else\n"
1689 "       myhalf3 surfacenormal = normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5, 0.5, 0.5));\n"
1690 "#endif\n"
1691 "\n"
1692 "       // get the material colors\n"
1693 "       myhalf3 diffusetex = color.rgb;\n"
1694 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
1695 "# ifdef USEVERTEXTEXTUREBLEND\n"
1696 "       myhalf4 glosstex = mix(myhalf4(texture2D(Texture_SecondaryGloss, TexCoord2)), myhalf4(texture2D(Texture_Gloss, TexCoord)), terrainblend);\n"
1697 "# else\n"
1698 "       myhalf4 glosstex = myhalf4(texture2D(Texture_Gloss, TexCoord));\n"
1699 "# endif\n"
1700 "#endif\n"
1701 "\n"
1702 "#ifdef USEREFLECTCUBE\n"
1703 "       vec3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
1704 "       vec3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
1705 "       vec3 ReflectCubeTexCoord = vec3(ModelToReflectCube * vec4(ModelReflectVector, 0));\n"
1706 "       diffusetex += myhalf3(texture2D(Texture_ReflectMask, TexCoord)) * myhalf3(textureCube(Texture_ReflectCube, ReflectCubeTexCoord));\n"
1707 "#endif\n"
1708 "\n"
1709 "\n"
1710 "\n"
1711 "\n"
1712 "#ifdef MODE_LIGHTSOURCE\n"
1713 "       // light source\n"
1714 "#ifdef USEDIFFUSE\n"
1715 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1716 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1717 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
1718 "#ifdef USESPECULAR\n"
1719 "#ifdef USEEXACTSPECULARMATH\n"
1720 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1721 "#else\n"
1722 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1723 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1724 "#endif\n"
1725 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
1726 "#endif\n"
1727 "#else\n"
1728 "       color.rgb = diffusetex * Color_Ambient;\n"
1729 "#endif\n"
1730 "       color.rgb *= LightColor;\n"
1731 "       color.rgb *= myhalf(texture2D(Texture_Attenuation, vec2(length(CubeVector), 0.0)));\n"
1732 "#if defined(USESHADOWMAP2D)\n"
1733 "       color.rgb *= ShadowMapCompare(CubeVector);\n"
1734 "#endif\n"
1735 "# ifdef USECUBEFILTER\n"
1736 "       color.rgb *= myhalf3(textureCube(Texture_Cube, CubeVector));\n"
1737 "# endif\n"
1738 "#endif // MODE_LIGHTSOURCE\n"
1739 "\n"
1740 "\n"
1741 "\n"
1742 "\n"
1743 "#ifdef MODE_LIGHTDIRECTION\n"
1744 "#define SHADING\n"
1745 "#ifdef USEDIFFUSE\n"
1746 "       myhalf3 lightnormal = myhalf3(normalize(LightVector));\n"
1747 "#endif\n"
1748 "#define lightcolor LightColor\n"
1749 "#endif // MODE_LIGHTDIRECTION\n"
1750 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1751 "#define SHADING\n"
1752 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
1753 "       myhalf3 lightnormal_modelspace = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1754 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1755 "       // convert modelspace light vector to tangentspace\n"
1756 "       myhalf3 lightnormal;\n"
1757 "       lightnormal.x = dot(lightnormal_modelspace, myhalf3(VectorS));\n"
1758 "       lightnormal.y = dot(lightnormal_modelspace, myhalf3(VectorT));\n"
1759 "       lightnormal.z = dot(lightnormal_modelspace, myhalf3(VectorR));\n"
1760 "       lightnormal = normalize(lightnormal); // VectorS/T/R are not always perfectly normalized, and EXACTSPECULARMATH is very picky about this\n"
1761 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
1762 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
1763 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
1764 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
1765 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
1766 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
1767 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
1768 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
1769 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
1770 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
1771 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
1772 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
1773 "#define SHADING\n"
1774 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
1775 "       myhalf3 lightnormal = myhalf3(texture2D(Texture_Deluxemap, TexCoordLightmap)) * 2.0 + myhalf3(-1.0, -1.0, -1.0);\n"
1776 "       myhalf3 lightcolor = myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap));\n"
1777 "#endif\n"
1778 "\n"
1779 "\n"
1780 "\n"
1781 "\n"
1782 "#ifdef MODE_FAKELIGHT\n"
1783 "#define SHADING\n"
1784 "myhalf3 lightnormal = myhalf3(normalize(EyeVector));\n"
1785 "myhalf3 lightcolor = myhalf3(1.0);\n"
1786 "#endif // MODE_FAKELIGHT\n"
1787 "\n"
1788 "\n"
1789 "\n"
1790 "\n"
1791 "#ifdef MODE_LIGHTMAP\n"
1792 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(texture2D(Texture_Lightmap, TexCoordLightmap)) * Color_Diffuse);\n"
1793 "#endif // MODE_LIGHTMAP\n"
1794 "#ifdef MODE_VERTEXCOLOR\n"
1795 "       color.rgb = diffusetex * (Color_Ambient + myhalf3(VertexColor.rgb) * Color_Diffuse);\n"
1796 "#endif // MODE_VERTEXCOLOR\n"
1797 "#ifdef MODE_FLATCOLOR\n"
1798 "       color.rgb = diffusetex * Color_Ambient;\n"
1799 "#endif // MODE_FLATCOLOR\n"
1800 "\n"
1801 "\n"
1802 "\n"
1803 "\n"
1804 "#ifdef SHADING\n"
1805 "# ifdef USEDIFFUSE\n"
1806 "       myhalf diffuse = myhalf(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
1807 "#  ifdef USESPECULAR\n"
1808 "#   ifdef USEEXACTSPECULARMATH\n"
1809 "       myhalf specular = pow(myhalf(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a);\n"
1810 "#   else\n"
1811 "       myhalf3 specularnormal = normalize(lightnormal + myhalf3(normalize(EyeVector)));\n"
1812 "       myhalf specular = pow(myhalf(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a);\n"
1813 "#   endif\n"
1814 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
1815 "#  else\n"
1816 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
1817 "#  endif\n"
1818 "# else\n"
1819 "       color.rgb = diffusetex * Color_Ambient;\n"
1820 "# endif\n"
1821 "#endif\n"
1822 "\n"
1823 "#ifdef USESHADOWMAPORTHO\n"
1824 "       color.rgb *= ShadowMapCompare(ShadowMapTC);\n"
1825 "#endif\n"
1826 "\n"
1827 "#ifdef USEDEFERREDLIGHTMAP\n"
1828 "       vec2 ScreenTexCoord = gl_FragCoord.xy * PixelToScreenTexCoord;\n"
1829 "       color.rgb += diffusetex * myhalf3(texture2D(Texture_ScreenDiffuse, ScreenTexCoord)) * DeferredMod_Diffuse;\n"
1830 "       color.rgb += glosstex.rgb * myhalf3(texture2D(Texture_ScreenSpecular, ScreenTexCoord)) * DeferredMod_Specular;\n"
1831 "#endif\n"
1832 "\n"
1833 "#ifdef USEBOUNCEGRID\n"
1834 "       color.rgb += diffusetex * myhalf3(texture3D(Texture_BounceGrid, BounceGridTexCoord)) * BounceGridIntensity;\n"
1835 "#endif\n"
1836 "\n"
1837 "#ifdef USEGLOW\n"
1838 "#ifdef USEVERTEXTEXTUREBLEND\n"
1839 "       color.rgb += mix(myhalf3(texture2D(Texture_SecondaryGlow, TexCoord2)), myhalf3(texture2D(Texture_Glow, TexCoord)), terrainblend) * Color_Glow;\n"
1840 "#else\n"
1841 "       color.rgb += myhalf3(texture2D(Texture_Glow, TexCoord)) * Color_Glow;\n"
1842 "#endif\n"
1843 "#endif\n"
1844 "\n"
1845 "#ifdef USEFOG\n"
1846 "       color.rgb = FogVertex(color.rgb);\n"
1847 "#endif\n"
1848 "\n"
1849 "       // 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"
1850 "#ifdef USEREFLECTION\n"
1851 "       vec4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
1852 "       //vec4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
1853 "       vec2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
1854 "       vec2 ScreenTexCoord = SafeScreenTexCoord + vec3(normalize(myhalf3(texture2D(Texture_Normal, TexCoord)) - myhalf3(0.5))).xy * DistortScaleRefractReflect.zw;\n"
1855 "       // FIXME temporary hack to detect the case that the reflection\n"
1856 "       // gets blackened at edges due to leaving the area that contains actual\n"
1857 "       // content.\n"
1858 "       // Remove this 'ack once we have a better way to stop this thing from\n"
1859 "       // 'appening.\n"
1860 "       float f = min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, 0.01)).rgb) / 0.05);\n"
1861 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(0.01, -0.01)).rgb) / 0.05);\n"
1862 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, 0.01)).rgb) / 0.05);\n"
1863 "       f      *= min(1.0, length(texture2D(Texture_Reflection, ScreenTexCoord + vec2(-0.01, -0.01)).rgb) / 0.05);\n"
1864 "       ScreenTexCoord = mix(SafeScreenTexCoord, ScreenTexCoord, f);\n"
1865 "       color.rgb = mix(color.rgb, myhalf3(texture2D(Texture_Reflection, ScreenTexCoord)) * ReflectColor.rgb, ReflectColor.a);\n"
1866 "#endif\n"
1867 "\n"
1868 "       gl_FragColor = vec4(color);\n"
1869 "}\n"
1870 "#endif // FRAGMENT_SHADER\n"
1871 "\n"
1872 "#endif // !MODE_DEFERREDBOUNCELIGHT\n"
1873 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
1874 "#endif // !MODE_DEFERREDGEOMETRY\n"
1875 "#endif // !MODE_WATER\n"
1876 "#endif // !MODE_REFRACTION\n"
1877 "#endif // !MODE_BLOOMBLUR\n"
1878 "#endif // !MODE_GENERIC\n"
1879 "#endif // !MODE_POSTPROCESS\n"
1880 "#endif // !MODE_SHOWDEPTH\n"
1881 "#endif // !MODE_DEPTH_OR_SHADOW\n"
1882 ;
1883
1884 /*
1885 =========================================================================================================================================================
1886
1887
1888
1889 =========================================================================================================================================================
1890
1891
1892
1893 =========================================================================================================================================================
1894
1895
1896
1897 =========================================================================================================================================================
1898
1899
1900
1901 =========================================================================================================================================================
1902
1903
1904
1905 =========================================================================================================================================================
1906
1907
1908
1909 =========================================================================================================================================================
1910 */
1911
1912 const char *builtinhlslshaderstring =
1913 "// ambient+diffuse+specular+normalmap+attenuation+cubemap+fog shader\n"
1914 "// written by Forest 'LordHavoc' Hale\n"
1915 "// shadowmapping enhancements by Lee 'eihrul' Salzman\n"
1916 "\n"
1917 "// FIXME: we need to get rid of ModelViewProjectionPosition to make room for the texcoord for this\n"
1918 "#if defined(USEREFLECTION)\n"
1919 "#undef USESHADOWMAPORTHO\n"
1920 "#endif\n"
1921 "\n"
1922 "#if defined(USEFOGINSIDE) || defined(USEFOGOUTSIDE) || defined(USEFOGHEIGHTTEXTURE)\n"
1923 "# define USEFOG\n"
1924 "#endif\n"
1925 "#if defined(MODE_LIGHTMAP) || defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
1926 "#define USELIGHTMAP\n"
1927 "#endif\n"
1928 "#if defined(USESPECULAR) || defined(USEOFFSETMAPPING) || defined(USEREFLECTCUBE) || defined(MODE_FAKELIGHT)\n"
1929 "#define USEEYEVECTOR\n"
1930 "#endif\n"
1931 "\n"
1932 "#ifdef FRAGMENT_SHADER\n"
1933 "#ifdef HLSL\n"
1934 "//#undef USESHADOWMAPPCF\n"
1935 "//#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1936 "#define texDepth2D(tex,texcoord) dot(tex2D(tex,texcoord).rgb, float3(1.0, 255.0/65536.0, 255.0/16777216.0))\n"
1937 "#else\n"
1938 "#define texDepth2D(tex,texcoord) tex2D(tex,texcoord).r\n"
1939 "#endif\n"
1940 "#endif\n"
1941 "\n"
1942 "#ifdef MODE_DEPTH_OR_SHADOW\n"
1943 "#ifdef VERTEX_SHADER\n"
1944 "void main\n"
1945 "(\n"
1946 "float4 gl_Vertex : POSITION,\n"
1947 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1948 "out float4 gl_Position : POSITION,\n"
1949 "out float Depth : TEXCOORD0\n"
1950 ")\n"
1951 "{\n"
1952 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1953 "       Depth = gl_Position.z;\n"
1954 "}\n"
1955 "#endif\n"
1956 "\n"
1957 "#ifdef FRAGMENT_SHADER\n"
1958 "void main\n"
1959 "(\n"
1960 "float Depth : TEXCOORD0,\n"
1961 "out float4 gl_FragColor : COLOR\n"
1962 ")\n"
1963 "{\n"
1964 "//     float4 temp = float4(Depth,Depth*(65536.0/255.0),Depth*(16777216.0/255.0),0.0);\n"
1965 "       float4 temp = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
1966 "       temp.yz -= floor(temp.yz);\n"
1967 "       gl_FragColor = temp;\n"
1968 "//     gl_FragColor = float4(Depth,0,0,0);\n"
1969 "}\n"
1970 "#endif\n"
1971 "#else // !MODE_DEPTH_ORSHADOW\n"
1972 "\n"
1973 "\n"
1974 "\n"
1975 "\n"
1976 "#ifdef MODE_SHOWDEPTH\n"
1977 "#ifdef VERTEX_SHADER\n"
1978 "void main\n"
1979 "(\n"
1980 "float4 gl_Vertex : POSITION,\n"
1981 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
1982 "out float4 gl_Position : POSITION,\n"
1983 "out float4 gl_FrontColor : COLOR0\n"
1984 ")\n"
1985 "{\n"
1986 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
1987 "       gl_FrontColor = float4(gl_Position.z, gl_Position.z, gl_Position.z, 1.0);\n"
1988 "}\n"
1989 "#endif\n"
1990 "\n"
1991 "#ifdef FRAGMENT_SHADER\n"
1992 "void main\n"
1993 "(\n"
1994 "float4 gl_FrontColor : COLOR0,\n"
1995 "out float4 gl_FragColor : COLOR\n"
1996 ")\n"
1997 "{\n"
1998 "       gl_FragColor = gl_FrontColor;\n"
1999 "}\n"
2000 "#endif\n"
2001 "#else // !MODE_SHOWDEPTH\n"
2002 "\n"
2003 "\n"
2004 "\n"
2005 "\n"
2006 "#ifdef MODE_POSTPROCESS\n"
2007 "\n"
2008 "#ifdef VERTEX_SHADER\n"
2009 "void main\n"
2010 "(\n"
2011 "float4 gl_Vertex : POSITION,\n"
2012 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2013 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2014 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2015 "out float4 gl_Position : POSITION,\n"
2016 "out float2 TexCoord1 : TEXCOORD0,\n"
2017 "out float2 TexCoord2 : TEXCOORD1\n"
2018 ")\n"
2019 "{\n"
2020 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2021 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2022 "#ifdef USEBLOOM\n"
2023 "       TexCoord2 = gl_MultiTexCoord4.xy;\n"
2024 "#endif\n"
2025 "}\n"
2026 "#endif\n"
2027 "\n"
2028 "#ifdef FRAGMENT_SHADER\n"
2029 "void main\n"
2030 "(\n"
2031 "float2 TexCoord1 : TEXCOORD0,\n"
2032 "float2 TexCoord2 : TEXCOORD1,\n"
2033 "uniform sampler Texture_First : register(s0),\n"
2034 "#ifdef USEBLOOM\n"
2035 "uniform sampler Texture_Second : register(s1),\n"
2036 "#endif\n"
2037 "#ifdef USEGAMMARAMPS\n"
2038 "uniform sampler Texture_GammaRamps : register(s2),\n"
2039 "#endif\n"
2040 "#ifdef USESATURATION\n"
2041 "uniform float Saturation : register(c30),\n"
2042 "#endif\n"
2043 "#ifdef USEVIEWTINT\n"
2044 "uniform float4 ViewTintColor : register(c41),\n"
2045 "#endif\n"
2046 "uniform float4 UserVec1 : register(c37),\n"
2047 "uniform float4 UserVec2 : register(c38),\n"
2048 "uniform float4 UserVec3 : register(c39),\n"
2049 "uniform float4 UserVec4 : register(c40),\n"
2050 "uniform float ClientTime : register(c2),\n"
2051 "uniform float2 PixelSize : register(c25),\n"
2052 "uniform float4 BloomColorSubtract : register(c43),\n"
2053 "out float4 gl_FragColor : COLOR\n"
2054 ")\n"
2055 "{\n"
2056 "       gl_FragColor = tex2D(Texture_First, TexCoord1);\n"
2057 "#ifdef USEBLOOM\n"
2058 "       gl_FragColor += max(float4(0,0,0,0), tex2D(Texture_Second, TexCoord2) - BloomColorSubtract);\n"
2059 "#endif\n"
2060 "#ifdef USEVIEWTINT\n"
2061 "       gl_FragColor = lerp(gl_FragColor, ViewTintColor, ViewTintColor.a);\n"
2062 "#endif\n"
2063 "\n"
2064 "#ifdef USEPOSTPROCESSING\n"
2065 "// do r_glsl_dumpshader, edit glsl/default.glsl, and replace this by your own postprocessing if you want\n"
2066 "// 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"
2067 "       float sobel = 1.0;\n"
2068 "       // float2 ts = textureSize(Texture_First, 0);\n"
2069 "       // float2 px = float2(1/ts.x, 1/ts.y);\n"
2070 "       float2 px = PixelSize;\n"
2071 "       float3 x1 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2072 "       float3 x2 = tex2D(Texture_First, TexCoord1 + float2(-px.x,  0.0)).rgb;\n"
2073 "       float3 x3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2074 "       float3 x4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2075 "       float3 x5 = tex2D(Texture_First, TexCoord1 + float2( px.x,  0.0)).rgb;\n"
2076 "       float3 x6 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2077 "       float3 y1 = tex2D(Texture_First, TexCoord1 + float2( px.x,-px.y)).rgb;\n"
2078 "       float3 y2 = tex2D(Texture_First, TexCoord1 + float2(  0.0,-px.y)).rgb;\n"
2079 "       float3 y3 = tex2D(Texture_First, TexCoord1 + float2(-px.x,-px.y)).rgb;\n"
2080 "       float3 y4 = tex2D(Texture_First, TexCoord1 + float2( px.x, px.y)).rgb;\n"
2081 "       float3 y5 = tex2D(Texture_First, TexCoord1 + float2(  0.0, px.y)).rgb;\n"
2082 "       float3 y6 = tex2D(Texture_First, TexCoord1 + float2(-px.x, px.y)).rgb;\n"
2083 "       float px1 = -1.0 * dot(float3(0.3, 0.59, 0.11), x1);\n"
2084 "       float px2 = -2.0 * dot(float3(0.3, 0.59, 0.11), x2);\n"
2085 "       float px3 = -1.0 * dot(float3(0.3, 0.59, 0.11), x3);\n"
2086 "       float px4 =  1.0 * dot(float3(0.3, 0.59, 0.11), x4);\n"
2087 "       float px5 =  2.0 * dot(float3(0.3, 0.59, 0.11), x5);\n"
2088 "       float px6 =  1.0 * dot(float3(0.3, 0.59, 0.11), x6);\n"
2089 "       float py1 = -1.0 * dot(float3(0.3, 0.59, 0.11), y1);\n"
2090 "       float py2 = -2.0 * dot(float3(0.3, 0.59, 0.11), y2);\n"
2091 "       float py3 = -1.0 * dot(float3(0.3, 0.59, 0.11), y3);\n"
2092 "       float py4 =  1.0 * dot(float3(0.3, 0.59, 0.11), y4);\n"
2093 "       float py5 =  2.0 * dot(float3(0.3, 0.59, 0.11), y5);\n"
2094 "       float py6 =  1.0 * dot(float3(0.3, 0.59, 0.11), y6);\n"
2095 "       sobel = 0.25 * abs(px1 + px2 + px3 + px4 + px5 + px6) + 0.25 * abs(py1 + py2 + py3 + py4 + py5 + py6);\n"
2096 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.987688, -0.156434)) * UserVec1.y;\n"
2097 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.156434, -0.891007)) * UserVec1.y;\n"
2098 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.891007, -0.453990)) * UserVec1.y;\n"
2099 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2( 0.707107,  0.707107)) * UserVec1.y;\n"
2100 "       gl_FragColor += tex2D(Texture_First, TexCoord1 + PixelSize*UserVec1.x*float2(-0.453990,  0.891007)) * UserVec1.y;\n"
2101 "       gl_FragColor /= (1.0 + 5.0 * UserVec1.y);\n"
2102 "       gl_FragColor.rgb = gl_FragColor.rgb * (1.0 + UserVec2.x) + float3(1,1,1)*max(0.0, sobel - UserVec2.z)*UserVec2.y;\n"
2103 "#endif\n"
2104 "\n"
2105 "#ifdef USESATURATION\n"
2106 "       //apply saturation BEFORE gamma ramps, so v_glslgamma value does not matter\n"
2107 "       float y = dot(gl_FragColor.rgb, float3(0.299, 0.587, 0.114));\n"
2108 "       // 'vampire sight' effect, wheres red is compensated\n"
2109 "       #ifdef SATURATION_REDCOMPENSATE\n"
2110 "               float rboost = max(0.0, (gl_FragColor.r - max(gl_FragColor.g, gl_FragColor.b))*(1.0 - Saturation));\n"
2111 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2112 "               gl_FragColor.r += r;\n"
2113 "       #else\n"
2114 "               // normal desaturation\n"
2115 "               //gl_FragColor = float3(y,y,y) + (gl_FragColor.rgb - float3(y)) * Saturation;\n"
2116 "               gl_FragColor.rgb = lerp(float3(y,y,y), gl_FragColor.rgb, Saturation);\n"
2117 "       #endif\n"
2118 "#endif\n"
2119 "\n"
2120 "#ifdef USEGAMMARAMPS\n"
2121 "       gl_FragColor.r = tex2D(Texture_GammaRamps, float2(gl_FragColor.r, 0)).r;\n"
2122 "       gl_FragColor.g = tex2D(Texture_GammaRamps, float2(gl_FragColor.g, 0)).g;\n"
2123 "       gl_FragColor.b = tex2D(Texture_GammaRamps, float2(gl_FragColor.b, 0)).b;\n"
2124 "#endif\n"
2125 "}\n"
2126 "#endif\n"
2127 "#else // !MODE_POSTPROCESS\n"
2128 "\n"
2129 "\n"
2130 "\n"
2131 "\n"
2132 "#ifdef MODE_GENERIC\n"
2133 "#ifdef VERTEX_SHADER\n"
2134 "void main\n"
2135 "(\n"
2136 "float4 gl_Vertex : POSITION,\n"
2137 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2138 "float4 gl_Color : COLOR0,\n"
2139 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2140 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2141 "out float4 gl_Position : POSITION,\n"
2142 "#ifdef USEDIFFUSE\n"
2143 "out float2 TexCoord1 : TEXCOORD0,\n"
2144 "#endif\n"
2145 "#ifdef USESPECULAR\n"
2146 "out float2 TexCoord2 : TEXCOORD1,\n"
2147 "#endif\n"
2148 "out float4 gl_FrontColor : COLOR\n"
2149 ")\n"
2150 "{\n"
2151 "#ifdef HLSL\n"
2152 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2153 "#else\n"
2154 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2155 "#endif\n"
2156 "#ifdef USEDIFFUSE\n"
2157 "       TexCoord1 = gl_MultiTexCoord0.xy;\n"
2158 "#endif\n"
2159 "#ifdef USESPECULAR\n"
2160 "       TexCoord2 = gl_MultiTexCoord1.xy;\n"
2161 "#endif\n"
2162 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2163 "}\n"
2164 "#endif\n"
2165 "\n"
2166 "#ifdef FRAGMENT_SHADER\n"
2167 "\n"
2168 "void main\n"
2169 "(\n"
2170 "float4 gl_FrontColor : COLOR0,\n"
2171 "float2 TexCoord1 : TEXCOORD0,\n"
2172 "float2 TexCoord2 : TEXCOORD1,\n"
2173 "#ifdef USEDIFFUSE\n"
2174 "uniform sampler Texture_First : register(s0),\n"
2175 "#endif\n"
2176 "#ifdef USESPECULAR\n"
2177 "uniform sampler Texture_Second : register(s1),\n"
2178 "#endif\n"
2179 "out float4 gl_FragColor : COLOR\n"
2180 ")\n"
2181 "{\n"
2182 "#ifdef USEVIEWTINT\n"
2183 "       gl_FragColor = gl_FrontColor;\n"
2184 "#else\n"
2185 "       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n"
2186 "#endif\n"
2187 "#ifdef USEDIFFUSE\n"
2188 "       gl_FragColor *= tex2D(Texture_First, TexCoord1);\n"
2189 "#endif\n"
2190 "\n"
2191 "#ifdef USESPECULAR\n"
2192 "       float4 tex2 = tex2D(Texture_Second, TexCoord2);\n"
2193 "# ifdef USECOLORMAPPING\n"
2194 "       gl_FragColor *= tex2;\n"
2195 "# endif\n"
2196 "# ifdef USEGLOW\n"
2197 "       gl_FragColor += tex2;\n"
2198 "# endif\n"
2199 "# ifdef USEVERTEXTEXTUREBLEND\n"
2200 "       gl_FragColor = lerp(gl_FragColor, tex2, tex2.a);\n"
2201 "# endif\n"
2202 "#endif\n"
2203 "}\n"
2204 "#endif\n"
2205 "#else // !MODE_GENERIC\n"
2206 "\n"
2207 "\n"
2208 "\n"
2209 "\n"
2210 "#ifdef MODE_BLOOMBLUR\n"
2211 "#ifdef VERTEX_SHADER\n"
2212 "void main\n"
2213 "(\n"
2214 "float4 gl_Vertex : POSITION,\n"
2215 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2216 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2217 "out float4 gl_Position : POSITION,\n"
2218 "out float2 TexCoord : TEXCOORD0\n"
2219 ")\n"
2220 "{\n"
2221 "       TexCoord = gl_MultiTexCoord0.xy;\n"
2222 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2223 "}\n"
2224 "#endif\n"
2225 "\n"
2226 "#ifdef FRAGMENT_SHADER\n"
2227 "\n"
2228 "void main\n"
2229 "(\n"
2230 "float2 TexCoord : TEXCOORD0,\n"
2231 "uniform sampler Texture_First : register(s0),\n"
2232 "uniform float4 BloomBlur_Parameters : register(c1),\n"
2233 "out float4 gl_FragColor : COLOR\n"
2234 ")\n"
2235 "{\n"
2236 "       int i;\n"
2237 "       float2 tc = TexCoord;\n"
2238 "       float3 color = tex2D(Texture_First, tc).rgb;\n"
2239 "       tc += BloomBlur_Parameters.xy;\n"
2240 "       for (i = 1;i < SAMPLES;i++)\n"
2241 "       {\n"
2242 "               color += tex2D(Texture_First, tc).rgb;\n"
2243 "               tc += BloomBlur_Parameters.xy;\n"
2244 "       }\n"
2245 "       gl_FragColor = float4(color * BloomBlur_Parameters.z + float3(BloomBlur_Parameters.w), 1);\n"
2246 "}\n"
2247 "#endif\n"
2248 "#else // !MODE_BLOOMBLUR\n"
2249 "#ifdef MODE_REFRACTION\n"
2250 "#ifdef VERTEX_SHADER\n"
2251 "void main\n"
2252 "(\n"
2253 "float4 gl_Vertex : POSITION,\n"
2254 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2255 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2256 "uniform float4x4 TexMatrix : register(c0),\n"
2257 "uniform float3 EyePosition : register(c24),\n"
2258 "out float4 gl_Position : POSITION,\n"
2259 "out float2 TexCoord : TEXCOORD0,\n"
2260 "out float3 EyeVector : TEXCOORD1,\n"
2261 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2262 ")\n"
2263 "{\n"
2264 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2265 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2266 "       ModelViewProjectionPosition = gl_Position;\n"
2267 "}\n"
2268 "#endif\n"
2269 "\n"
2270 "#ifdef FRAGMENT_SHADER\n"
2271 "void main\n"
2272 "(\n"
2273 "float2 TexCoord : TEXCOORD0,\n"
2274 "float3 EyeVector : TEXCOORD1,\n"
2275 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2276 "uniform sampler Texture_Normal : register(s0),\n"
2277 "uniform sampler Texture_Refraction : register(s3),\n"
2278 "uniform sampler Texture_Reflection : register(s7),\n"
2279 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2280 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2281 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2282 "uniform float4 RefractColor : register(c29),\n"
2283 "out float4 gl_FragColor : COLOR\n"
2284 ")\n"
2285 "{\n"
2286 "       float2 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect.xy * (1.0 / ModelViewProjectionPosition.w);\n"
2287 "       //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"
2288 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect.xy;\n"
2289 "       float2 ScreenTexCoord = SafeScreenTexCoord + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy * DistortScaleRefractReflect.xy;\n"
2290 "       // FIXME temporary hack to detect the case that the reflection\n"
2291 "       // gets blackened at edges due to leaving the area that contains actual\n"
2292 "       // content.\n"
2293 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2294 "       // 'appening.\n"
2295 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
2296 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
2297 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2298 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2299 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
2300 "       gl_FragColor = float4(tex2D(Texture_Refraction, ScreenTexCoord).rgb, 1) * RefractColor;\n"
2301 "}\n"
2302 "#endif\n"
2303 "#else // !MODE_REFRACTION\n"
2304 "\n"
2305 "\n"
2306 "\n"
2307 "\n"
2308 "#ifdef MODE_WATER\n"
2309 "#ifdef VERTEX_SHADER\n"
2310 "\n"
2311 "void main\n"
2312 "(\n"
2313 "float4 gl_Vertex : POSITION,\n"
2314 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2315 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2316 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2317 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2318 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2319 "uniform float4x4 TexMatrix : register(c0),\n"
2320 "uniform float3 EyePosition : register(c24),\n"
2321 "out float4 gl_Position : POSITION,\n"
2322 "out float2 TexCoord : TEXCOORD0,\n"
2323 "out float3 EyeVector : TEXCOORD1,\n"
2324 "out float4 ModelViewProjectionPosition : TEXCOORD2\n"
2325 ")\n"
2326 "{\n"
2327 "       TexCoord = mul(TexMatrix, gl_MultiTexCoord0).xy;\n"
2328 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2329 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2330 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2331 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2332 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2333 "       ModelViewProjectionPosition = gl_Position;\n"
2334 "}\n"
2335 "#endif\n"
2336 "\n"
2337 "#ifdef FRAGMENT_SHADER\n"
2338 "void main\n"
2339 "(\n"
2340 "float2 TexCoord : TEXCOORD0,\n"
2341 "float3 EyeVector : TEXCOORD1,\n"
2342 "float4 ModelViewProjectionPosition : TEXCOORD2,\n"
2343 "uniform sampler Texture_Normal : register(s0),\n"
2344 "uniform sampler Texture_Refraction : register(s3),\n"
2345 "uniform sampler Texture_Reflection : register(s7),\n"
2346 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
2347 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
2348 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
2349 "uniform float4 RefractColor : register(c29),\n"
2350 "uniform float4 ReflectColor : register(c26),\n"
2351 "uniform float ReflectFactor : register(c27),\n"
2352 "uniform float ReflectOffset : register(c28),\n"
2353 "out float4 gl_FragColor : COLOR\n"
2354 ")\n"
2355 "{\n"
2356 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
2357 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2358 "       float4 SafeScreenTexCoord = ModelViewProjectionPosition.xyxy * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
2359 "       //SafeScreenTexCoord = gl_FragCoord.xyxy * float4(1.0 / 1920.0, 1.0 / 1200.0, 1.0 / 1920.0, 1.0 / 1200.0);\n"
2360 "       float4 ScreenTexCoord = SafeScreenTexCoord + float2(normalize(tex2D(Texture_Normal, TexCoord).rgb - float3(0.5,0.5,0.5)).xy).xyxy * DistortScaleRefractReflect;\n"
2361 "       // FIXME temporary hack to detect the case that the reflection\n"
2362 "       // gets blackened at edges due to leaving the area that contains actual\n"
2363 "       // content.\n"
2364 "       // Remove this 'ack once we have a better way to stop this thing from\n"
2365 "       // 'appening.\n"
2366 "       float f = min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, 0.01)).rgb) / 0.05);\n"
2367 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(0.01, -0.01)).rgb) / 0.05);\n"
2368 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2369 "       f      *= min(1.0, length(tex2D(Texture_Refraction, ScreenTexCoord.xy + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2370 "       ScreenTexCoord.xy = lerp(SafeScreenTexCoord.xy, ScreenTexCoord.xy, f);\n"
2371 "       f  = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, 0.01)).rgb) / 0.05);\n"
2372 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(0.01, -0.01)).rgb) / 0.05);\n"
2373 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, 0.01)).rgb) / 0.05);\n"
2374 "       f *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord.zw + float2(-0.01, -0.01)).rgb) / 0.05);\n"
2375 "       ScreenTexCoord.zw = lerp(SafeScreenTexCoord.zw, ScreenTexCoord.zw, f);\n"
2376 "       float Fresnel = pow(min(1.0, 1.0 - float(normalize(EyeVector).z)), 2.0) * ReflectFactor + ReflectOffset;\n"
2377 "       gl_FragColor = lerp(float4(tex2D(Texture_Refraction, ScreenTexCoord.xy).rgb, 1) * RefractColor, float4(tex2D(Texture_Reflection, ScreenTexCoord.zw).rgb, 1) * ReflectColor, Fresnel);\n"
2378 "}\n"
2379 "#endif\n"
2380 "#else // !MODE_WATER\n"
2381 "\n"
2382 "\n"
2383 "\n"
2384 "\n"
2385 "// 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"
2386 "\n"
2387 "// fragment shader specific:\n"
2388 "#ifdef FRAGMENT_SHADER\n"
2389 "\n"
2390 "#ifdef USEFOG\n"
2391 "float3 FogVertex(float3 surfacecolor, float3 FogColor, float3 EyeVectorModelSpace, float FogPlaneVertexDist, float FogRangeRecip, float FogPlaneViewDist, float FogHeightFade, sampler Texture_FogMask, sampler Texture_FogHeightTexture)\n"
2392 "{\n"
2393 "       float fogfrac;\n"
2394 "#ifdef USEFOGHEIGHTTEXTURE\n"
2395 "       float4 fogheightpixel = tex2D(Texture_FogHeightTexture, float2(1,1) + float2(FogPlaneVertexDist, FogPlaneViewDist) * (-2.0 * FogHeightFade));\n"
2396 "       fogfrac = fogheightpixel.a;\n"
2397 "       return lerp(fogheightpixel.rgb * FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2398 "#else\n"
2399 "# ifdef USEFOGOUTSIDE\n"
2400 "       fogfrac = min(0.0, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0, min(0.0, FogPlaneVertexDist) * FogHeightFade);\n"
2401 "# else\n"
2402 "       fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0, FogPlaneVertexDist)) * min(1.0, (min(0.0, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);\n"
2403 "# endif\n"
2404 "       return lerp(FogColor, surfacecolor, tex2D(Texture_FogMask, float2(length(EyeVectorModelSpace)*fogfrac*FogRangeRecip, 0.0)).r);\n"
2405 "#endif\n"
2406 "}\n"
2407 "#endif\n"
2408 "\n"
2409 "#ifdef USEOFFSETMAPPING\n"
2410 "float2 OffsetMapping(float2 TexCoord, float OffsetMapping_Scale, float3 EyeVector, sampler Texture_Normal)\n"
2411 "{\n"
2412 "#ifdef USEOFFSETMAPPING_RELIEFMAPPING\n"
2413 "       // 14 sample relief mapping: linear search and then binary search\n"
2414 "       // this basically steps forward a small amount repeatedly until it finds\n"
2415 "       // itself inside solid, then jitters forward and back using decreasing\n"
2416 "       // amounts to find the impact\n"
2417 "       //float3 OffsetVector = float3(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1), -1);\n"
2418 "       //float3 OffsetVector = float3(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2419 "       float3 OffsetVector = float3(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1), -1);\n"
2420 "       float3 RT = float3(TexCoord, 1);\n"
2421 "       OffsetVector *= 0.1;\n"
2422 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2423 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2424 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2425 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2426 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2427 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2428 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2429 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2430 "       RT += OffsetVector *  step(tex2D(Texture_Normal, RT.xy).a, RT.z);\n"
2431 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z)          - 0.5);\n"
2432 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.5    - 0.25);\n"
2433 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.25   - 0.125);\n"
2434 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.125  - 0.0625);\n"
2435 "       RT += OffsetVector * (step(tex2D(Texture_Normal, RT.xy).a, RT.z) * 0.0625 - 0.03125);\n"
2436 "       return RT.xy;\n"
2437 "#else\n"
2438 "       // 2 sample offset mapping (only 2 samples because of ATI Radeon 9500-9800/X300 limits)\n"
2439 "       //float2 OffsetVector = float2(EyeVector.xy * ((1.0 / EyeVector.z) * OffsetMapping_Scale) * float2(-1, 1));\n"
2440 "       //float2 OffsetVector = float2(normalize(EyeVector.xy) * OffsetMapping_Scale * float2(-1, 1));\n"
2441 "       float2 OffsetVector = float2(normalize(EyeVector).xy * OffsetMapping_Scale * float2(-1, 1));\n"
2442 "       OffsetVector *= 0.5;\n"
2443 "       TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2444 "       TexCoord += OffsetVector * (1.0 - tex2D(Texture_Normal, TexCoord).a);\n"
2445 "       return TexCoord;\n"
2446 "#endif\n"
2447 "}\n"
2448 "#endif // USEOFFSETMAPPING\n"
2449 "\n"
2450 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
2451 "#if defined(USESHADOWMAP2D)\n"
2452 "# ifdef USESHADOWMAPORTHO\n"
2453 "#  define GetShadowMapTC2D(dir, ShadowMap_Parameters) (min(dir, ShadowMap_Parameters.xyz))\n"
2454 "# else\n"
2455 "#  ifdef USESHADOWMAPVSDCT\n"
2456 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters, samplerCUBE Texture_CubeProjection)\n"
2457 "{\n"
2458 "       float3 adir = abs(dir);\n"
2459 "       float2 aparams = ShadowMap_Parameters.xy / max(max(adir.x, adir.y), adir.z);\n"
2460 "       float4 proj = texCUBE(Texture_CubeProjection, dir);\n"
2461 "       return float3(lerp(dir.xy, dir.zz, proj.xy) * aparams.x + proj.zw * ShadowMap_Parameters.z, aparams.y + ShadowMap_Parameters.w);\n"
2462 "}\n"
2463 "#  else\n"
2464 "float3 GetShadowMapTC2D(float3 dir, float4 ShadowMap_Parameters)\n"
2465 "{\n"
2466 "       float3 adir = abs(dir);\n"
2467 "       float ma = adir.z;\n"
2468 "       float4 proj = float4(dir, 2.5);\n"
2469 "       if (adir.x > ma) { ma = adir.x; proj = float4(dir.zyx, 0.5); }\n"
2470 "       if (adir.y > ma) { ma = adir.y; proj = float4(dir.xzy, 1.5); }\n"
2471 "#ifdef HLSL\n"
2472 "       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"
2473 "#else\n"
2474 "       float2 aparams = ShadowMap_Parameters.xy / ma;\n"
2475 "       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"
2476 "#endif\n"
2477 "}\n"
2478 "#  endif\n"
2479 "# endif\n"
2480 "#endif // defined(USESHADOWMAP2D)\n"
2481 "\n"
2482 "# ifdef USESHADOWMAP2D\n"
2483 "#ifdef USESHADOWMAPVSDCT\n"
2484 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale, samplerCUBE Texture_CubeProjection)\n"
2485 "#else\n"
2486 "float ShadowMapCompare(float3 dir, sampler Texture_ShadowMap2D, float4 ShadowMap_Parameters, float2 ShadowMap_TextureScale)\n"
2487 "#endif\n"
2488 "{\n"
2489 "#ifdef USESHADOWMAPVSDCT\n"
2490 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters, Texture_CubeProjection);\n"
2491 "#else\n"
2492 "       float3 shadowmaptc = GetShadowMapTC2D(dir, ShadowMap_Parameters);\n"
2493 "#endif\n"
2494 "       float f;\n"
2495 "\n"
2496 "#  ifdef USESHADOWSAMPLER\n"
2497 "#    ifdef USESHADOWMAPPCF\n"
2498 "#      define texval(x, y) tex2Dproj(Texture_ShadowMap2D, float4(center + float2(x, y)*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r  \n"
2499 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale;\n"
2500 "       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"
2501 "#    else\n"
2502 "       f = tex2Dproj(Texture_ShadowMap2D, float4(shadowmaptc.xy*ShadowMap_TextureScale, shadowmaptc.z, 1.0)).r;\n"
2503 "#    endif\n"
2504 "#  else\n"
2505 "#    ifdef USESHADOWMAPPCF\n"
2506 "#     if defined(GL_ARB_texture_gather) || defined(GL_AMD_texture_texture4)\n"
2507 "#      ifdef GL_ARB_texture_gather\n"
2508 "#        define texval(x, y) textureGatherOffset(Texture_ShadowMap2D, center, int2(x, y))\n"
2509 "#      else\n"
2510 "#        define texval(x, y) texture4(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale)\n"
2511 "#      endif\n"
2512 "       float2 offset = frac(shadowmaptc.xy - 0.5), center = (shadowmaptc.xy - offset)*ShadowMap_TextureScale;\n"
2513 "#      if USESHADOWMAPPCF > 1\n"
2514 "       float4 group1 = step(shadowmaptc.z, texval(-2.0, -2.0));\n"
2515 "       float4 group2 = step(shadowmaptc.z, texval( 0.0, -2.0));\n"
2516 "       float4 group3 = step(shadowmaptc.z, texval( 2.0, -2.0));\n"
2517 "       float4 group4 = step(shadowmaptc.z, texval(-2.0,  0.0));\n"
2518 "       float4 group5 = step(shadowmaptc.z, texval( 0.0,  0.0));\n"
2519 "       float4 group6 = step(shadowmaptc.z, texval( 2.0,  0.0));\n"
2520 "       float4 group7 = step(shadowmaptc.z, texval(-2.0,  2.0));\n"
2521 "       float4 group8 = step(shadowmaptc.z, texval( 0.0,  2.0));\n"
2522 "       float4 group9 = step(shadowmaptc.z, texval( 2.0,  2.0));\n"
2523 "       float4 locols = float4(group1.ab, group3.ab);\n"
2524 "       float4 hicols = float4(group7.rg, group9.rg);\n"
2525 "       locols.yz += group2.ab;\n"
2526 "       hicols.yz += group8.rg;\n"
2527 "       float4 midcols = float4(group1.rg, group3.rg) + float4(group7.ab, group9.ab) +\n"
2528 "                               float4(group4.rg, group6.rg) + float4(group4.ab, group6.ab) +\n"
2529 "                               lerp(locols, hicols, offset.y);\n"
2530 "       float4 cols = group5 + float4(group2.rg, group8.ab);\n"
2531 "       cols.xyz += lerp(midcols.xyz, midcols.yzw, offset.x);\n"
2532 "       f = dot(cols, float4(1.0/25.0));\n"
2533 "#      else\n"
2534 "       float4 group1 = step(shadowmaptc.z, texval(-1.0, -1.0));\n"
2535 "       float4 group2 = step(shadowmaptc.z, texval( 1.0, -1.0));\n"
2536 "       float4 group3 = step(shadowmaptc.z, texval(-1.0,  1.0));\n"
2537 "       float4 group4 = step(shadowmaptc.z, texval( 1.0,  1.0));\n"
2538 "       float4 cols = float4(group1.rg, group2.rg) + float4(group3.ab, group4.ab) +\n"
2539 "                               lerp(float4(group1.ab, group2.ab), float4(group3.rg, group4.rg), offset.y);\n"
2540 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2541 "#      endif\n"
2542 "#     else\n"
2543 "#      ifdef GL_EXT_gpu_shader4\n"
2544 "#        define texval(x, y) tex2DOffset(Texture_ShadowMap2D, center, int2(x, y)).r\n"
2545 "#      else\n"
2546 "#        define texval(x, y) texDepth2D(Texture_ShadowMap2D, center + float2(x, y)*ShadowMap_TextureScale).r  \n"
2547 "#      endif\n"
2548 "#      if USESHADOWMAPPCF > 1\n"
2549 "       float2 center = shadowmaptc.xy - 0.5, offset = frac(center);\n"
2550 "       center *= ShadowMap_TextureScale;\n"
2551 "       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"
2552 "       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"
2553 "       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"
2554 "       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"
2555 "       float4 cols = row2 + row3 + lerp(row1, row4, offset.y);\n"
2556 "       f = dot(lerp(cols.xyz, cols.yzw, offset.x), float3(1.0/9.0));\n"
2557 "#      else\n"
2558 "       float2 center = shadowmaptc.xy*ShadowMap_TextureScale, offset = frac(shadowmaptc.xy);\n"
2559 "       float3 row1 = step(shadowmaptc.z, float3(texval(-1.0, -1.0), texval( 0.0, -1.0), texval( 1.0, -1.0)));\n"
2560 "       float3 row2 = step(shadowmaptc.z, float3(texval(-1.0,  0.0), texval( 0.0,  0.0), texval( 1.0,  0.0)));\n"
2561 "       float3 row3 = step(shadowmaptc.z, float3(texval(-1.0,  1.0), texval( 0.0,  1.0), texval( 1.0,  1.0)));\n"
2562 "       float3 cols = row2 + lerp(row1, row3, offset.y);\n"
2563 "       f = dot(lerp(cols.xy, cols.yz, offset.x), float2(0.25,0.25));\n"
2564 "#      endif\n"
2565 "#     endif\n"
2566 "#    else\n"
2567 "       f = step(shadowmaptc.z, tex2D(Texture_ShadowMap2D, shadowmaptc.xy*ShadowMap_TextureScale).r);\n"
2568 "#    endif\n"
2569 "#  endif\n"
2570 "#  ifdef USESHADOWMAPORTHO\n"
2571 "       return lerp(ShadowMap_Parameters.w, 1.0, f);\n"
2572 "#  else\n"
2573 "       return f;\n"
2574 "#  endif\n"
2575 "}\n"
2576 "# endif\n"
2577 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
2578 "#endif // FRAGMENT_SHADER\n"
2579 "\n"
2580 "\n"
2581 "\n"
2582 "\n"
2583 "#ifdef MODE_DEFERREDGEOMETRY\n"
2584 "#ifdef VERTEX_SHADER\n"
2585 "void main\n"
2586 "(\n"
2587 "float4 gl_Vertex : POSITION,\n"
2588 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2589 "#ifdef USEVERTEXTEXTUREBLEND\n"
2590 "float4 gl_Color : COLOR0,\n"
2591 "#endif\n"
2592 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2593 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2594 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2595 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2596 "uniform float4x4 TexMatrix : register(c0),\n"
2597 "#ifdef USEVERTEXTEXTUREBLEND\n"
2598 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2599 "#endif\n"
2600 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2601 "#ifdef USEOFFSETMAPPING\n"
2602 "uniform float3 EyePosition : register(c24),\n"
2603 "#endif\n"
2604 "out float4 gl_Position : POSITION,\n"
2605 "#ifdef USEVERTEXTEXTUREBLEND\n"
2606 "out float4 gl_FrontColor : COLOR,\n"
2607 "#endif\n"
2608 "out float4 TexCoordBoth : TEXCOORD0,\n"
2609 "#ifdef USEOFFSETMAPPING\n"
2610 "out float3 EyeVector : TEXCOORD2,\n"
2611 "#endif\n"
2612 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2613 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2614 "out float4 VectorR : TEXCOORD7 // direction of R texcoord (surface normal), Depth value\n"
2615 ")\n"
2616 "{\n"
2617 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2618 "#ifdef USEVERTEXTEXTUREBLEND\n"
2619 "#ifdef HLSL\n"
2620 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2621 "#else\n"
2622 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2623 "#endif\n"
2624 "       TexCoordBoth.zw = float2(Backgroundmul(TexMatrix, gl_MultiTexCoord0));\n"
2625 "#endif\n"
2626 "\n"
2627 "       // transform unnormalized eye direction into tangent space\n"
2628 "#ifdef USEOFFSETMAPPING\n"
2629 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2630 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2631 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2632 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2633 "#endif\n"
2634 "\n"
2635 "       VectorS = mul(ModelViewMatrix, float4(gl_MultiTexCoord1.xyz, 0)).xyz;\n"
2636 "       VectorT = mul(ModelViewMatrix, float4(gl_MultiTexCoord2.xyz, 0)).xyz;\n"
2637 "       VectorR.xyz = mul(ModelViewMatrix, float4(gl_MultiTexCoord3.xyz, 0)).xyz;\n"
2638 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2639 "       VectorR.w = gl_Position.z;\n"
2640 "}\n"
2641 "#endif // VERTEX_SHADER\n"
2642 "\n"
2643 "#ifdef FRAGMENT_SHADER\n"
2644 "void main\n"
2645 "(\n"
2646 "float4 TexCoordBoth : TEXCOORD0,\n"
2647 "float3 EyeVector : TEXCOORD2,\n"
2648 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2649 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2650 "float4 VectorR : TEXCOORD7, // direction of R texcoord (surface normal), Depth value\n"
2651 "uniform sampler Texture_Normal : register(s0),\n"
2652 "#ifdef USEALPHAKILL\n"
2653 "uniform sampler Texture_Color : register(s1),\n"
2654 "#endif\n"
2655 "uniform sampler Texture_Gloss : register(s2),\n"
2656 "#ifdef USEVERTEXTEXTUREBLEND\n"
2657 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
2658 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
2659 "#endif\n"
2660 "#ifdef USEOFFSETMAPPING\n"
2661 "uniform float OffsetMapping_Scale : register(c24),\n"
2662 "#endif\n"
2663 "uniform half SpecularPower : register(c36),\n"
2664 "#ifdef HLSL\n"
2665 "out float4 gl_FragData0 : COLOR0,\n"
2666 "out float4 gl_FragData1 : COLOR1\n"
2667 "#else\n"
2668 "out float4 gl_FragColor : COLOR\n"
2669 "#endif\n"
2670 ")\n"
2671 "{\n"
2672 "       float2 TexCoord = TexCoordBoth.xy;\n"
2673 "#ifdef USEOFFSETMAPPING\n"
2674 "       // apply offsetmapping\n"
2675 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
2676 "#define TexCoord TexCoordOffset\n"
2677 "#endif\n"
2678 "\n"
2679 "#ifdef USEALPHAKILL\n"
2680 "       if (tex2D(Texture_Color, TexCoord).a < 0.5)\n"
2681 "               discard;\n"
2682 "#endif\n"
2683 "\n"
2684 "#ifdef USEVERTEXTEXTUREBLEND\n"
2685 "       float alpha = tex2D(Texture_Color, TexCoord).a;\n"
2686 "       float terrainblend = clamp(float(gl_FrontColor.a) * alpha * 2.0 - 0.5, float(0.0), float(1.0));\n"
2687 "       //float terrainblend = min(float(gl_FrontColor.a) * alpha * 2.0, float(1.0));\n"
2688 "       //float terrainblend = float(gl_FrontColor.a) * alpha > 0.5;\n"
2689 "#endif\n"
2690 "\n"
2691 "#ifdef USEVERTEXTEXTUREBLEND\n"
2692 "       float3 surfacenormal = lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend) - float3(0.5, 0.5, 0.5);\n"
2693 "       float a = lerp(tex2D(Texture_SecondaryGloss, TexCoord2).a, tex2D(Texture_Gloss, TexCoord).a, terrainblend);\n"
2694 "#else\n"
2695 "       float3 surfacenormal = tex2D(Texture_Normal, TexCoord).rgb - float3(0.5, 0.5, 0.5);\n"
2696 "       float a = tex2D(Texture_Gloss, TexCoord).a;\n"
2697 "#endif\n"
2698 "\n"
2699 "#ifdef HLSL\n"
2700 "       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"
2701 "       float Depth = VectorR.w / 256.0;\n"
2702 "       float4 depthcolor = float4(Depth,Depth*65536.0/255.0,Depth*16777216.0/255.0,0.0);\n"
2703 "//     float4 depthcolor = float4(Depth,Depth*256.0,Depth*65536.0,0.0);\n"
2704 "       depthcolor.yz -= floor(depthcolor.yz);\n"
2705 "       gl_FragData1 = depthcolor;\n"
2706 "#else\n"
2707 "       gl_FragColor = float4(normalize(surfacenormal.x * VectorS + surfacenormal.y * VectorT + surfacenormal.z * VectorR) * 0.5 + float3(0.5, 0.5, 0.5), a);\n"
2708 "#endif\n"
2709 "}\n"
2710 "#endif // FRAGMENT_SHADER\n"
2711 "#else // !MODE_DEFERREDGEOMETRY\n"
2712 "\n"
2713 "\n"
2714 "\n"
2715 "\n"
2716 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2717 "#ifdef VERTEX_SHADER\n"
2718 "void main\n"
2719 "(\n"
2720 "float4 gl_Vertex : POSITION,\n"
2721 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2722 "uniform float4x4 ModelViewMatrix : register(c12),\n"
2723 "out float4 gl_Position : POSITION,\n"
2724 "out float4 ModelViewPosition : TEXCOORD0\n"
2725 ")\n"
2726 "{\n"
2727 "       ModelViewPosition = mul(ModelViewMatrix, gl_Vertex);\n"
2728 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2729 "}\n"
2730 "#endif // VERTEX_SHADER\n"
2731 "\n"
2732 "#ifdef FRAGMENT_SHADER\n"
2733 "void main\n"
2734 "(\n"
2735 "#ifdef HLSL\n"
2736 "float2 Pixel : VPOS,\n"
2737 "#else\n"
2738 "float2 Pixel : WPOS,\n"
2739 "#endif\n"
2740 "float4 ModelViewPosition : TEXCOORD0,\n"
2741 "uniform float4x4 ViewToLight : register(c44),\n"
2742 "uniform float2 ScreenToDepth : register(c33), // ScreenToDepth = float2(Far / (Far - Near), Far * Near / (Near - Far));\n"
2743 "uniform float3 LightPosition : register(c23),\n"
2744 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
2745 "uniform half3 DeferredColor_Ambient : register(c9),\n"
2746 "uniform half3 DeferredColor_Diffuse : register(c10),\n"
2747 "#ifdef USESPECULAR\n"
2748 "uniform half3 DeferredColor_Specular : register(c11),\n"
2749 "uniform half SpecularPower : register(c36),\n"
2750 "#endif\n"
2751 "uniform sampler Texture_Attenuation : register(s9),\n"
2752 "uniform sampler Texture_ScreenDepth : register(s13),\n"
2753 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
2754 "\n"
2755 "#ifdef USECUBEFILTER\n"
2756 "uniform samplerCUBE Texture_Cube : register(s10),\n"
2757 "#endif\n"
2758 "\n"
2759 "#ifdef USESHADOWMAP2D\n"
2760 "# ifdef USESHADOWSAMPLER\n"
2761 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2762 "# else\n"
2763 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
2764 "# endif\n"
2765 "#endif\n"
2766 "\n"
2767 "#ifdef USESHADOWMAPVSDCT\n"
2768 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
2769 "#endif\n"
2770 "\n"
2771 "#if defined(USESHADOWMAP2D)\n"
2772 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
2773 "uniform float4 ShadowMap_Parameters : register(c34),\n"
2774 "#endif\n"
2775 "\n"
2776 "out float4 gl_FragData0 : COLOR0,\n"
2777 "out float4 gl_FragData1 : COLOR1\n"
2778 ")\n"
2779 "{\n"
2780 "       // calculate viewspace pixel position\n"
2781 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
2782 "       //ScreenTexCoord.y = ScreenTexCoord.y * -1 + 1; // Cg is opposite?\n"
2783 "       float3 position;\n"
2784 "#ifdef HLSL\n"
2785 "       position.z = texDepth2D(Texture_ScreenDepth, ScreenTexCoord) * 256.0;\n"
2786 "#else\n"
2787 "       position.z = ScreenToDepth.y / (texDepth2D(Texture_ScreenDepth, ScreenTexCoord) + ScreenToDepth.x);\n"
2788 "#endif\n"
2789 "       position.xy = ModelViewPosition.xy * (position.z / ModelViewPosition.z);\n"
2790 "       // decode viewspace pixel normal\n"
2791 "       half4 normalmap = half4(tex2D(Texture_ScreenNormalMap, ScreenTexCoord));\n"
2792 "       half3 surfacenormal = half3(normalize(normalmap.rgb - half3(0.5,0.5,0.5)));\n"
2793 "       // surfacenormal = pixel normal in viewspace\n"
2794 "       // LightVector = pixel to light in viewspace\n"
2795 "       // CubeVector = position in lightspace\n"
2796 "       // eyevector = pixel to view in viewspace\n"
2797 "       float3 CubeVector = mul(ViewToLight, float4(position,1)).xyz;\n"
2798 "       half fade = half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
2799 "#ifdef USEDIFFUSE\n"
2800 "       // calculate diffuse shading\n"
2801 "       half3 lightnormal = half3(normalize(LightPosition - position));\n"
2802 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
2803 "#endif\n"
2804 "#ifdef USESPECULAR\n"
2805 "       // calculate directional shading\n"
2806 "       float3 eyevector = position * -1.0;\n"
2807 "#  ifdef USEEXACTSPECULARMATH\n"
2808 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(eyevector)))*-1.0, 0.0)), SpecularPower * normalmap.a));\n"
2809 "#  else\n"
2810 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(eyevector))));\n"
2811 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * normalmap.a));\n"
2812 "#  endif\n"
2813 "#endif\n"
2814 "\n"
2815 "#if defined(USESHADOWMAP2D)\n"
2816 "       fade *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
2817 "#ifdef USESHADOWMAPVSDCT\n"
2818 ", Texture_CubeProjection\n"
2819 "#endif\n"
2820 "       ));\n"
2821 "#endif\n"
2822 "\n"
2823 "#ifdef USEDIFFUSE\n"
2824 "       gl_FragData0 = float4((DeferredColor_Ambient + DeferredColor_Diffuse * diffuse) * fade, 1.0);\n"
2825 "#else\n"
2826 "       gl_FragData0 = float4(DeferredColor_Ambient * fade, 1.0);\n"
2827 "#endif\n"
2828 "#ifdef USESPECULAR\n"
2829 "       gl_FragData1 = float4(DeferredColor_Specular * (specular * fade), 1.0);\n"
2830 "#else\n"
2831 "       gl_FragData1 = float4(0.0, 0.0, 0.0, 1.0);\n"
2832 "#endif\n"
2833 "\n"
2834 "# ifdef USECUBEFILTER\n"
2835 "       float3 cubecolor = texCUBE(Texture_Cube, CubeVector).rgb;\n"
2836 "       gl_FragData0.rgb *= cubecolor;\n"
2837 "       gl_FragData1.rgb *= cubecolor;\n"
2838 "# endif\n"
2839 "}\n"
2840 "#endif // FRAGMENT_SHADER\n"
2841 "#else // !MODE_DEFERREDLIGHTSOURCE\n"
2842 "\n"
2843 "\n"
2844 "\n"
2845 "\n"
2846 "#ifdef VERTEX_SHADER\n"
2847 "void main\n"
2848 "(\n"
2849 "float4 gl_Vertex : POSITION,\n"
2850 "uniform float4x4 ModelViewProjectionMatrix : register(c8),\n"
2851 "#if defined(USEVERTEXTEXTUREBLEND) || defined(MODE_VERTEXCOLOR)\n"
2852 "float4 gl_Color : COLOR0,\n"
2853 "#endif\n"
2854 "float4 gl_MultiTexCoord0 : TEXCOORD0,\n"
2855 "float4 gl_MultiTexCoord1 : TEXCOORD1,\n"
2856 "float4 gl_MultiTexCoord2 : TEXCOORD2,\n"
2857 "float4 gl_MultiTexCoord3 : TEXCOORD3,\n"
2858 "float4 gl_MultiTexCoord4 : TEXCOORD4,\n"
2859 "\n"
2860 "uniform float3 EyePosition : register(c24),\n"
2861 "uniform float4x4 TexMatrix : register(c0),\n"
2862 "#ifdef USEVERTEXTEXTUREBLEND\n"
2863 "uniform float4x4 BackgroundTexMatrix : register(c4),\n"
2864 "#endif\n"
2865 "#ifdef MODE_LIGHTSOURCE\n"
2866 "uniform float4x4 ModelToLight : register(c20),\n"
2867 "#endif\n"
2868 "#ifdef MODE_LIGHTSOURCE\n"
2869 "uniform float3 LightPosition : register(c27),\n"
2870 "#endif\n"
2871 "#ifdef MODE_LIGHTDIRECTION\n"
2872 "uniform float3 LightDir : register(c26),\n"
2873 "#endif\n"
2874 "uniform float4 FogPlane : register(c25),\n"
2875 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
2876 "uniform float3 LightPosition : register(c27),\n"
2877 "#endif\n"
2878 "#ifdef USESHADOWMAPORTHO\n"
2879 "uniform float4x4 ShadowMapMatrix : register(c16),\n"
2880 "#endif\n"
2881 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2882 "out float4 gl_FrontColor : COLOR,\n"
2883 "#endif\n"
2884 "out float4 TexCoordBoth : TEXCOORD0,\n"
2885 "#ifdef USELIGHTMAP\n"
2886 "out float2 TexCoordLightmap : TEXCOORD1,\n"
2887 "#endif\n"
2888 "#ifdef USEEYEVECTOR\n"
2889 "out float3 EyeVector : TEXCOORD2,\n"
2890 "#endif\n"
2891 "#ifdef USEREFLECTION\n"
2892 "out float4 ModelViewProjectionPosition : TEXCOORD3,\n"
2893 "#endif\n"
2894 "#ifdef USEFOG\n"
2895 "out float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
2896 "#endif\n"
2897 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE) || defined(USEDIFFUSE)\n"
2898 "out float3 LightVector : TEXCOORD1,\n"
2899 "#endif\n"
2900 "#ifdef MODE_LIGHTSOURCE\n"
2901 "out float3 CubeVector : TEXCOORD3,\n"
2902 "#endif\n"
2903 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
2904 "out float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
2905 "out float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
2906 "out float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
2907 "#endif\n"
2908 "#ifdef USESHADOWMAPORTHO\n"
2909 "out float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
2910 "#endif\n"
2911 "out float4 gl_Position : POSITION\n"
2912 ")\n"
2913 "{\n"
2914 "#if defined(MODE_VERTEXCOLOR) || defined(USEVERTEXTEXTUREBLEND)\n"
2915 "#ifdef HLSL\n"
2916 "       gl_FrontColor = gl_Color.bgra; // NOTE: D3DCOLOR is backwards\n"
2917 "#else\n"
2918 "       gl_FrontColor = gl_Color; // Cg is forward\n"
2919 "#endif\n"
2920 "#endif\n"
2921 "       // copy the surface texcoord\n"
2922 "       TexCoordBoth = mul(TexMatrix, gl_MultiTexCoord0);\n"
2923 "#ifdef USEVERTEXTEXTUREBLEND\n"
2924 "       TexCoordBoth.zw = mul(BackgroundTexMatrix, gl_MultiTexCoord0).xy;\n"
2925 "#endif\n"
2926 "#ifdef USELIGHTMAP\n"
2927 "       TexCoordLightmap = gl_MultiTexCoord4.xy;\n"
2928 "#endif\n"
2929 "\n"
2930 "#ifdef MODE_LIGHTSOURCE\n"
2931 "       // transform vertex position into light attenuation/cubemap space\n"
2932 "       // (-1 to +1 across the light box)\n"
2933 "       CubeVector = mul(ModelToLight, gl_Vertex).xyz;\n"
2934 "\n"
2935 "# ifdef USEDIFFUSE\n"
2936 "       // transform unnormalized light direction into tangent space\n"
2937 "       // (we use unnormalized to ensure that it interpolates correctly and then\n"
2938 "       //  normalize it per pixel)\n"
2939 "       float3 lightminusvertex = LightPosition - gl_Vertex.xyz;\n"
2940 "       LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);\n"
2941 "       LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);\n"
2942 "       LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);\n"
2943 "# endif\n"
2944 "#endif\n"
2945 "\n"
2946 "#if defined(MODE_LIGHTDIRECTION) && defined(USEDIFFUSE)\n"
2947 "       LightVector.x = dot(LightDir, gl_MultiTexCoord1.xyz);\n"
2948 "       LightVector.y = dot(LightDir, gl_MultiTexCoord2.xyz);\n"
2949 "       LightVector.z = dot(LightDir, gl_MultiTexCoord3.xyz);\n"
2950 "#endif\n"
2951 "\n"
2952 "       // transform unnormalized eye direction into tangent space\n"
2953 "#ifdef USEEYEVECTOR\n"
2954 "       float3 EyeVectorModelSpace = EyePosition - gl_Vertex.xyz;\n"
2955 "       EyeVector.x = dot(EyeVectorModelSpace, gl_MultiTexCoord1.xyz);\n"
2956 "       EyeVector.y = dot(EyeVectorModelSpace, gl_MultiTexCoord2.xyz);\n"
2957 "       EyeVector.z = dot(EyeVectorModelSpace, gl_MultiTexCoord3.xyz);\n"
2958 "#endif\n"
2959 "\n"
2960 "#ifdef USEFOG\n"
2961 "       EyeVectorModelSpaceFogPlaneVertexDist.xyz = EyePosition - gl_Vertex.xyz;\n"
2962 "       EyeVectorModelSpaceFogPlaneVertexDist.w = dot(FogPlane, gl_Vertex);\n"
2963 "#endif\n"
2964 "\n"
2965 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
2966 "       VectorS = gl_MultiTexCoord1.xyz;\n"
2967 "       VectorT = gl_MultiTexCoord2.xyz;\n"
2968 "       VectorR = gl_MultiTexCoord3.xyz;\n"
2969 "#endif\n"
2970 "\n"
2971 "       // transform vertex to camera space, using ftransform to match non-VS rendering\n"
2972 "       gl_Position = mul(ModelViewProjectionMatrix, gl_Vertex);\n"
2973 "\n"
2974 "#ifdef USESHADOWMAPORTHO\n"
2975 "       ShadowMapTC = mul(ShadowMapMatrix, gl_Position).xyz;\n"
2976 "#endif\n"
2977 "\n"
2978 "#ifdef USEREFLECTION\n"
2979 "       ModelViewProjectionPosition = gl_Position;\n"
2980 "#endif\n"
2981 "}\n"
2982 "#endif // VERTEX_SHADER\n"
2983 "\n"
2984 "\n"
2985 "\n"
2986 "\n"
2987 "#ifdef FRAGMENT_SHADER\n"
2988 "void main\n"
2989 "(\n"
2990 "#ifdef USEDEFERREDLIGHTMAP\n"
2991 "#ifdef HLSL\n"
2992 "float2 Pixel : VPOS,\n"
2993 "#else\n"
2994 "float2 Pixel : WPOS,\n"
2995 "#endif\n"
2996 "#endif\n"
2997 "float4 gl_FrontColor : COLOR,\n"
2998 "float4 TexCoordBoth : TEXCOORD0,\n"
2999 "#ifdef USELIGHTMAP\n"
3000 "float2 TexCoordLightmap : TEXCOORD1,\n"
3001 "#endif\n"
3002 "#ifdef USEEYEVECTOR\n"
3003 "float3 EyeVector : TEXCOORD2,\n"
3004 "#endif\n"
3005 "#ifdef USEREFLECTION\n"
3006 "float4 ModelViewProjectionPosition : TEXCOORD3,\n"
3007 "#endif\n"
3008 "#ifdef USEFOG\n"
3009 "float4 EyeVectorModelSpaceFogPlaneVertexDist : TEXCOORD4,\n"
3010 "#endif\n"
3011 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_LIGHTDIRECTION)\n"
3012 "float3 LightVector : TEXCOORD1,\n"
3013 "#endif\n"
3014 "#ifdef MODE_LIGHTSOURCE\n"
3015 "float3 CubeVector : TEXCOORD3,\n"
3016 "#endif\n"
3017 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3018 "float4 ModelViewPosition : TEXCOORD0,\n"
3019 "#endif\n"
3020 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_DEFERREDGEOMETRY) || defined(USEREFLECTCUBE)\n"
3021 "float3 VectorS : TEXCOORD5, // direction of S texcoord (sometimes crudely called tangent)\n"
3022 "float3 VectorT : TEXCOORD6, // direction of T texcoord (sometimes crudely called binormal)\n"
3023 "float3 VectorR : TEXCOORD7, // direction of R texcoord (surface normal)\n"
3024 "#endif\n"
3025 "#ifdef USESHADOWMAPORTHO\n"
3026 "float3 ShadowMapTC : TEXCOORD3, // CONFLICTS WITH USEREFLECTION!\n"
3027 "#endif\n"
3028 "\n"
3029 "uniform sampler Texture_Normal : register(s0),\n"
3030 "uniform sampler Texture_Color : register(s1),\n"
3031 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3032 "uniform sampler Texture_Gloss : register(s2),\n"
3033 "#endif\n"
3034 "#ifdef USEGLOW\n"
3035 "uniform sampler Texture_Glow : register(s3),\n"
3036 "#endif\n"
3037 "#ifdef USEVERTEXTEXTUREBLEND\n"
3038 "uniform sampler Texture_SecondaryNormal : register(s4),\n"
3039 "uniform sampler Texture_SecondaryColor : register(s5),\n"
3040 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3041 "uniform sampler Texture_SecondaryGloss : register(s6),\n"
3042 "#endif\n"
3043 "#ifdef USEGLOW\n"
3044 "uniform sampler Texture_SecondaryGlow : register(s7),\n"
3045 "#endif\n"
3046 "#endif\n"
3047 "#ifdef USECOLORMAPPING\n"
3048 "uniform sampler Texture_Pants : register(s4),\n"
3049 "uniform sampler Texture_Shirt : register(s7),\n"
3050 "#endif\n"
3051 "#ifdef USEFOG\n"
3052 "uniform sampler Texture_FogHeightTexture : register(s14),\n"
3053 "uniform sampler Texture_FogMask : register(s8),\n"
3054 "#endif\n"
3055 "#ifdef USELIGHTMAP\n"
3056 "uniform sampler Texture_Lightmap : register(s9),\n"
3057 "#endif\n"
3058 "#if defined(MODE_LIGHTDIRECTIONMAP_MODELSPACE) || defined(MODE_LIGHTDIRECTIONMAP_TANGENTSPACE)\n"
3059 "uniform sampler Texture_Deluxemap : register(s10),\n"
3060 "#endif\n"
3061 "#ifdef USEREFLECTION\n"
3062 "uniform sampler Texture_Reflection : register(s7),\n"
3063 "#endif\n"
3064 "\n"
3065 "#ifdef MODE_DEFERREDLIGHTSOURCE\n"
3066 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3067 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3068 "#endif\n"
3069 "#ifdef USEDEFERREDLIGHTMAP\n"
3070 "uniform sampler Texture_ScreenDepth : register(s13),\n"
3071 "uniform sampler Texture_ScreenNormalMap : register(s14),\n"
3072 "uniform sampler Texture_ScreenDiffuse : register(s11),\n"
3073 "uniform sampler Texture_ScreenSpecular : register(s12),\n"
3074 "#endif\n"
3075 "\n"
3076 "#ifdef USECOLORMAPPING\n"
3077 "uniform half3 Color_Pants : register(c7),\n"
3078 "uniform half3 Color_Shirt : register(c8),\n"
3079 "#endif\n"
3080 "#ifdef USEFOG\n"
3081 "uniform float3 FogColor : register(c16),\n"
3082 "uniform float FogRangeRecip : register(c20),\n"
3083 "uniform float FogPlaneViewDist : register(c19),\n"
3084 "uniform float FogHeightFade : register(c17),\n"
3085 "#endif\n"
3086 "\n"
3087 "#ifdef USEOFFSETMAPPING\n"
3088 "uniform float OffsetMapping_Scale : register(c24),\n"
3089 "#endif\n"
3090 "\n"
3091 "#ifdef USEDEFERREDLIGHTMAP\n"
3092 "uniform half2 PixelToScreenTexCoord : register(c42),\n"
3093 "uniform half3 DeferredMod_Diffuse : register(c12),\n"
3094 "uniform half3 DeferredMod_Specular : register(c13),\n"
3095 "#endif\n"
3096 "uniform half3 Color_Ambient : register(c3),\n"
3097 "uniform half3 Color_Diffuse : register(c4),\n"
3098 "uniform half3 Color_Specular : register(c5),\n"
3099 "uniform half SpecularPower : register(c36),\n"
3100 "#ifdef USEGLOW\n"
3101 "uniform half3 Color_Glow : register(c6),\n"
3102 "#endif\n"
3103 "uniform half Alpha : register(c0),\n"
3104 "#ifdef USEREFLECTION\n"
3105 "uniform float4 DistortScaleRefractReflect : register(c14),\n"
3106 "uniform float4 ScreenScaleRefractReflect : register(c32),\n"
3107 "uniform float4 ScreenCenterRefractReflect : register(c31),\n"
3108 "uniform half4 ReflectColor : register(c26),\n"
3109 "#endif\n"
3110 "#ifdef USEREFLECTCUBE\n"
3111 "uniform float4x4 ModelToReflectCube : register(c48),\n"
3112 "uniform sampler Texture_ReflectMask : register(s5),\n"
3113 "uniform samplerCUBE Texture_ReflectCube : register(s6),\n"
3114 "#endif\n"
3115 "#ifdef MODE_LIGHTDIRECTION\n"
3116 "uniform half3 LightColor : register(c21),\n"
3117 "#endif\n"
3118 "#ifdef MODE_LIGHTSOURCE\n"
3119 "uniform half3 LightColor : register(c21),\n"
3120 "#endif\n"
3121 "\n"
3122 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE)\n"
3123 "uniform sampler Texture_Attenuation : register(s9),\n"
3124 "uniform samplerCUBE Texture_Cube : register(s10),\n"
3125 "#endif\n"
3126 "\n"
3127 "#if defined(MODE_LIGHTSOURCE) || defined(MODE_DEFERREDLIGHTSOURCE) || defined(USESHADOWMAPORTHO)\n"
3128 "\n"
3129 "#ifdef USESHADOWMAP2D\n"
3130 "# ifdef USESHADOWSAMPLER\n"
3131 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3132 "# else\n"
3133 "uniform sampler Texture_ShadowMap2D : register(s15),\n"
3134 "# endif\n"
3135 "#endif\n"
3136 "\n"
3137 "#ifdef USESHADOWMAPVSDCT\n"
3138 "uniform samplerCUBE Texture_CubeProjection : register(s12),\n"
3139 "#endif\n"
3140 "\n"
3141 "#if defined(USESHADOWMAP2D)\n"
3142 "uniform float2 ShadowMap_TextureScale : register(c35),\n"
3143 "uniform float4 ShadowMap_Parameters : register(c34),\n"
3144 "#endif\n"
3145 "#endif // !defined(MODE_LIGHTSOURCE) && !defined(MODE_DEFERREDLIGHTSOURCE) && !defined(USESHADOWMAPORTHO)\n"
3146 "\n"
3147 "out float4 gl_FragColor : COLOR\n"
3148 ")\n"
3149 "{\n"
3150 "       float2 TexCoord = TexCoordBoth.xy;\n"
3151 "#ifdef USEVERTEXTEXTUREBLEND\n"
3152 "       float2 TexCoord2 = TexCoordBoth.zw;\n"
3153 "#endif\n"
3154 "#ifdef USEOFFSETMAPPING\n"
3155 "       // apply offsetmapping\n"
3156 "       float2 TexCoordOffset = OffsetMapping(TexCoord, OffsetMapping_Scale, EyeVector, Texture_Normal);\n"
3157 "#define TexCoord TexCoordOffset\n"
3158 "#endif\n"
3159 "\n"
3160 "       // combine the diffuse textures (base, pants, shirt)\n"
3161 "       half4 color = half4(tex2D(Texture_Color, TexCoord));\n"
3162 "#ifdef USEALPHAKILL\n"
3163 "       if (color.a < 0.5)\n"
3164 "               discard;\n"
3165 "#endif\n"
3166 "       color.a *= Alpha;\n"
3167 "#ifdef USECOLORMAPPING\n"
3168 "       color.rgb += half3(tex2D(Texture_Pants, TexCoord).rgb) * Color_Pants + half3(tex2D(Texture_Shirt, TexCoord).rgb) * Color_Shirt;\n"
3169 "#endif\n"
3170 "#ifdef USEVERTEXTEXTUREBLEND\n"
3171 "       half terrainblend = clamp(half(gl_FrontColor.a) * color.a * 2.0 - 0.5, half(0.0), half(1.0));\n"
3172 "       //half terrainblend = min(half(gl_FrontColor.a) * color.a * 2.0, half(1.0));\n"
3173 "       //half terrainblend = half(gl_FrontColor.a) * color.a > 0.5;\n"
3174 "       color.rgb = half3(lerp(tex2D(Texture_SecondaryColor, TexCoord2).rgb, float3(color.rgb), terrainblend));\n"
3175 "       color.a = 1.0;\n"
3176 "       //color = half4(lerp(float4(1, 0, 0, 1), color, terrainblend));\n"
3177 "#endif\n"
3178 "\n"
3179 "       // get the surface normal\n"
3180 "#ifdef USEVERTEXTEXTUREBLEND\n"
3181 "       half3 surfacenormal = normalize(half3(lerp(tex2D(Texture_SecondaryNormal, TexCoord2).rgb, tex2D(Texture_Normal, TexCoord).rgb, terrainblend)) - half3(0.5, 0.5, 0.5));\n"
3182 "#else\n"
3183 "       half3 surfacenormal = half3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5, 0.5, 0.5)));\n"
3184 "#endif\n"
3185 "\n"
3186 "       // get the material colors\n"
3187 "       half3 diffusetex = color.rgb;\n"
3188 "#if defined(USESPECULAR) || defined(USEDEFERREDLIGHTMAP)\n"
3189 "# ifdef USEVERTEXTEXTUREBLEND\n"
3190 "       half4 glosstex = half4(lerp(tex2D(Texture_SecondaryGloss, TexCoord2), tex2D(Texture_Gloss, TexCoord), terrainblend));\n"
3191 "# else\n"
3192 "       half4 glosstex = half4(tex2D(Texture_Gloss, TexCoord));\n"
3193 "# endif\n"
3194 "#endif\n"
3195 "\n"
3196 "#ifdef USEREFLECTCUBE\n"
3197 "       float3 TangentReflectVector = reflect(-EyeVector, surfacenormal);\n"
3198 "       float3 ModelReflectVector = TangentReflectVector.x * VectorS + TangentReflectVector.y * VectorT + TangentReflectVector.z * VectorR;\n"
3199 "       float3 ReflectCubeTexCoord = mul(ModelToReflectCube, float4(ModelReflectVector, 0)).xyz;\n"
3200 "       diffusetex += half3(tex2D(Texture_ReflectMask, TexCoord).rgb) * half3(texCUBE(Texture_ReflectCube, ReflectCubeTexCoord).rgb);\n"
3201 "#endif\n"
3202 "\n"
3203 "\n"
3204 "\n"
3205 "\n"
3206 "#ifdef MODE_LIGHTSOURCE\n"
3207 "       // light source\n"
3208 "#ifdef USEDIFFUSE\n"
3209 "       half3 lightnormal = half3(normalize(LightVector));\n"
3210 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3211 "       color.rgb = diffusetex * (Color_Ambient + diffuse * Color_Diffuse);\n"
3212 "#ifdef USESPECULAR\n"
3213 "#ifdef USEEXACTSPECULARMATH\n"
3214 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3215 "#else\n"
3216 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3217 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3218 "#endif\n"
3219 "       color.rgb += glosstex.rgb * (specular * Color_Specular);\n"
3220 "#endif\n"
3221 "#else\n"
3222 "       color.rgb = diffusetex * Color_Ambient;\n"
3223 "#endif\n"
3224 "       color.rgb *= LightColor;\n"
3225 "       color.rgb *= half(tex2D(Texture_Attenuation, float2(length(CubeVector), 0.0)).r);\n"
3226 "#if defined(USESHADOWMAP2D)\n"
3227 "       color.rgb *= half(ShadowMapCompare(CubeVector, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale\n"
3228 "#ifdef USESHADOWMAPVSDCT\n"
3229 ", Texture_CubeProjection\n"
3230 "#endif\n"
3231 "       ));\n"
3232 "\n"
3233 "#endif\n"
3234 "# ifdef USECUBEFILTER\n"
3235 "       color.rgb *= half3(texCUBE(Texture_Cube, CubeVector).rgb);\n"
3236 "# endif\n"
3237 "\n"
3238 "#ifdef USESHADOWMAP2D\n"
3239 "#ifdef USESHADOWMAPVSDCT\n"
3240 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters, Texture_CubeProjection);\n"
3241 "#else\n"
3242 "//     float3 shadowmaptc = GetShadowMapTC2D(CubeVector, ShadowMap_Parameters);\n"
3243 "#endif\n"
3244 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3245 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3246 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3247 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3248 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, float2(0.1,0.1)).rgb);\n"
3249 "//     color.rgb = half3(tex2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale).rgb);\n"
3250 "//     color.rgb = half3(shadowmaptc.xyz * float3(ShadowMap_TextureScale,1.0));\n"
3251 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3252 "//     color.r = half(shadowmaptc.z - texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3253 "//     color.r = half(shadowmaptc.z);\n"
3254 "//     color.r = half(texDepth2D(Texture_ShadowMap2D, shadowmaptc.xy * ShadowMap_TextureScale));\n"
3255 "//     color.r = half(shadowmaptc.z);\n"
3256 "//     color.r = 1;\n"
3257 "//     color.rgb = abs(CubeVector);\n"
3258 "#endif\n"
3259 "//     color.rgb = half3(1,1,1);\n"
3260 "#endif // MODE_LIGHTSOURCE\n"
3261 "\n"
3262 "\n"
3263 "\n"
3264 "\n"
3265 "#ifdef MODE_LIGHTDIRECTION\n"
3266 "#define SHADING\n"
3267 "#ifdef USEDIFFUSE\n"
3268 "       half3 lightnormal = half3(normalize(LightVector));\n"
3269 "#endif\n"
3270 "#define lightcolor LightColor\n"
3271 "#endif // MODE_LIGHTDIRECTION\n"
3272 "#ifdef MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3273 "#define SHADING\n"
3274 "       // deluxemap lightmapping using light vectors in modelspace (q3map2 -light -deluxe)\n"
3275 "       half3 lightnormal_modelspace = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3276 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3277 "       // convert modelspace light vector to tangentspace\n"
3278 "       half3 lightnormal;\n"
3279 "       lightnormal.x = dot(lightnormal_modelspace, half3(VectorS));\n"
3280 "       lightnormal.y = dot(lightnormal_modelspace, half3(VectorT));\n"
3281 "       lightnormal.z = dot(lightnormal_modelspace, half3(VectorR));\n"
3282 "       // calculate directional shading (and undoing the existing angle attenuation on the lightmap by the division)\n"
3283 "       // note that q3map2 is too stupid to calculate proper surface normals when q3map_nonplanar\n"
3284 "       // is used (the lightmap and deluxemap coords correspond to virtually random coordinates\n"
3285 "       // on that luxel, and NOT to its center, because recursive triangle subdivision is used\n"
3286 "       // to map the luxels to coordinates on the draw surfaces), which also causes\n"
3287 "       // deluxemaps to be wrong because light contributions from the wrong side of the surface\n"
3288 "       // are added up. To prevent divisions by zero or strong exaggerations, a max()\n"
3289 "       // nudge is done here at expense of some additional fps. This is ONLY needed for\n"
3290 "       // deluxemaps, tangentspace deluxemap avoid this problem by design.\n"
3291 "       lightcolor *= 1.0 / max(0.25, lightnormal.z);\n"
3292 "#endif // MODE_LIGHTDIRECTIONMAP_MODELSPACE\n"
3293 "#ifdef MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n"
3294 "#define SHADING\n"
3295 "       // deluxemap lightmapping using light vectors in tangentspace (hmap2 -light)\n"
3296 "       half3 lightnormal = half3(tex2D(Texture_Deluxemap, TexCoordLightmap).rgb) * 2.0 + half3(-1.0, -1.0, -1.0);\n"
3297 "       half3 lightcolor = half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb);\n"
3298 "#endif\n"
3299 "\n"
3300 "\n"
3301 "\n"
3302 "\n"
3303 "#ifdef MODE_FAKELIGHT\n"
3304 "#define SHADING\n"
3305 "half3 lightnormal = half3(normalize(EyeVector));\n"
3306 "half3 lightcolor = half3(1.0,1.0,1.0);\n"
3307 "#endif // MODE_FAKELIGHT\n"
3308 "\n"
3309 "\n"
3310 "\n"
3311 "\n"
3312 "#ifdef MODE_LIGHTMAP\n"
3313 "       color.rgb = diffusetex * (Color_Ambient + half3(tex2D(Texture_Lightmap, TexCoordLightmap).rgb) * Color_Diffuse);\n"
3314 "#endif // MODE_LIGHTMAP\n"
3315 "#ifdef MODE_VERTEXCOLOR\n"
3316 "       color.rgb = diffusetex * (Color_Ambient + half3(gl_FrontColor.rgb) * Color_Diffuse);\n"
3317 "#endif // MODE_VERTEXCOLOR\n"
3318 "#ifdef MODE_FLATCOLOR\n"
3319 "       color.rgb = diffusetex * Color_Ambient;\n"
3320 "#endif // MODE_FLATCOLOR\n"
3321 "\n"
3322 "\n"
3323 "\n"
3324 "\n"
3325 "#ifdef SHADING\n"
3326 "# ifdef USEDIFFUSE\n"
3327 "       half diffuse = half(max(float(dot(surfacenormal, lightnormal)), 0.0));\n"
3328 "#  ifdef USESPECULAR\n"
3329 "#   ifdef USEEXACTSPECULARMATH\n"
3330 "       half specular = half(pow(half(max(float(dot(reflect(lightnormal, surfacenormal), normalize(EyeVector)))*-1.0, 0.0)), SpecularPower * glosstex.a));\n"
3331 "#   else\n"
3332 "       half3 specularnormal = half3(normalize(lightnormal + half3(normalize(EyeVector))));\n"
3333 "       half specular = half(pow(half(max(float(dot(surfacenormal, specularnormal)), 0.0)), SpecularPower * glosstex.a));\n"
3334 "#   endif\n"
3335 "       color.rgb = diffusetex * Color_Ambient + (diffusetex * Color_Diffuse * diffuse + glosstex.rgb * Color_Specular * specular) * lightcolor;\n"
3336 "#  else\n"
3337 "       color.rgb = diffusetex * (Color_Ambient + Color_Diffuse * diffuse * lightcolor);\n"
3338 "#  endif\n"
3339 "# else\n"
3340 "       color.rgb = diffusetex * Color_Ambient;\n"
3341 "# endif\n"
3342 "#endif\n"
3343 "\n"
3344 "#ifdef USESHADOWMAPORTHO\n"
3345 "       color.rgb *= half(ShadowMapCompare(ShadowMapTC, Texture_ShadowMap2D, ShadowMap_Parameters, ShadowMap_TextureScale));\n"
3346 "#endif\n"
3347 "\n"
3348 "#ifdef USEDEFERREDLIGHTMAP\n"
3349 "       float2 ScreenTexCoord = Pixel * PixelToScreenTexCoord;\n"
3350 "       color.rgb += diffusetex * half3(tex2D(Texture_ScreenDiffuse, ScreenTexCoord).rgb) * DeferredMod_Diffuse;\n"
3351 "       color.rgb += glosstex.rgb * half3(tex2D(Texture_ScreenSpecular, ScreenTexCoord).rgb) * DeferredMod_Specular;\n"
3352 "//     color.rgb = half3(tex2D(Texture_ScreenDepth, ScreenTexCoord).rgb);\n"
3353 "//     color.r = half(texDepth2D(Texture_ScreenDepth, ScreenTexCoord)) * 1.0;\n"
3354 "#endif\n"
3355 "\n"
3356 "#ifdef USEGLOW\n"
3357 "#ifdef USEVERTEXTEXTUREBLEND\n"
3358 "       color.rgb += half3(lerp(tex2D(Texture_SecondaryGlow, TexCoord2).rgb, tex2D(Texture_Glow, TexCoord).rgb, terrainblend)) * Color_Glow;\n"
3359 "#else\n"
3360 "       color.rgb += half3(tex2D(Texture_Glow, TexCoord).rgb) * Color_Glow;\n"
3361 "#endif\n"
3362 "#endif\n"
3363 "\n"
3364 "#ifdef USEFOG\n"
3365 "       color.rgb = FogVertex(color.rgb, FogColor, EyeVectorModelSpaceFogPlaneVertexDist.xyz, EyeVectorModelSpaceFogPlaneVertexDist.w, FogRangeRecip, FogPlaneViewDist, FogHeightFade, Texture_FogMask, Texture_FogHeightTexture);\n"
3366 "#endif\n"
3367 "\n"
3368 "       // 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"
3369 "#ifdef USEREFLECTION\n"
3370 "       float4 ScreenScaleRefractReflectIW = ScreenScaleRefractReflect * (1.0 / ModelViewProjectionPosition.w);\n"
3371 "       //float4 ScreenTexCoord = (ModelViewProjectionPosition.xyxy + normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5)).xyxy * DistortScaleRefractReflect * 100) * ScreenScaleRefractReflectIW + ScreenCenterRefractReflect;\n"
3372 "       float2 SafeScreenTexCoord = ModelViewProjectionPosition.xy * ScreenScaleRefractReflectIW.zw + ScreenCenterRefractReflect.zw;\n"
3373 "       float2 ScreenTexCoord = SafeScreenTexCoord + float3(normalize(half3(tex2D(Texture_Normal, TexCoord).rgb) - half3(0.5,0.5,0.5))).xy * DistortScaleRefractReflect.zw;\n"
3374 "       // FIXME temporary hack to detect the case that the reflection\n"
3375 "       // gets blackened at edges due to leaving the area that contains actual\n"
3376 "       // content.\n"
3377 "       // Remove this 'ack once we have a better way to stop this thing from\n"
3378 "       // 'appening.\n"
3379 "       float f = min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, 0.01)).rgb) / 0.05);\n"
3380 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(0.01, -0.01)).rgb) / 0.05);\n"
3381 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, 0.01)).rgb) / 0.05);\n"
3382 "       f      *= min(1.0, length(tex2D(Texture_Reflection, ScreenTexCoord + float2(-0.01, -0.01)).rgb) / 0.05);\n"
3383 "       ScreenTexCoord = lerp(SafeScreenTexCoord, ScreenTexCoord, f);\n"
3384 "       color.rgb = lerp(color.rgb, half3(tex2D(Texture_Reflection, ScreenTexCoord).rgb) * ReflectColor.rgb, ReflectColor.a);\n"
3385 "#endif\n"
3386 "\n"
3387 "       gl_FragColor = float4(color);\n"
3388 "}\n"
3389 "#endif // FRAGMENT_SHADER\n"
3390 "\n"
3391 "#endif // !MODE_DEFERREDLIGHTSOURCE\n"
3392 "#endif // !MODE_DEFERREDGEOMETRY\n"
3393 "#endif // !MODE_WATER\n"
3394 "#endif // !MODE_REFRACTION\n"
3395 "#endif // !MODE_BLOOMBLUR\n"
3396 "#endif // !MODE_GENERIC\n"
3397 "#endif // !MODE_POSTPROCESS\n"
3398 "#endif // !MODE_SHOWDEPTH\n"
3399 "#endif // !MODE_DEPTH_OR_SHADOW\n"
3400 ;
3401
3402 char *glslshaderstring = NULL;
3403 char *hlslshaderstring = NULL;
3404
3405 //=======================================================================================================================================================
3406
3407 typedef struct shaderpermutationinfo_s
3408 {
3409         const char *pretext;
3410         const char *name;
3411 }
3412 shaderpermutationinfo_t;
3413
3414 typedef struct shadermodeinfo_s
3415 {
3416         const char *vertexfilename;
3417         const char *geometryfilename;
3418         const char *fragmentfilename;
3419         const char *pretext;
3420         const char *name;
3421 }
3422 shadermodeinfo_t;
3423
3424 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
3425 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
3426 {
3427         {"#define USEDIFFUSE\n", " diffuse"},
3428         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
3429         {"#define USEVIEWTINT\n", " viewtint"},
3430         {"#define USECOLORMAPPING\n", " colormapping"},
3431         {"#define USESATURATION\n", " saturation"},
3432         {"#define USEFOGINSIDE\n", " foginside"},
3433         {"#define USEFOGOUTSIDE\n", " fogoutside"},
3434         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
3435         {"#define USEGAMMARAMPS\n", " gammaramps"},
3436         {"#define USECUBEFILTER\n", " cubefilter"},
3437         {"#define USEGLOW\n", " glow"},
3438         {"#define USEBLOOM\n", " bloom"},
3439         {"#define USESPECULAR\n", " specular"},
3440         {"#define USEPOSTPROCESSING\n", " postprocessing"},
3441         {"#define USEREFLECTION\n", " reflection"},
3442         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
3443         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
3444         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
3445         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
3446         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
3447         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
3448         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
3449         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
3450         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
3451         {"#define USEALPHAKILL\n", " alphakill"},
3452         {"#define USEREFLECTCUBE\n", " reflectcube"},
3453         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
3454         {"#define USEBOUNCEGRID\n", " bouncegrid"},
3455 };
3456
3457 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
3458 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
3459 {
3460         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
3461         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3462         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3463         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3464         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3465         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3466         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3467         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3468         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3469         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3470         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3471         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
3472         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
3473         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3474         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3475         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3476         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDBOUNCELIGHT\n", " deferredbouncelight"},
3477 };
3478
3479 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
3480 {
3481         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
3482         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
3483         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
3484         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
3485         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
3486         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
3487         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
3488         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
3489         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
3490         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
3491         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
3492         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
3493         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
3494         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
3495         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
3496         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
3497         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDBOUNCELIGHT\n", " deferredbouncelight"},
3498 };
3499
3500 struct r_glsl_permutation_s;
3501 typedef struct r_glsl_permutation_s
3502 {
3503         /// hash lookup data
3504         struct r_glsl_permutation_s *hashnext;
3505         unsigned int mode;
3506         unsigned int permutation;
3507
3508         /// indicates if we have tried compiling this permutation already
3509         qboolean compiled;
3510         /// 0 if compilation failed
3511         int program;
3512         // texture units assigned to each detected uniform
3513         int tex_Texture_First;
3514         int tex_Texture_Second;
3515         int tex_Texture_GammaRamps;
3516         int tex_Texture_Normal;
3517         int tex_Texture_Color;
3518         int tex_Texture_Gloss;
3519         int tex_Texture_Glow;
3520         int tex_Texture_SecondaryNormal;
3521         int tex_Texture_SecondaryColor;
3522         int tex_Texture_SecondaryGloss;
3523         int tex_Texture_SecondaryGlow;
3524         int tex_Texture_Pants;
3525         int tex_Texture_Shirt;
3526         int tex_Texture_FogHeightTexture;
3527         int tex_Texture_FogMask;
3528         int tex_Texture_Lightmap;
3529         int tex_Texture_Deluxemap;
3530         int tex_Texture_Attenuation;
3531         int tex_Texture_Cube;
3532         int tex_Texture_Refraction;
3533         int tex_Texture_Reflection;
3534         int tex_Texture_ShadowMap2D;
3535         int tex_Texture_CubeProjection;
3536         int tex_Texture_ScreenDepth;
3537         int tex_Texture_ScreenNormalMap;
3538         int tex_Texture_ScreenDiffuse;
3539         int tex_Texture_ScreenSpecular;
3540         int tex_Texture_ReflectMask;
3541         int tex_Texture_ReflectCube;
3542         int tex_Texture_BounceGrid;
3543         /// locations of detected uniforms in program object, or -1 if not found
3544         int loc_Texture_First;
3545         int loc_Texture_Second;
3546         int loc_Texture_GammaRamps;
3547         int loc_Texture_Normal;
3548         int loc_Texture_Color;
3549         int loc_Texture_Gloss;
3550         int loc_Texture_Glow;
3551         int loc_Texture_SecondaryNormal;
3552         int loc_Texture_SecondaryColor;
3553         int loc_Texture_SecondaryGloss;
3554         int loc_Texture_SecondaryGlow;
3555         int loc_Texture_Pants;
3556         int loc_Texture_Shirt;
3557         int loc_Texture_FogHeightTexture;
3558         int loc_Texture_FogMask;
3559         int loc_Texture_Lightmap;
3560         int loc_Texture_Deluxemap;
3561         int loc_Texture_Attenuation;
3562         int loc_Texture_Cube;
3563         int loc_Texture_Refraction;
3564         int loc_Texture_Reflection;
3565         int loc_Texture_ShadowMap2D;
3566         int loc_Texture_CubeProjection;
3567         int loc_Texture_ScreenDepth;
3568         int loc_Texture_ScreenNormalMap;
3569         int loc_Texture_ScreenDiffuse;
3570         int loc_Texture_ScreenSpecular;
3571         int loc_Texture_ReflectMask;
3572         int loc_Texture_ReflectCube;
3573         int loc_Texture_BounceGrid;
3574         int loc_Alpha;
3575         int loc_BloomBlur_Parameters;
3576         int loc_ClientTime;
3577         int loc_Color_Ambient;
3578         int loc_Color_Diffuse;
3579         int loc_Color_Specular;
3580         int loc_Color_Glow;
3581         int loc_Color_Pants;
3582         int loc_Color_Shirt;
3583         int loc_DeferredColor_Ambient;
3584         int loc_DeferredColor_Diffuse;
3585         int loc_DeferredColor_Specular;
3586         int loc_DeferredMod_Diffuse;
3587         int loc_DeferredMod_Specular;
3588         int loc_DistortScaleRefractReflect;
3589         int loc_EyePosition;
3590         int loc_FogColor;
3591         int loc_FogHeightFade;
3592         int loc_FogPlane;
3593         int loc_FogPlaneViewDist;
3594         int loc_FogRangeRecip;
3595         int loc_LightColor;
3596         int loc_LightDir;
3597         int loc_LightPosition;
3598         int loc_OffsetMapping_Scale;
3599         int loc_PixelSize;
3600         int loc_ReflectColor;
3601         int loc_ReflectFactor;
3602         int loc_ReflectOffset;
3603         int loc_RefractColor;
3604         int loc_Saturation;
3605         int loc_ScreenCenterRefractReflect;
3606         int loc_ScreenScaleRefractReflect;
3607         int loc_ScreenToDepth;
3608         int loc_ShadowMap_Parameters;
3609         int loc_ShadowMap_TextureScale;
3610         int loc_SpecularPower;
3611         int loc_UserVec1;
3612         int loc_UserVec2;
3613         int loc_UserVec3;
3614         int loc_UserVec4;
3615         int loc_ViewTintColor;
3616         int loc_ViewToLight;
3617         int loc_ModelToLight;
3618         int loc_TexMatrix;
3619         int loc_BackgroundTexMatrix;
3620         int loc_ModelViewProjectionMatrix;
3621         int loc_ModelViewMatrix;
3622         int loc_PixelToScreenTexCoord;
3623         int loc_ModelToReflectCube;
3624         int loc_ShadowMapMatrix;
3625         int loc_BloomColorSubtract;
3626         int loc_NormalmapScrollBlend;
3627         int loc_BounceGridMatrix;
3628         int loc_BounceGridIntensity;
3629 }
3630 r_glsl_permutation_t;
3631
3632 #define SHADERPERMUTATION_HASHSIZE 256
3633
3634
3635 // non-degradable "lightweight" shader parameters to keep the permutations simpler
3636 // these can NOT degrade! only use for simple stuff
3637 enum
3638 {
3639         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
3640         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
3641         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
3642         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
3643         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
3644         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5  ///< postprocess uservec4 is enabled
3645 };
3646 #define SHADERSTATICPARMS_COUNT 6
3647
3648 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
3649 static int shaderstaticparms_count = 0;
3650
3651 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
3652 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
3653 qboolean R_CompileShader_CheckStaticParms(void)
3654 {
3655         static int r_compileshader_staticparms_save[1];
3656         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
3657         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
3658
3659         // detect all
3660         if (r_glsl_saturation_redcompensate.integer)
3661                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
3662         if (r_shadow_glossexact.integer)
3663                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
3664         if (r_glsl_postprocess.integer)
3665         {
3666                 if (r_glsl_postprocess_uservec1_enable.integer)
3667                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
3668                 if (r_glsl_postprocess_uservec2_enable.integer)
3669                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
3670                 if (r_glsl_postprocess_uservec3_enable.integer)
3671                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
3672                 if (r_glsl_postprocess_uservec4_enable.integer)
3673                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
3674         }
3675         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
3676 }
3677
3678 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
3679         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
3680                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
3681         else \
3682                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
3683 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
3684 {
3685         shaderstaticparms_count = 0;
3686
3687         // emit all
3688         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
3689         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
3690         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
3691         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
3692         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
3693         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
3694 }
3695
3696 /// information about each possible shader permutation
3697 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
3698 /// currently selected permutation
3699 r_glsl_permutation_t *r_glsl_permutation;
3700 /// storage for permutations linked in the hash table
3701 memexpandablearray_t r_glsl_permutationarray;
3702
3703 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
3704 {
3705         //unsigned int hashdepth = 0;
3706         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
3707         r_glsl_permutation_t *p;
3708         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
3709         {
3710                 if (p->mode == mode && p->permutation == permutation)
3711                 {
3712                         //if (hashdepth > 10)
3713                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3714                         return p;
3715                 }
3716                 //hashdepth++;
3717         }
3718         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
3719         p->mode = mode;
3720         p->permutation = permutation;
3721         p->hashnext = r_glsl_permutationhash[mode][hashindex];
3722         r_glsl_permutationhash[mode][hashindex] = p;
3723         //if (hashdepth > 10)
3724         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
3725         return p;
3726 }
3727
3728 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
3729 {
3730         char *shaderstring;
3731         if (!filename || !filename[0])
3732                 return NULL;
3733         if (!strcmp(filename, "glsl/default.glsl"))
3734         {
3735                 if (!glslshaderstring)
3736                 {
3737                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3738                         if (glslshaderstring)
3739                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
3740                         else
3741                                 glslshaderstring = (char *)builtinshaderstring;
3742                 }
3743                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
3744                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
3745                 return shaderstring;
3746         }
3747         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
3748         if (shaderstring)
3749         {
3750                 if (printfromdisknotice)
3751                         Con_DPrintf("from disk %s... ", filename);
3752                 return shaderstring;
3753         }
3754         return shaderstring;
3755 }
3756
3757 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
3758 {
3759         int i;
3760         int sampler;
3761         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
3762         char *vertexstring, *geometrystring, *fragmentstring;
3763         char permutationname[256];
3764         int vertstrings_count = 0;
3765         int geomstrings_count = 0;
3766         int fragstrings_count = 0;
3767         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3768         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3769         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
3770
3771         if (p->compiled)
3772                 return;
3773         p->compiled = true;
3774         p->program = 0;
3775
3776         permutationname[0] = 0;
3777         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
3778         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
3779         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
3780
3781         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
3782
3783         // the first pretext is which type of shader to compile as
3784         // (later these will all be bound together as a program object)
3785         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
3786         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
3787         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
3788
3789         // the second pretext is the mode (for example a light source)
3790         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
3791         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
3792         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
3793         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
3794
3795         // now add all the permutation pretexts
3796         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
3797         {
3798                 if (permutation & (1<<i))
3799                 {
3800                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
3801                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
3802                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
3803                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
3804                 }
3805                 else
3806                 {
3807                         // keep line numbers correct
3808                         vertstrings_list[vertstrings_count++] = "\n";
3809                         geomstrings_list[geomstrings_count++] = "\n";
3810                         fragstrings_list[fragstrings_count++] = "\n";
3811                 }
3812         }
3813
3814         // add static parms
3815         R_CompileShader_AddStaticParms(mode, permutation);
3816         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3817         vertstrings_count += shaderstaticparms_count;
3818         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3819         geomstrings_count += shaderstaticparms_count;
3820         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
3821         fragstrings_count += shaderstaticparms_count;
3822
3823         // now append the shader text itself
3824         vertstrings_list[vertstrings_count++] = vertexstring;
3825         geomstrings_list[geomstrings_count++] = geometrystring;
3826         fragstrings_list[fragstrings_count++] = fragmentstring;
3827
3828         // if any sources were NULL, clear the respective list
3829         if (!vertexstring)
3830                 vertstrings_count = 0;
3831         if (!geometrystring)
3832                 geomstrings_count = 0;
3833         if (!fragmentstring)
3834                 fragstrings_count = 0;
3835
3836         // compile the shader program
3837         if (vertstrings_count + geomstrings_count + fragstrings_count)
3838                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
3839         if (p->program)
3840         {
3841                 CHECKGLERROR
3842                 qglUseProgram(p->program);CHECKGLERROR
3843                 // look up all the uniform variable names we care about, so we don't
3844                 // have to look them up every time we set them
3845
3846                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
3847                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
3848                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
3849                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
3850                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
3851                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
3852                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
3853                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
3854                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
3855                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
3856                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
3857                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
3858                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
3859                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
3860                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
3861                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
3862                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
3863                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
3864                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
3865                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
3866                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
3867                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
3868                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
3869                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
3870                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
3871                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
3872                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
3873                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
3874                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
3875                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
3876                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
3877                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
3878                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
3879                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
3880                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
3881                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
3882                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
3883                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
3884                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
3885                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
3886                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
3887                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
3888                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
3889                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
3890                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
3891                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
3892                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
3893                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
3894                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
3895                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
3896                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
3897                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
3898                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
3899                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
3900                 p->loc_OffsetMapping_Scale        = qglGetUniformLocation(p->program, "OffsetMapping_Scale");
3901                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
3902                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
3903                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
3904                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
3905                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
3906                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
3907                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
3908                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
3909                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
3910                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
3911                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
3912                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
3913                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
3914                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
3915                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
3916                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
3917                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
3918                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
3919                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
3920                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
3921                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
3922                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
3923                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
3924                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
3925                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
3926                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
3927                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
3928                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
3929                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
3930                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
3931                 // initialize the samplers to refer to the texture units we use
3932                 p->tex_Texture_First = -1;
3933                 p->tex_Texture_Second = -1;
3934                 p->tex_Texture_GammaRamps = -1;
3935                 p->tex_Texture_Normal = -1;
3936                 p->tex_Texture_Color = -1;
3937                 p->tex_Texture_Gloss = -1;
3938                 p->tex_Texture_Glow = -1;
3939                 p->tex_Texture_SecondaryNormal = -1;
3940                 p->tex_Texture_SecondaryColor = -1;
3941                 p->tex_Texture_SecondaryGloss = -1;
3942                 p->tex_Texture_SecondaryGlow = -1;
3943                 p->tex_Texture_Pants = -1;
3944                 p->tex_Texture_Shirt = -1;
3945                 p->tex_Texture_FogHeightTexture = -1;
3946                 p->tex_Texture_FogMask = -1;
3947                 p->tex_Texture_Lightmap = -1;
3948                 p->tex_Texture_Deluxemap = -1;
3949                 p->tex_Texture_Attenuation = -1;
3950                 p->tex_Texture_Cube = -1;
3951                 p->tex_Texture_Refraction = -1;
3952                 p->tex_Texture_Reflection = -1;
3953                 p->tex_Texture_ShadowMap2D = -1;
3954                 p->tex_Texture_CubeProjection = -1;
3955                 p->tex_Texture_ScreenDepth = -1;
3956                 p->tex_Texture_ScreenNormalMap = -1;
3957                 p->tex_Texture_ScreenDiffuse = -1;
3958                 p->tex_Texture_ScreenSpecular = -1;
3959                 p->tex_Texture_ReflectMask = -1;
3960                 p->tex_Texture_ReflectCube = -1;
3961                 p->tex_Texture_BounceGrid = -1;
3962                 sampler = 0;
3963                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
3964                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
3965                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
3966                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
3967                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
3968                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
3969                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
3970                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
3971                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
3972                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
3973                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
3974                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
3975                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
3976                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
3977                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
3978                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
3979                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
3980                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
3981                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
3982                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
3983                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
3984                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
3985                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
3986                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
3987                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
3988                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
3989                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
3990                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
3991                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
3992                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
3993                 CHECKGLERROR
3994                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
3995         }
3996         else
3997                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
3998
3999         // free the strings
4000         if (vertexstring)
4001                 Mem_Free(vertexstring);
4002         if (geometrystring)
4003                 Mem_Free(geometrystring);
4004         if (fragmentstring)
4005                 Mem_Free(fragmentstring);
4006 }
4007
4008 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
4009 {
4010         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
4011         if (r_glsl_permutation != perm)
4012         {
4013                 r_glsl_permutation = perm;
4014                 if (!r_glsl_permutation->program)
4015                 {
4016                         if (!r_glsl_permutation->compiled)
4017                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4018                         if (!r_glsl_permutation->program)
4019                         {
4020                                 // remove features until we find a valid permutation
4021                                 int i;
4022                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4023                                 {
4024                                         // reduce i more quickly whenever it would not remove any bits
4025                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4026                                         if (!(permutation & j))
4027                                                 continue;
4028                                         permutation -= j;
4029                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4030                                         if (!r_glsl_permutation->compiled)
4031                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
4032                                         if (r_glsl_permutation->program)
4033                                                 break;
4034                                 }
4035                                 if (i >= SHADERPERMUTATION_COUNT)
4036                                 {
4037                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4038                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
4039                                         qglUseProgram(0);CHECKGLERROR
4040                                         return; // no bit left to clear, entire mode is broken
4041                                 }
4042                         }
4043                 }
4044                 CHECKGLERROR
4045                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
4046         }
4047         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
4048         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
4049         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
4050 }
4051
4052 #ifdef SUPPORTD3D
4053
4054 #ifdef SUPPORTD3D
4055 #include <d3d9.h>
4056 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
4057 extern D3DCAPS9 vid_d3d9caps;
4058 #endif
4059
4060 struct r_hlsl_permutation_s;
4061 typedef struct r_hlsl_permutation_s
4062 {
4063         /// hash lookup data
4064         struct r_hlsl_permutation_s *hashnext;
4065         unsigned int mode;
4066         unsigned int permutation;
4067
4068         /// indicates if we have tried compiling this permutation already
4069         qboolean compiled;
4070         /// NULL if compilation failed
4071         IDirect3DVertexShader9 *vertexshader;
4072         IDirect3DPixelShader9 *pixelshader;
4073 }
4074 r_hlsl_permutation_t;
4075
4076 typedef enum D3DVSREGISTER_e
4077 {
4078         D3DVSREGISTER_TexMatrix = 0, // float4x4
4079         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
4080         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
4081         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
4082         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
4083         D3DVSREGISTER_ModelToLight = 20, // float4x4
4084         D3DVSREGISTER_EyePosition = 24,
4085         D3DVSREGISTER_FogPlane = 25,
4086         D3DVSREGISTER_LightDir = 26,
4087         D3DVSREGISTER_LightPosition = 27,
4088 }
4089 D3DVSREGISTER_t;
4090
4091 typedef enum D3DPSREGISTER_e
4092 {
4093         D3DPSREGISTER_Alpha = 0,
4094         D3DPSREGISTER_BloomBlur_Parameters = 1,
4095         D3DPSREGISTER_ClientTime = 2,
4096         D3DPSREGISTER_Color_Ambient = 3,
4097         D3DPSREGISTER_Color_Diffuse = 4,
4098         D3DPSREGISTER_Color_Specular = 5,
4099         D3DPSREGISTER_Color_Glow = 6,
4100         D3DPSREGISTER_Color_Pants = 7,
4101         D3DPSREGISTER_Color_Shirt = 8,
4102         D3DPSREGISTER_DeferredColor_Ambient = 9,
4103         D3DPSREGISTER_DeferredColor_Diffuse = 10,
4104         D3DPSREGISTER_DeferredColor_Specular = 11,
4105         D3DPSREGISTER_DeferredMod_Diffuse = 12,
4106         D3DPSREGISTER_DeferredMod_Specular = 13,
4107         D3DPSREGISTER_DistortScaleRefractReflect = 14,
4108         D3DPSREGISTER_EyePosition = 15, // unused
4109         D3DPSREGISTER_FogColor = 16,
4110         D3DPSREGISTER_FogHeightFade = 17,
4111         D3DPSREGISTER_FogPlane = 18,
4112         D3DPSREGISTER_FogPlaneViewDist = 19,
4113         D3DPSREGISTER_FogRangeRecip = 20,
4114         D3DPSREGISTER_LightColor = 21,
4115         D3DPSREGISTER_LightDir = 22, // unused
4116         D3DPSREGISTER_LightPosition = 23,
4117         D3DPSREGISTER_OffsetMapping_Scale = 24,
4118         D3DPSREGISTER_PixelSize = 25,
4119         D3DPSREGISTER_ReflectColor = 26,
4120         D3DPSREGISTER_ReflectFactor = 27,
4121         D3DPSREGISTER_ReflectOffset = 28,
4122         D3DPSREGISTER_RefractColor = 29,
4123         D3DPSREGISTER_Saturation = 30,
4124         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
4125         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
4126         D3DPSREGISTER_ScreenToDepth = 33,
4127         D3DPSREGISTER_ShadowMap_Parameters = 34,
4128         D3DPSREGISTER_ShadowMap_TextureScale = 35,
4129         D3DPSREGISTER_SpecularPower = 36,
4130         D3DPSREGISTER_UserVec1 = 37,
4131         D3DPSREGISTER_UserVec2 = 38,
4132         D3DPSREGISTER_UserVec3 = 39,
4133         D3DPSREGISTER_UserVec4 = 40,
4134         D3DPSREGISTER_ViewTintColor = 41,
4135         D3DPSREGISTER_PixelToScreenTexCoord = 42,
4136         D3DPSREGISTER_BloomColorSubtract = 43,
4137         D3DPSREGISTER_ViewToLight = 44, // float4x4
4138         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
4139         D3DPSREGISTER_NormalmapScrollBlend = 52,
4140         // next at 53
4141 }
4142 D3DPSREGISTER_t;
4143
4144 /// information about each possible shader permutation
4145 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
4146 /// currently selected permutation
4147 r_hlsl_permutation_t *r_hlsl_permutation;
4148 /// storage for permutations linked in the hash table
4149 memexpandablearray_t r_hlsl_permutationarray;
4150
4151 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
4152 {
4153         //unsigned int hashdepth = 0;
4154         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
4155         r_hlsl_permutation_t *p;
4156         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
4157         {
4158                 if (p->mode == mode && p->permutation == permutation)
4159                 {
4160                         //if (hashdepth > 10)
4161                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4162                         return p;
4163                 }
4164                 //hashdepth++;
4165         }
4166         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
4167         p->mode = mode;
4168         p->permutation = permutation;
4169         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
4170         r_hlsl_permutationhash[mode][hashindex] = p;
4171         //if (hashdepth > 10)
4172         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
4173         return p;
4174 }
4175
4176 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
4177 {
4178         char *shaderstring;
4179         if (!filename || !filename[0])
4180                 return NULL;
4181         if (!strcmp(filename, "hlsl/default.hlsl"))
4182         {
4183                 if (!hlslshaderstring)
4184                 {
4185                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4186                         if (hlslshaderstring)
4187                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
4188                         else
4189                                 hlslshaderstring = (char *)builtinhlslshaderstring;
4190                 }
4191                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
4192                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
4193                 return shaderstring;
4194         }
4195         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
4196         if (shaderstring)
4197         {
4198                 if (printfromdisknotice)
4199                         Con_DPrintf("from disk %s... ", filename);
4200                 return shaderstring;
4201         }
4202         return shaderstring;
4203 }
4204
4205 #include <d3dx9.h>
4206 //#include <d3dx9shader.h>
4207 //#include <d3dx9mesh.h>
4208
4209 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
4210 {
4211         DWORD *vsbin = NULL;
4212         DWORD *psbin = NULL;
4213         fs_offset_t vsbinsize;
4214         fs_offset_t psbinsize;
4215 //      IDirect3DVertexShader9 *vs = NULL;
4216 //      IDirect3DPixelShader9 *ps = NULL;
4217         ID3DXBuffer *vslog = NULL;
4218         ID3DXBuffer *vsbuffer = NULL;
4219         ID3DXConstantTable *vsconstanttable = NULL;
4220         ID3DXBuffer *pslog = NULL;
4221         ID3DXBuffer *psbuffer = NULL;
4222         ID3DXConstantTable *psconstanttable = NULL;
4223         int vsresult = 0;
4224         int psresult = 0;
4225         char temp[MAX_INPUTLINE];
4226         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
4227         qboolean debugshader = gl_paranoid.integer != 0;
4228         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4229         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
4230         if (!debugshader)
4231         {
4232                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
4233                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
4234         }
4235         if ((!vsbin && vertstring) || (!psbin && fragstring))
4236         {
4237                 const char* dllnames_d3dx9 [] =
4238                 {
4239                         "d3dx9_43.dll",
4240                         "d3dx9_42.dll",
4241                         "d3dx9_41.dll",
4242                         "d3dx9_40.dll",
4243                         "d3dx9_39.dll",
4244                         "d3dx9_38.dll",
4245                         "d3dx9_37.dll",
4246                         "d3dx9_36.dll",
4247                         "d3dx9_35.dll",
4248                         "d3dx9_34.dll",
4249                         "d3dx9_33.dll",
4250                         "d3dx9_32.dll",
4251                         "d3dx9_31.dll",
4252                         "d3dx9_30.dll",
4253                         "d3dx9_29.dll",
4254                         "d3dx9_28.dll",
4255                         "d3dx9_27.dll",
4256                         "d3dx9_26.dll",
4257                         "d3dx9_25.dll",
4258                         "d3dx9_24.dll",
4259                         NULL
4260                 };
4261                 dllhandle_t d3dx9_dll = NULL;
4262                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4263                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
4264                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
4265                 dllfunction_t d3dx9_dllfuncs[] =
4266                 {
4267                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
4268                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
4269                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
4270                         {NULL, NULL}
4271                 };
4272                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
4273                 {
4274                         DWORD shaderflags = 0;
4275                         if (debugshader)
4276                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
4277                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4278                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4279                         if (vertstring && vertstring[0])
4280                         {
4281                                 if (debugshader)
4282                                 {
4283 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
4284 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
4285                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
4286                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4287                                 }
4288                                 else
4289                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
4290                                 if (vsbuffer)
4291                                 {
4292                                         vsbinsize = vsbuffer->GetBufferSize();
4293                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
4294                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
4295                                         vsbuffer->Release();
4296                                 }
4297                                 if (vslog)
4298                                 {
4299                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
4300                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
4301                                         vslog->Release();
4302                                 }
4303                         }
4304                         if (fragstring && fragstring[0])
4305                         {
4306                                 if (debugshader)
4307                                 {
4308 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
4309 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
4310                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
4311                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4312                                 }
4313                                 else
4314                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
4315                                 if (psbuffer)
4316                                 {
4317                                         psbinsize = psbuffer->GetBufferSize();
4318                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
4319                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
4320                                         psbuffer->Release();
4321                                 }
4322                                 if (pslog)
4323                                 {
4324                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
4325                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
4326                                         pslog->Release();
4327                                 }
4328                         }
4329                         Sys_UnloadLibrary(&d3dx9_dll);
4330                 }
4331                 else
4332                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
4333         }
4334         if (vsbin && psbin)
4335         {
4336                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
4337                 if (FAILED(vsresult))
4338                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
4339                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
4340                 if (FAILED(psresult))
4341                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
4342         }
4343         // free the shader data
4344         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
4345         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
4346 }
4347
4348 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
4349 {
4350         int i;
4351         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
4352         int vertstring_length = 0;
4353         int geomstring_length = 0;
4354         int fragstring_length = 0;
4355         char *t;
4356         char *vertexstring, *geometrystring, *fragmentstring;
4357         char *vertstring, *geomstring, *fragstring;
4358         char permutationname[256];
4359         char cachename[256];
4360         int vertstrings_count = 0;
4361         int geomstrings_count = 0;
4362         int fragstrings_count = 0;
4363         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4364         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4365         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
4366
4367         if (p->compiled)
4368                 return;
4369         p->compiled = true;
4370         p->vertexshader = NULL;
4371         p->pixelshader = NULL;
4372
4373         permutationname[0] = 0;
4374         cachename[0] = 0;
4375         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
4376         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
4377         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
4378
4379         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
4380         strlcat(cachename, "hlsl/", sizeof(cachename));
4381
4382         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
4383         vertstrings_count = 0;
4384         geomstrings_count = 0;
4385         fragstrings_count = 0;
4386         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
4387         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
4388         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
4389
4390         // the first pretext is which type of shader to compile as
4391         // (later these will all be bound together as a program object)
4392         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
4393         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
4394         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
4395
4396         // the second pretext is the mode (for example a light source)
4397         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
4398         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
4399         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
4400         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
4401         strlcat(cachename, modeinfo->name, sizeof(cachename));
4402
4403         // now add all the permutation pretexts
4404         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4405         {
4406                 if (permutation & (1<<i))
4407                 {
4408                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
4409                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
4410                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
4411                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
4412                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
4413                 }
4414                 else
4415                 {
4416                         // keep line numbers correct
4417                         vertstrings_list[vertstrings_count++] = "\n";
4418                         geomstrings_list[geomstrings_count++] = "\n";
4419                         fragstrings_list[fragstrings_count++] = "\n";
4420                 }
4421         }
4422
4423         // add static parms
4424         R_CompileShader_AddStaticParms(mode, permutation);
4425         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4426         vertstrings_count += shaderstaticparms_count;
4427         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4428         geomstrings_count += shaderstaticparms_count;
4429         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
4430         fragstrings_count += shaderstaticparms_count;
4431
4432         // replace spaces in the cachename with _ characters
4433         for (i = 0;cachename[i];i++)
4434                 if (cachename[i] == ' ')
4435                         cachename[i] = '_';
4436
4437         // now append the shader text itself
4438         vertstrings_list[vertstrings_count++] = vertexstring;
4439         geomstrings_list[geomstrings_count++] = geometrystring;
4440         fragstrings_list[fragstrings_count++] = fragmentstring;
4441
4442         // if any sources were NULL, clear the respective list
4443         if (!vertexstring)
4444                 vertstrings_count = 0;
4445         if (!geometrystring)
4446                 geomstrings_count = 0;
4447         if (!fragmentstring)
4448                 fragstrings_count = 0;
4449
4450         vertstring_length = 0;
4451         for (i = 0;i < vertstrings_count;i++)
4452                 vertstring_length += strlen(vertstrings_list[i]);
4453         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
4454         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
4455                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
4456
4457         geomstring_length = 0;
4458         for (i = 0;i < geomstrings_count;i++)
4459                 geomstring_length += strlen(geomstrings_list[i]);
4460         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
4461         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
4462                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
4463
4464         fragstring_length = 0;
4465         for (i = 0;i < fragstrings_count;i++)
4466                 fragstring_length += strlen(fragstrings_list[i]);
4467         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
4468         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
4469                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
4470
4471         // try to load the cached shader, or generate one
4472         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
4473
4474         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
4475                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
4476         else
4477                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
4478
4479         // free the strings
4480         if (vertstring)
4481                 Mem_Free(vertstring);
4482         if (geomstring)
4483                 Mem_Free(geomstring);
4484         if (fragstring)
4485                 Mem_Free(fragstring);
4486         if (vertexstring)
4487                 Mem_Free(vertexstring);
4488         if (geometrystring)
4489                 Mem_Free(geometrystring);
4490         if (fragmentstring)
4491                 Mem_Free(fragmentstring);
4492 }
4493
4494 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
4495 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
4496 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);}
4497 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);}
4498 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);}
4499 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);}
4500
4501 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
4502 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
4503 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);}
4504 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);}
4505 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);}
4506 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);}
4507
4508 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
4509 {
4510         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
4511         if (r_hlsl_permutation != perm)
4512         {
4513                 r_hlsl_permutation = perm;
4514                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4515                 {
4516                         if (!r_hlsl_permutation->compiled)
4517                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4518                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
4519                         {
4520                                 // remove features until we find a valid permutation
4521                                 int i;
4522                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4523                                 {
4524                                         // reduce i more quickly whenever it would not remove any bits
4525                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
4526                                         if (!(permutation & j))
4527                                                 continue;
4528                                         permutation -= j;
4529                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4530                                         if (!r_hlsl_permutation->compiled)
4531                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
4532                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
4533                                                 break;
4534                                 }
4535                                 if (i >= SHADERPERMUTATION_COUNT)
4536                                 {
4537                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
4538                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
4539                                         return; // no bit left to clear, entire mode is broken
4540                                 }
4541                         }
4542                 }
4543                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
4544                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
4545         }
4546         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
4547         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
4548         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
4549 }
4550 #endif
4551
4552 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
4553 {
4554         DPSOFTRAST_SetShader(mode, permutation);
4555         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
4556         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
4557         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
4558 }
4559
4560 void R_GLSL_Restart_f(void)
4561 {
4562         unsigned int i, limit;
4563         if (glslshaderstring && glslshaderstring != builtinshaderstring)
4564                 Mem_Free(glslshaderstring);
4565         glslshaderstring = NULL;
4566         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
4567                 Mem_Free(hlslshaderstring);
4568         hlslshaderstring = NULL;
4569         switch(vid.renderpath)
4570         {
4571         case RENDERPATH_D3D9:
4572 #ifdef SUPPORTD3D
4573                 {
4574                         r_hlsl_permutation_t *p;
4575                         r_hlsl_permutation = NULL;
4576                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
4577                         for (i = 0;i < limit;i++)
4578                         {
4579                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
4580                                 {
4581                                         if (p->vertexshader)
4582                                                 IDirect3DVertexShader9_Release(p->vertexshader);
4583                                         if (p->pixelshader)
4584                                                 IDirect3DPixelShader9_Release(p->pixelshader);
4585                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
4586                                 }
4587                         }
4588                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4589                 }
4590 #endif
4591                 break;
4592         case RENDERPATH_D3D10:
4593                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4594                 break;
4595         case RENDERPATH_D3D11:
4596                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4597                 break;
4598         case RENDERPATH_GL20:
4599         case RENDERPATH_GLES2:
4600                 {
4601                         r_glsl_permutation_t *p;
4602                         r_glsl_permutation = NULL;
4603                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
4604                         for (i = 0;i < limit;i++)
4605                         {
4606                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
4607                                 {
4608                                         GL_Backend_FreeProgram(p->program);
4609                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
4610                                 }
4611                         }
4612                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4613                 }
4614                 break;
4615         case RENDERPATH_GL13:
4616         case RENDERPATH_GL11:
4617                 break;
4618         case RENDERPATH_SOFT:
4619                 break;
4620         }
4621 }
4622
4623 void R_GLSL_DumpShader_f(void)
4624 {
4625         int i;
4626         qfile_t *file;
4627
4628         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
4629         if (file)
4630         {
4631                 FS_Print(file, "/* The engine may define the following macros:\n");
4632                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4633                 for (i = 0;i < SHADERMODE_COUNT;i++)
4634                         FS_Print(file, glslshadermodeinfo[i].pretext);
4635                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4636                         FS_Print(file, shaderpermutationinfo[i].pretext);
4637                 FS_Print(file, "*/\n");
4638                 FS_Print(file, builtinshaderstring);
4639                 FS_Close(file);
4640                 Con_Printf("glsl/default.glsl written\n");
4641         }
4642         else
4643                 Con_Printf("failed to write to glsl/default.glsl\n");
4644
4645         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
4646         if (file)
4647         {
4648                 FS_Print(file, "/* The engine may define the following macros:\n");
4649                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
4650                 for (i = 0;i < SHADERMODE_COUNT;i++)
4651                         FS_Print(file, hlslshadermodeinfo[i].pretext);
4652                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
4653                         FS_Print(file, shaderpermutationinfo[i].pretext);
4654                 FS_Print(file, "*/\n");
4655                 FS_Print(file, builtinhlslshaderstring);
4656                 FS_Close(file);
4657                 Con_Printf("hlsl/default.hlsl written\n");
4658         }
4659         else
4660                 Con_Printf("failed to write to hlsl/default.hlsl\n");
4661 }
4662
4663 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale)
4664 {
4665         if (!second)
4666                 texturemode = GL_MODULATE;
4667         switch (vid.renderpath)
4668         {
4669         case RENDERPATH_D3D9:
4670 #ifdef SUPPORTD3D
4671                 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))));
4672                 R_Mesh_TexBind(GL20TU_FIRST , first );
4673                 R_Mesh_TexBind(GL20TU_SECOND, second);
4674 #endif
4675                 break;
4676         case RENDERPATH_D3D10:
4677                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4678                 break;
4679         case RENDERPATH_D3D11:
4680                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4681                 break;
4682         case RENDERPATH_GL20:
4683         case RENDERPATH_GLES2:
4684                 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))));
4685                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
4686                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
4687                 break;
4688         case RENDERPATH_GL13:
4689                 R_Mesh_TexBind(0, first );
4690                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
4691                 R_Mesh_TexBind(1, second);
4692                 if (second)
4693                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
4694                 break;
4695         case RENDERPATH_GL11:
4696                 R_Mesh_TexBind(0, first );
4697                 break;
4698         case RENDERPATH_SOFT:
4699                 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))));
4700                 R_Mesh_TexBind(GL20TU_FIRST , first );
4701                 R_Mesh_TexBind(GL20TU_SECOND, second);
4702                 break;
4703         }
4704 }
4705
4706 void R_SetupShader_DepthOrShadow(void)
4707 {
4708         switch (vid.renderpath)
4709         {
4710         case RENDERPATH_D3D9:
4711 #ifdef SUPPORTD3D
4712                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4713 #endif
4714                 break;
4715         case RENDERPATH_D3D10:
4716                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4717                 break;
4718         case RENDERPATH_D3D11:
4719                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4720                 break;
4721         case RENDERPATH_GL20:
4722         case RENDERPATH_GLES2:
4723                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, 0);
4724                 break;
4725         case RENDERPATH_GL13:
4726                 R_Mesh_TexBind(0, 0);
4727                 R_Mesh_TexBind(1, 0);
4728                 break;
4729         case RENDERPATH_GL11:
4730                 R_Mesh_TexBind(0, 0);
4731                 break;
4732         case RENDERPATH_SOFT:
4733                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, 0);
4734                 break;
4735         }
4736 }
4737
4738 void R_SetupShader_ShowDepth(void)
4739 {
4740         switch (vid.renderpath)
4741         {
4742         case RENDERPATH_D3D9:
4743 #ifdef SUPPORTHLSL
4744                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, 0);
4745 #endif
4746                 break;
4747         case RENDERPATH_D3D10:
4748                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4749                 break;
4750         case RENDERPATH_D3D11:
4751                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4752                 break;
4753         case RENDERPATH_GL20:
4754         case RENDERPATH_GLES2:
4755                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, 0);
4756                 break;
4757         case RENDERPATH_GL13:
4758                 break;
4759         case RENDERPATH_GL11:
4760                 break;
4761         case RENDERPATH_SOFT:
4762                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, 0);
4763                 break;
4764         }
4765 }
4766
4767 extern qboolean r_shadow_usingdeferredprepass;
4768 extern cvar_t r_shadow_deferred_8bitrange;
4769 extern rtexture_t *r_shadow_attenuationgradienttexture;
4770 extern rtexture_t *r_shadow_attenuation2dtexture;
4771 extern rtexture_t *r_shadow_attenuation3dtexture;
4772 extern qboolean r_shadow_usingshadowmap2d;
4773 extern qboolean r_shadow_usingshadowmaportho;
4774 extern float r_shadow_shadowmap_texturescale[2];
4775 extern float r_shadow_shadowmap_parameters[4];
4776 extern qboolean r_shadow_shadowmapvsdct;
4777 extern qboolean r_shadow_shadowmapsampler;
4778 extern int r_shadow_shadowmappcf;
4779 extern rtexture_t *r_shadow_shadowmap2dtexture;
4780 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
4781 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
4782 extern matrix4x4_t r_shadow_shadowmapmatrix;
4783 extern int r_shadow_shadowmaplod; // changes for each light based on distance
4784 extern int r_shadow_prepass_width;
4785 extern int r_shadow_prepass_height;
4786 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
4787 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
4788 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
4789 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
4790 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
4791 static qboolean R_BlendFuncAllowsColormod(int src, int dst)
4792 {
4793         // a blendfunc allows colormod if:
4794         // a) it can never keep the destination pixel invariant, or
4795         // b) it can keep the destination pixel invariant, and still can do so if colormodded
4796         // this is to prevent unintended side effects from colormod
4797
4798         // in formulas:
4799         // IF there is a (s, sa) for which for all (d, da),
4800         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4801         // THEN, for this (s, sa) and all (colormod, d, da):
4802         //   s*colormod * src(s*colormod, d, sa, da) + d * dst(s*colormod, d, sa, da) == d
4803         // OBVIOUSLY, this means that
4804         //   s*colormod * src(s*colormod, d, sa, da) = 0
4805         //   dst(s*colormod, d, sa, da)              = 1
4806
4807         // note: not caring about GL_SRC_ALPHA_SATURATE and following here, these are unused in DP code
4808
4809         // main condition to leave dst color invariant:
4810         //   s * src(s, d, sa, da) + d * dst(s, d, sa, da) == d
4811         //   src == GL_ZERO:
4812         //     s * 0 + d * dst(s, d, sa, da) == d
4813         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4814         //       => colormod is a problem for GL_SRC_COLOR only
4815         //   src == GL_ONE:
4816         //     s + d * dst(s, d, sa, da) == d
4817         //       => s == 0
4818         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4819         //       => colormod is never problematic for these
4820         //   src == GL_SRC_COLOR:
4821         //     s*s + d * dst(s, d, sa, da) == d
4822         //       => s == 0
4823         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4824         //       => colormod is never problematic for these
4825         //   src == GL_ONE_MINUS_SRC_COLOR:
4826         //     s*(1-s) + d * dst(s, d, sa, da) == d
4827         //       => s == 0 or s == 1
4828         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4829         //       => colormod is a problem for GL_SRC_COLOR only
4830         //   src == GL_DST_COLOR
4831         //     s*d + d * dst(s, d, sa, da) == d
4832         //       => s == 1
4833         //       => dst == GL_ZERO/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4834         //       => colormod is always a problem
4835         //     or
4836         //       => s == 0
4837         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4838         //       => colormod is never problematic for these
4839         //       => BUT, we do not know s! We must assume it is problematic
4840         //       then... except in GL_ONE case, where we know all invariant
4841         //       cases are fine
4842         //   src == GL_ONE_MINUS_DST_COLOR
4843         //     s*(1-d) + d * dst(s, d, sa, da) == d
4844         //       => s == 0 (1-d is impossible to handle for our desired result)
4845         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4846         //       => colormod is never problematic for these
4847         //   src == GL_SRC_ALPHA
4848         //     s*sa + d * dst(s, d, sa, da) == d
4849         //       => s == 0, or sa == 0
4850         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4851         //       => colormod breaks in the case GL_SRC_COLOR only
4852         //   src == GL_ONE_MINUS_SRC_ALPHA
4853         //     s*(1-sa) + d * dst(s, d, sa, da) == d
4854         //       => s == 0, or sa == 1
4855         //       => dst == GL_ONE/GL_SRC_COLOR/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4856         //       => colormod breaks in the case GL_SRC_COLOR only
4857         //   src == GL_DST_ALPHA
4858         //     s*da + d * dst(s, d, sa, da) == d
4859         //       => s == 0
4860         //       => dst == GL_ONE/GL_ONE_MINUS_SRC_COLOR/GL_SRC_ALPHA/GL_ONE_MINUS_SRC_ALPHA
4861         //       => colormod is never problematic for these
4862
4863         switch(src)
4864         {
4865                 case GL_ZERO:
4866                 case GL_ONE_MINUS_SRC_COLOR:
4867                 case GL_SRC_ALPHA:
4868                 case GL_ONE_MINUS_SRC_ALPHA:
4869                         if(dst == GL_SRC_COLOR)
4870                                 return false;
4871                         return true;
4872                 case GL_ONE:
4873                 case GL_SRC_COLOR:
4874                 case GL_ONE_MINUS_DST_COLOR:
4875                 case GL_DST_ALPHA:
4876                 case GL_ONE_MINUS_DST_ALPHA:
4877                         return true;
4878                 case GL_DST_COLOR:
4879                         if(dst == GL_ONE)
4880                                 return true;
4881                         return false;
4882                 default:
4883                         return false;
4884         }
4885 }
4886 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)
4887 {
4888         // select a permutation of the lighting shader appropriate to this
4889         // combination of texture, entity, light source, and fogging, only use the
4890         // minimum features necessary to avoid wasting rendering time in the
4891         // fragment shader on features that are not being used
4892         unsigned int permutation = 0;
4893         unsigned int mode = 0;
4894         qboolean allow_colormod;
4895         static float dummy_colormod[3] = {1, 1, 1};
4896         float *colormod = rsurface.colormod;
4897         float m16f[16];
4898         matrix4x4_t tempmatrix;
4899         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
4900         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
4901                 permutation |= SHADERPERMUTATION_ALPHAKILL;
4902         if (rsurfacepass == RSURFPASS_BACKGROUND)
4903         {
4904                 // distorted background
4905                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
4906                 {
4907                         mode = SHADERMODE_WATER;
4908                         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
4909                                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND;
4910                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
4911                         {
4912                                 // this is the right thing to do for wateralpha
4913                                 GL_BlendFunc(GL_ONE, GL_ZERO);
4914                                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4915                         }
4916                         else
4917                         {
4918                                 // this is the right thing to do for entity alpha
4919                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4920                                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4921                         }
4922                 }
4923                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
4924                 {
4925                         mode = SHADERMODE_REFRACTION;
4926                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4927                         allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
4928                 }
4929                 else
4930                 {
4931                         mode = SHADERMODE_GENERIC;
4932                         permutation |= SHADERPERMUTATION_DIFFUSE;
4933                         GL_BlendFunc(GL_ONE, GL_ZERO);
4934                         allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4935                 }
4936         }
4937         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
4938         {
4939                 if (r_glsl_offsetmapping.integer)
4940                 {
4941                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4942                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4943                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4944                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4945                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4946                         {
4947                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4948                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4949                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4950                         }
4951                 }
4952                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4953                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4954                 // normalmap (deferred prepass), may use alpha test on diffuse
4955                 mode = SHADERMODE_DEFERREDGEOMETRY;
4956                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4957                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4958                 GL_BlendFunc(GL_ONE, GL_ZERO);
4959                 allow_colormod = R_BlendFuncAllowsColormod(GL_ONE, GL_ZERO);
4960         }
4961         else if (rsurfacepass == RSURFPASS_RTLIGHT)
4962         {
4963                 if (r_glsl_offsetmapping.integer)
4964                 {
4965                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
4966                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4967                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
4968                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4969                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
4970                         {
4971                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
4972                                 if (r_glsl_offsetmapping_reliefmapping.integer)
4973                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
4974                         }
4975                 }
4976                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4977                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4978                 // light source
4979                 mode = SHADERMODE_LIGHTSOURCE;
4980                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
4981                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
4982                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
4983                         permutation |= SHADERPERMUTATION_CUBEFILTER;
4984                 if (diffusescale > 0)
4985                         permutation |= SHADERPERMUTATION_DIFFUSE;
4986                 if (specularscale > 0)
4987                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
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_usingshadowmap2d)
4993                 {
4994                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
4995                         if(r_shadow_shadowmapvsdct)
4996                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
4997
4998                         if (r_shadow_shadowmapsampler)
4999                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5000                         if (r_shadow_shadowmappcf > 1)
5001                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5002                         else if (r_shadow_shadowmappcf)
5003                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5004                 }
5005                 if (rsurface.texture->reflectmasktexture)
5006                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5007                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
5008                 allow_colormod = R_BlendFuncAllowsColormod(GL_SRC_ALPHA, GL_ONE);
5009         }
5010         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
5011         {
5012                 if (r_glsl_offsetmapping.integer)
5013                 {
5014                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5015                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5016                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5017                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5018                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5019                         {
5020                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5021                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5022                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5023                         }
5024                 }
5025                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5026                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5027                 // unshaded geometry (fullbright or ambient model lighting)
5028                 mode = SHADERMODE_FLATCOLOR;
5029                 ambientscale = diffusescale = specularscale = 0;
5030                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5031                         permutation |= SHADERPERMUTATION_GLOW;
5032                 if (r_refdef.fogenabled)
5033                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5034                 if (rsurface.texture->colormapping)
5035                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5036                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5037                 {
5038                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5039                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5040
5041                         if (r_shadow_shadowmapsampler)
5042                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5043                         if (r_shadow_shadowmappcf > 1)
5044                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5045                         else if (r_shadow_shadowmappcf)
5046                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5047                 }
5048                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5049                         permutation |= SHADERPERMUTATION_REFLECTION;
5050                 if (rsurface.texture->reflectmasktexture)
5051                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5052                 if (r_shadow_bouncegridtexture)
5053                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5054                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5055                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5056         }
5057         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
5058         {
5059                 if (r_glsl_offsetmapping.integer)
5060                 {
5061                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5062                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5063                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5064                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5065                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5066                         {
5067                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5068                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5069                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5070                         }
5071                 }
5072                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5073                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5074                 // directional model lighting
5075                 mode = SHADERMODE_LIGHTDIRECTION;
5076                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5077                         permutation |= SHADERPERMUTATION_GLOW;
5078                 permutation |= SHADERPERMUTATION_DIFFUSE;
5079                 if (specularscale > 0)
5080                         permutation |= SHADERPERMUTATION_SPECULAR;
5081                 if (r_refdef.fogenabled)
5082                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5083                 if (rsurface.texture->colormapping)
5084                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5085                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5086                 {
5087                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5088                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5089
5090                         if (r_shadow_shadowmapsampler)
5091                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5092                         if (r_shadow_shadowmappcf > 1)
5093                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5094                         else if (r_shadow_shadowmappcf)
5095                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5096                 }
5097                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5098                         permutation |= SHADERPERMUTATION_REFLECTION;
5099                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5100                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5101                 if (rsurface.texture->reflectmasktexture)
5102                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5103                 if (r_shadow_bouncegridtexture)
5104                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5105                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5106                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5107         }
5108         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
5109         {
5110                 if (r_glsl_offsetmapping.integer)
5111                 {
5112                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5113                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5114                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5115                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5116                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5117                         {
5118                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5119                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5120                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5121                         }
5122                 }
5123                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5124                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5125                 // ambient model lighting
5126                 mode = SHADERMODE_LIGHTDIRECTION;
5127                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5128                         permutation |= SHADERPERMUTATION_GLOW;
5129                 if (r_refdef.fogenabled)
5130                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5131                 if (rsurface.texture->colormapping)
5132                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5133                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5134                 {
5135                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5136                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5137
5138                         if (r_shadow_shadowmapsampler)
5139                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5140                         if (r_shadow_shadowmappcf > 1)
5141                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5142                         else if (r_shadow_shadowmappcf)
5143                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5144                 }
5145                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5146                         permutation |= SHADERPERMUTATION_REFLECTION;
5147                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5148                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5149                 if (rsurface.texture->reflectmasktexture)
5150                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5151                 if (r_shadow_bouncegridtexture)
5152                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5153                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5154                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5155         }
5156         else
5157         {
5158                 if (r_glsl_offsetmapping.integer)
5159                 {
5160                         if (rsurface.texture->offsetmapping == OFFSETMAPPING_LINEAR)
5161                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5162                         else if (rsurface.texture->offsetmapping == OFFSETMAPPING_RELIEF)
5163                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5164                         else if (rsurface.texture->offsetmapping != OFFSETMAPPING_OFF)
5165                         {
5166                                 permutation |= SHADERPERMUTATION_OFFSETMAPPING;
5167                                 if (r_glsl_offsetmapping_reliefmapping.integer)
5168                                         permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;
5169                         }
5170                 }
5171                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
5172                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
5173                 // lightmapped wall
5174                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
5175                         permutation |= SHADERPERMUTATION_GLOW;
5176                 if (r_refdef.fogenabled)
5177                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
5178                 if (rsurface.texture->colormapping)
5179                         permutation |= SHADERPERMUTATION_COLORMAPPING;
5180                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
5181                 {
5182                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
5183                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5184
5185                         if (r_shadow_shadowmapsampler)
5186                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5187                         if (r_shadow_shadowmappcf > 1)
5188                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5189                         else if (r_shadow_shadowmappcf)
5190                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5191                 }
5192                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
5193                         permutation |= SHADERPERMUTATION_REFLECTION;
5194                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
5195                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
5196                 if (rsurface.texture->reflectmasktexture)
5197                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
5198                 if (FAKELIGHT_ENABLED)
5199                 {
5200                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
5201                         mode = SHADERMODE_FAKELIGHT;
5202                         permutation |= SHADERPERMUTATION_DIFFUSE;
5203                         if (specularscale > 0)
5204                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5205                 }
5206                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
5207                 {
5208                         // deluxemapping (light direction texture)
5209                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
5210                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
5211                         else
5212                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5213                         permutation |= SHADERPERMUTATION_DIFFUSE;
5214                         if (specularscale > 0)
5215                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5216                 }
5217                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
5218                 {
5219                         // fake deluxemapping (uniform light direction in tangentspace)
5220                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
5221                         permutation |= SHADERPERMUTATION_DIFFUSE;
5222                         if (specularscale > 0)
5223                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5224                 }
5225                 else if (rsurface.uselightmaptexture)
5226                 {
5227                         // ordinary lightmapping (q1bsp, q3bsp)
5228                         mode = SHADERMODE_LIGHTMAP;
5229                 }
5230                 else
5231                 {
5232                         // ordinary vertex coloring (q3bsp)
5233                         mode = SHADERMODE_VERTEXCOLOR;
5234                 }
5235                 if (r_shadow_bouncegridtexture)
5236                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
5237                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5238                 allow_colormod = R_BlendFuncAllowsColormod(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
5239         }
5240         if(!allow_colormod)
5241                 colormod = dummy_colormod;
5242         switch(vid.renderpath)
5243         {
5244         case RENDERPATH_D3D9:
5245 #ifdef SUPPORTD3D
5246                 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);
5247                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5248                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5249                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
5250                 if (mode == SHADERMODE_LIGHTSOURCE)
5251                 {
5252                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
5253                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5254                 }
5255                 else
5256                 {
5257                         if (mode == SHADERMODE_LIGHTDIRECTION)
5258                         {
5259                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5260                         }
5261                 }
5262                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
5263                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
5264                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
5265                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5266                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5267
5268                 if (mode == SHADERMODE_LIGHTSOURCE)
5269                 {
5270                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5271                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5272                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5273                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5274                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5275
5276                         // additive passes are only darkened by fog, not tinted
5277                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5278                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5279                 }
5280                 else
5281                 {
5282                         if (mode == SHADERMODE_FLATCOLOR)
5283                         {
5284                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5285                         }
5286                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5287                         {
5288                                 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]);
5289                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5290                                 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);
5291                                 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);
5292                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5293                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
5294                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5295                         }
5296                         else
5297                         {
5298                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5299                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5300                                 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);
5301                                 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);
5302                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5303                         }
5304                         // additive passes are only darkened by fog, not tinted
5305                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5306                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
5307                         else
5308                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5309                         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);
5310                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5311                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5312                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5313                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
5314                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5315                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
5316                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5317                         if (mode == SHADERMODE_WATER)
5318                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5319                 }
5320                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5321                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5322                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5323                 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));
5324                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5325                 if (rsurface.texture->pantstexture)
5326                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5327                 else
5328                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
5329                 if (rsurface.texture->shirttexture)
5330                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5331                 else
5332                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
5333                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5334                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
5335                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
5336                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
5337                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value);
5338                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5339                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5340
5341                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5342                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5343                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5344                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5345                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5346                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5347                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5348                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5349                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5350                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5351                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5352                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5353                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5354                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5355                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5356                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5357                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5358                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5359                 {
5360                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5361                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5362                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5363                 }
5364                 else
5365                 {
5366                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5367                 }
5368 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5369 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5370                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5371                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5372                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5373                 {
5374                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5375                         if (rsurface.rtlight)
5376                         {
5377                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5378                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5379                         }
5380                 }
5381 #endif
5382                 break;
5383         case RENDERPATH_D3D10:
5384                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5385                 break;
5386         case RENDERPATH_D3D11:
5387                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5388                 break;
5389         case RENDERPATH_GL20:
5390         case RENDERPATH_GLES2:
5391                 if (!vid.useinterleavedarrays)
5392                 {
5393                         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);
5394                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
5395                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
5396                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
5397                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
5398                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
5399                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
5400                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
5401                 }
5402                 else
5403                 {
5404                         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);
5405                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
5406                 }
5407                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5408                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
5409                 if (mode == SHADERMODE_LIGHTSOURCE)
5410                 {
5411                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
5412                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5413                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5414                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5415                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5416                         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);
5417         
5418                         // additive passes are only darkened by fog, not tinted
5419                         if (r_glsl_permutation->loc_FogColor >= 0)
5420                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5421                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5422                 }
5423                 else
5424                 {
5425                         if (mode == SHADERMODE_FLATCOLOR)
5426                         {
5427                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5428                         }
5429                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5430                         {
5431                                 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]);
5432                                 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]);
5433                                 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);
5434                                 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);
5435                                 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);
5436                                 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]);
5437                                 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]);
5438                         }
5439                         else
5440                         {
5441                                 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]);
5442                                 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]);
5443                                 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);
5444                                 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);
5445                                 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);
5446                         }
5447                         // additive passes are only darkened by fog, not tinted
5448                         if (r_glsl_permutation->loc_FogColor >= 0)
5449                         {
5450                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5451                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
5452                                 else
5453                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5454                         }
5455                         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);
5456                         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]);
5457                         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]);
5458                         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]);
5459                         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]);
5460                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5461                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
5462                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5463                         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]);
5464                 }
5465                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
5466                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
5467                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
5468                 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]);
5469                 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]);
5470
5471                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5472                 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));
5473                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5474                 if (r_glsl_permutation->loc_Color_Pants >= 0)
5475                 {
5476                         if (rsurface.texture->pantstexture)
5477                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5478                         else
5479                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
5480                 }
5481                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
5482                 {
5483                         if (rsurface.texture->shirttexture)
5484                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5485                         else
5486                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
5487                 }
5488                 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]);
5489                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
5490                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
5491                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
5492                 if (r_glsl_permutation->loc_OffsetMapping_Scale >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5493                 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]);
5494                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5495                 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);}
5496                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity);
5497
5498                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
5499                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
5500                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
5501                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
5502                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
5503                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
5504                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
5505                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
5506                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
5507                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
5508                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
5509                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
5510                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
5511                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
5512                 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);
5513                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
5514                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
5515                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5516                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5517                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
5518                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5519                 {
5520                         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);
5521                         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);
5522                         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);
5523                 }
5524                 else
5525                 {
5526                         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);
5527                 }
5528                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
5529                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
5530                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
5531                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
5532                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5533                 {
5534                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
5535                         if (rsurface.rtlight)
5536                         {
5537                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
5538                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
5539                         }
5540                 }
5541                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
5542                 CHECKGLERROR
5543                 break;
5544         case RENDERPATH_GL13:
5545         case RENDERPATH_GL11:
5546                 break;
5547         case RENDERPATH_SOFT:
5548                 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);
5549                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
5550                 R_SetupShader_SetPermutationSoft(mode, permutation);
5551                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
5552                 if (mode == SHADERMODE_LIGHTSOURCE)
5553                 {
5554                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
5555                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
5556                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
5557                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
5558                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
5559                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
5560         
5561                         // additive passes are only darkened by fog, not tinted
5562                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5563                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5564                 }
5565                 else
5566                 {
5567                         if (mode == SHADERMODE_FLATCOLOR)
5568                         {
5569                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
5570                         }
5571                         else if (mode == SHADERMODE_LIGHTDIRECTION)
5572                         {
5573                                 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]);
5574                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
5575                                 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);
5576                                 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);
5577                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5578                                 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]);
5579                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
5580                         }
5581                         else
5582                         {
5583                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
5584                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
5585                                 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);
5586                                 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);
5587                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
5588                         }
5589                         // additive passes are only darkened by fog, not tinted
5590                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
5591                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
5592                         else
5593                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
5594                         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);
5595                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
5596                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
5597                         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]);
5598                         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]);
5599                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
5600                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
5601                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5602                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
5603                 }
5604                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
5605                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
5606                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
5607                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5608                 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]);
5609
5610                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
5611                 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));
5612                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
5613                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
5614                 {
5615                         if (rsurface.texture->pantstexture)
5616                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
5617                         else
5618                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
5619                 }
5620                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
5621                 {
5622                         if (rsurface.texture->shirttexture)
5623                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
5624                         else
5625                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
5626                 }
5627                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
5628                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
5629                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
5630                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
5631                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Scale, r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale);
5632                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5633                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5634
5635                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
5636                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
5637                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
5638                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
5639                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
5640                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
5641                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
5642                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
5643                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
5644                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
5645                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
5646                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
5647                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
5648                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
5649                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
5650                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
5651                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
5652                 if (rsurfacepass == RSURFPASS_BACKGROUND)
5653                 {
5654                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
5655                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
5656                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5657                 }
5658                 else
5659                 {
5660                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
5661                 }
5662 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
5663 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
5664                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
5665                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
5666                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
5667                 {
5668                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
5669                         if (rsurface.rtlight)
5670                         {
5671                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
5672                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
5673                         }
5674                 }
5675                 break;
5676         }
5677 }
5678
5679 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
5680 {
5681         // select a permutation of the lighting shader appropriate to this
5682         // combination of texture, entity, light source, and fogging, only use the
5683         // minimum features necessary to avoid wasting rendering time in the
5684         // fragment shader on features that are not being used
5685         unsigned int permutation = 0;
5686         unsigned int mode = 0;
5687         const float *lightcolorbase = rtlight->currentcolor;
5688         float ambientscale = rtlight->ambientscale;
5689         float diffusescale = rtlight->diffusescale;
5690         float specularscale = rtlight->specularscale;
5691         // this is the location of the light in view space
5692         vec3_t viewlightorigin;
5693         // this transforms from view space (camera) to light space (cubemap)
5694         matrix4x4_t viewtolight;
5695         matrix4x4_t lighttoview;
5696         float viewtolight16f[16];
5697         float range = 1.0f / r_shadow_deferred_8bitrange.value;
5698         // light source
5699         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
5700         if (rtlight->currentcubemap != r_texture_whitecube)
5701                 permutation |= SHADERPERMUTATION_CUBEFILTER;
5702         if (diffusescale > 0)
5703                 permutation |= SHADERPERMUTATION_DIFFUSE;
5704         if (specularscale > 0)
5705                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
5706         if (r_shadow_usingshadowmap2d)
5707         {
5708                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
5709                 if (r_shadow_shadowmapvsdct)
5710                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
5711
5712                 if (r_shadow_shadowmapsampler)
5713                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
5714                 if (r_shadow_shadowmappcf > 1)
5715                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
5716                 else if (r_shadow_shadowmappcf)
5717                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
5718         }
5719         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
5720         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
5721         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
5722         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
5723         switch(vid.renderpath)
5724         {
5725         case RENDERPATH_D3D9:
5726 #ifdef SUPPORTD3D
5727                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5728                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5729                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
5730                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5731                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5732                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5733                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5734                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
5735                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
5736                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5737                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5738
5739                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5740                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
5741                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5742                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5743                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
5744                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5745 #endif
5746                 break;
5747         case RENDERPATH_D3D10:
5748                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5749                 break;
5750         case RENDERPATH_D3D11:
5751                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5752                 break;
5753         case RENDERPATH_GL20:
5754         case RENDERPATH_GLES2:
5755                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5756                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5757                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
5758                 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);
5759                 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);
5760                 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);
5761                 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]);
5762                 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]);
5763                 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));
5764                 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]);
5765                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
5766
5767                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
5768                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
5769                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
5770                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
5771                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
5772                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
5773                 break;
5774         case RENDERPATH_GL13:
5775         case RENDERPATH_GL11:
5776                 break;
5777         case RENDERPATH_SOFT:
5778                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5779                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
5780                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
5781                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
5782                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
5783                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
5784                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
5785                 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]);
5786                 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));
5787                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5788                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5789
5790                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
5791                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5792                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
5793                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
5794                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
5795                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
5796                 break;
5797         }
5798 }
5799
5800 void R_SetupShader_DeferredBounceLight(void)
5801 {
5802         // array of particle lights that contribute only ambient color
5803         unsigned int permutation = 0;
5804         unsigned int mode = 0;
5805         mode = SHADERMODE_DEFERREDBOUNCELIGHT;
5806         switch(vid.renderpath)
5807         {
5808         case RENDERPATH_D3D9:
5809 #ifdef SUPPORTD3D
5810                 R_SetupShader_SetPermutationHLSL(mode, permutation);
5811                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5812                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
5813
5814                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
5815 #endif
5816                 break;
5817         case RENDERPATH_D3D10:
5818                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5819                 break;
5820         case RENDERPATH_D3D11:
5821                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
5822                 break;
5823         case RENDERPATH_GL20:
5824         case RENDERPATH_GLES2:
5825                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5826                 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]);
5827                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
5828
5829                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
5830                 break;
5831         case RENDERPATH_GL13:
5832         case RENDERPATH_GL11:
5833                 break;
5834         case RENDERPATH_SOFT:
5835                 R_SetupShader_SetPermutationGLSL(mode, permutation);
5836                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
5837                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
5838
5839                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
5840                 break;
5841         }
5842 }
5843
5844 #define SKINFRAME_HASH 1024
5845
5846 typedef struct
5847 {
5848         int loadsequence; // incremented each level change
5849         memexpandablearray_t array;
5850         skinframe_t *hash[SKINFRAME_HASH];
5851 }
5852 r_skinframe_t;
5853 r_skinframe_t r_skinframe;
5854
5855 void R_SkinFrame_PrepareForPurge(void)
5856 {
5857         r_skinframe.loadsequence++;
5858         // wrap it without hitting zero
5859         if (r_skinframe.loadsequence >= 200)
5860                 r_skinframe.loadsequence = 1;
5861 }
5862
5863 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
5864 {
5865         if (!skinframe)
5866                 return;
5867         // mark the skinframe as used for the purging code
5868         skinframe->loadsequence = r_skinframe.loadsequence;
5869 }
5870
5871 void R_SkinFrame_Purge(void)
5872 {
5873         int i;
5874         skinframe_t *s;
5875         for (i = 0;i < SKINFRAME_HASH;i++)
5876         {
5877                 for (s = r_skinframe.hash[i];s;s = s->next)
5878                 {
5879                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
5880                         {
5881                                 if (s->merged == s->base)
5882                                         s->merged = NULL;
5883                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
5884                                 R_PurgeTexture(s->stain );s->stain  = NULL;
5885                                 R_PurgeTexture(s->merged);s->merged = NULL;
5886                                 R_PurgeTexture(s->base  );s->base   = NULL;
5887                                 R_PurgeTexture(s->pants );s->pants  = NULL;
5888                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
5889                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
5890                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
5891                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
5892                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
5893                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
5894                                 s->loadsequence = 0;
5895                         }
5896                 }
5897         }
5898 }
5899
5900 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
5901         skinframe_t *item;
5902         char basename[MAX_QPATH];
5903
5904         Image_StripImageExtension(name, basename, sizeof(basename));
5905
5906         if( last == NULL ) {
5907                 int hashindex;
5908                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5909                 item = r_skinframe.hash[hashindex];
5910         } else {
5911                 item = last->next;
5912         }
5913
5914         // linearly search through the hash bucket
5915         for( ; item ; item = item->next ) {
5916                 if( !strcmp( item->basename, basename ) ) {
5917                         return item;
5918                 }
5919         }
5920         return NULL;
5921 }
5922
5923 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
5924 {
5925         skinframe_t *item;
5926         int hashindex;
5927         char basename[MAX_QPATH];
5928
5929         Image_StripImageExtension(name, basename, sizeof(basename));
5930
5931         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
5932         for (item = r_skinframe.hash[hashindex];item;item = item->next)
5933                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
5934                         break;
5935
5936         if (!item) {
5937                 rtexture_t *dyntexture;
5938                 // check whether its a dynamic texture
5939                 dyntexture = CL_GetDynTexture( basename );
5940                 if (!add && !dyntexture)
5941                         return NULL;
5942                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
5943                 memset(item, 0, sizeof(*item));
5944                 strlcpy(item->basename, basename, sizeof(item->basename));
5945                 item->base = dyntexture; // either NULL or dyntexture handle
5946                 item->textureflags = textureflags;
5947                 item->comparewidth = comparewidth;
5948                 item->compareheight = compareheight;
5949                 item->comparecrc = comparecrc;
5950                 item->next = r_skinframe.hash[hashindex];
5951                 r_skinframe.hash[hashindex] = item;
5952         }
5953         else if( item->base == NULL )
5954         {
5955                 rtexture_t *dyntexture;
5956                 // check whether its a dynamic texture
5957                 // 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]
5958                 dyntexture = CL_GetDynTexture( basename );
5959                 item->base = dyntexture; // either NULL or dyntexture handle
5960         }
5961
5962         R_SkinFrame_MarkUsed(item);
5963         return item;
5964 }
5965
5966 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
5967         { \
5968                 unsigned long long avgcolor[5], wsum; \
5969                 int pix, comp, w; \
5970                 avgcolor[0] = 0; \
5971                 avgcolor[1] = 0; \
5972                 avgcolor[2] = 0; \
5973                 avgcolor[3] = 0; \
5974                 avgcolor[4] = 0; \
5975                 wsum = 0; \
5976                 for(pix = 0; pix < cnt; ++pix) \
5977                 { \
5978                         w = 0; \
5979                         for(comp = 0; comp < 3; ++comp) \
5980                                 w += getpixel; \
5981                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
5982                         { \
5983                                 ++wsum; \
5984                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5985                                 w = getpixel; \
5986                                 for(comp = 0; comp < 3; ++comp) \
5987                                         avgcolor[comp] += getpixel * w; \
5988                                 avgcolor[3] += w; \
5989                         } \
5990                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
5991                         avgcolor[4] += getpixel; \
5992                 } \
5993                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
5994                         avgcolor[3] = 1; \
5995                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
5996                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
5997                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
5998                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
5999         }
6000
6001 extern cvar_t gl_picmip;
6002 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
6003 {
6004         int j;
6005         unsigned char *pixels;
6006         unsigned char *bumppixels;
6007         unsigned char *basepixels = NULL;
6008         int basepixels_width = 0;
6009         int basepixels_height = 0;
6010         skinframe_t *skinframe;
6011         rtexture_t *ddsbase = NULL;
6012         qboolean ddshasalpha = false;
6013         float ddsavgcolor[4];
6014         char basename[MAX_QPATH];
6015         int miplevel = R_PicmipForFlags(textureflags);
6016         int savemiplevel = miplevel;
6017         int mymiplevel;
6018
6019         if (cls.state == ca_dedicated)
6020                 return NULL;
6021
6022         // return an existing skinframe if already loaded
6023         // if loading of the first image fails, don't make a new skinframe as it
6024         // would cause all future lookups of this to be missing
6025         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
6026         if (skinframe && skinframe->base)
6027                 return skinframe;
6028
6029         Image_StripImageExtension(name, basename, sizeof(basename));
6030
6031         // check for DDS texture file first
6032         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
6033         {
6034                 basepixels = loadimagepixelsbgra(name, complain, true, r_texture_convertsRGB_skin.integer != 0, &miplevel);
6035                 if (basepixels == NULL)
6036                         return NULL;
6037         }
6038
6039         // FIXME handle miplevel
6040
6041         if (developer_loading.integer)
6042                 Con_Printf("loading skin \"%s\"\n", name);
6043
6044         // we've got some pixels to store, so really allocate this new texture now
6045         if (!skinframe)
6046                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
6047         skinframe->stain = NULL;
6048         skinframe->merged = NULL;
6049         skinframe->base = NULL;
6050         skinframe->pants = NULL;
6051         skinframe->shirt = NULL;
6052         skinframe->nmap = NULL;
6053         skinframe->gloss = NULL;
6054         skinframe->glow = NULL;
6055         skinframe->fog = NULL;
6056         skinframe->reflect = NULL;
6057         skinframe->hasalpha = false;
6058
6059         if (ddsbase)
6060         {
6061                 skinframe->base = ddsbase;
6062                 skinframe->hasalpha = ddshasalpha;
6063                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
6064                 if (r_loadfog && skinframe->hasalpha)
6065                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
6066                 //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]);
6067         }
6068         else
6069         {
6070                 basepixels_width = image_width;
6071                 basepixels_height = image_height;
6072                 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);
6073                 if (textureflags & TEXF_ALPHA)
6074                 {
6075                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
6076                         {
6077                                 if (basepixels[j] < 255)
6078                                 {
6079                                         skinframe->hasalpha = true;
6080                                         break;
6081                                 }
6082                         }
6083                         if (r_loadfog && skinframe->hasalpha)
6084                         {
6085                                 // has transparent pixels
6086                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6087                                 for (j = 0;j < image_width * image_height * 4;j += 4)
6088                                 {
6089                                         pixels[j+0] = 255;
6090                                         pixels[j+1] = 255;
6091                                         pixels[j+2] = 255;
6092                                         pixels[j+3] = basepixels[j+3];
6093                                 }
6094                                 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);
6095                                 Mem_Free(pixels);
6096                         }
6097                 }
6098                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
6099                 //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]);
6100                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
6101                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), true, skinframe->hasalpha);
6102                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
6103                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), true, true);
6104         }
6105
6106         if (r_loaddds)
6107         {
6108                 mymiplevel = savemiplevel;
6109                 if (r_loadnormalmap)
6110                         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);
6111                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6112                 if (r_loadgloss)
6113                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6114                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6115                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6116                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
6117         }
6118
6119         // _norm is the name used by tenebrae and has been adopted as standard
6120         if (r_loadnormalmap && skinframe->nmap == NULL)
6121         {
6122                 mymiplevel = savemiplevel;
6123                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6124                 {
6125                         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);
6126                         Mem_Free(pixels);
6127                         pixels = NULL;
6128                 }
6129                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
6130                 {
6131                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
6132                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
6133                         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);
6134                         Mem_Free(pixels);
6135                         Mem_Free(bumppixels);
6136                 }
6137                 else if (r_shadow_bumpscale_basetexture.value > 0)
6138                 {
6139                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
6140                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
6141                         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);
6142                         Mem_Free(pixels);
6143                 }
6144                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
6145                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), true, true);
6146         }
6147
6148         // _luma is supported only for tenebrae compatibility
6149         // _glow is the preferred name
6150         mymiplevel = savemiplevel;
6151         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))))
6152         {
6153                 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);
6154                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
6155                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), true, true);
6156                 Mem_Free(pixels);pixels = NULL;
6157         }
6158
6159         mymiplevel = savemiplevel;
6160         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6161         {
6162                 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);
6163                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
6164                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), true, true);
6165                 Mem_Free(pixels);
6166                 pixels = NULL;
6167         }
6168
6169         mymiplevel = savemiplevel;
6170         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6171         {
6172                 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);
6173                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
6174                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), true, false);
6175                 Mem_Free(pixels);
6176                 pixels = NULL;
6177         }
6178
6179         mymiplevel = savemiplevel;
6180         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6181         {
6182                 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);
6183                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
6184                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), true, false);
6185                 Mem_Free(pixels);
6186                 pixels = NULL;
6187         }
6188
6189         mymiplevel = savemiplevel;
6190         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, r_texture_convertsRGB_skin.integer != 0, &mymiplevel)))
6191         {
6192                 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);
6193                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
6194                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), true, true);
6195                 Mem_Free(pixels);
6196                 pixels = NULL;
6197         }
6198
6199         if (basepixels)
6200                 Mem_Free(basepixels);
6201
6202         return skinframe;
6203 }
6204
6205 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
6206 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height)
6207 {
6208         int i;
6209         unsigned char *temp1, *temp2;
6210         skinframe_t *skinframe;
6211
6212         if (cls.state == ca_dedicated)
6213                 return NULL;
6214
6215         // if already loaded just return it, otherwise make a new skinframe
6216         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
6217         if (skinframe && skinframe->base)
6218                 return skinframe;
6219
6220         skinframe->stain = NULL;
6221         skinframe->merged = NULL;
6222         skinframe->base = NULL;
6223         skinframe->pants = NULL;
6224         skinframe->shirt = NULL;
6225         skinframe->nmap = NULL;
6226         skinframe->gloss = NULL;
6227         skinframe->glow = NULL;
6228         skinframe->fog = NULL;
6229         skinframe->reflect = NULL;
6230         skinframe->hasalpha = false;
6231
6232         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6233         if (!skindata)
6234                 return NULL;
6235
6236         if (developer_loading.integer)
6237                 Con_Printf("loading 32bit skin \"%s\"\n", name);
6238
6239         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
6240         {
6241                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6242                 temp2 = temp1 + width * height * 4;
6243                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6244                 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);
6245                 Mem_Free(temp1);
6246         }
6247         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_BGRA, textureflags, -1, NULL);
6248         if (textureflags & TEXF_ALPHA)
6249         {
6250                 for (i = 3;i < width * height * 4;i += 4)
6251                 {
6252                         if (skindata[i] < 255)
6253                         {
6254                                 skinframe->hasalpha = true;
6255                                 break;
6256                         }
6257                 }
6258                 if (r_loadfog && skinframe->hasalpha)
6259                 {
6260                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
6261                         memcpy(fogpixels, skindata, width * height * 4);
6262                         for (i = 0;i < width * height * 4;i += 4)
6263                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
6264                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
6265                         Mem_Free(fogpixels);
6266                 }
6267         }
6268
6269         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
6270         //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]);
6271
6272         return skinframe;
6273 }
6274
6275 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
6276 {
6277         int i;
6278         int featuresmask;
6279         skinframe_t *skinframe;
6280
6281         if (cls.state == ca_dedicated)
6282                 return NULL;
6283
6284         // if already loaded just return it, otherwise make a new skinframe
6285         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6286         if (skinframe && skinframe->base)
6287                 return skinframe;
6288
6289         skinframe->stain = NULL;
6290         skinframe->merged = NULL;
6291         skinframe->base = NULL;
6292         skinframe->pants = NULL;
6293         skinframe->shirt = NULL;
6294         skinframe->nmap = NULL;
6295         skinframe->gloss = NULL;
6296         skinframe->glow = NULL;
6297         skinframe->fog = NULL;
6298         skinframe->reflect = NULL;
6299         skinframe->hasalpha = false;
6300
6301         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6302         if (!skindata)
6303                 return NULL;
6304
6305         if (developer_loading.integer)
6306                 Con_Printf("loading quake skin \"%s\"\n", name);
6307
6308         // 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)
6309         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
6310         memcpy(skinframe->qpixels, skindata, width*height);
6311         skinframe->qwidth = width;
6312         skinframe->qheight = height;
6313
6314         featuresmask = 0;
6315         for (i = 0;i < width * height;i++)
6316                 featuresmask |= palette_featureflags[skindata[i]];
6317
6318         skinframe->hasalpha = false;
6319         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
6320         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
6321         skinframe->qgeneratemerged = true;
6322         skinframe->qgeneratebase = skinframe->qhascolormapping;
6323         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
6324
6325         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
6326         //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]);
6327
6328         return skinframe;
6329 }
6330
6331 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
6332 {
6333         int width;
6334         int height;
6335         unsigned char *skindata;
6336
6337         if (!skinframe->qpixels)
6338                 return;
6339
6340         if (!skinframe->qhascolormapping)
6341                 colormapped = false;
6342
6343         if (colormapped)
6344         {
6345                 if (!skinframe->qgeneratebase)
6346                         return;
6347         }
6348         else
6349         {
6350                 if (!skinframe->qgeneratemerged)
6351                         return;
6352         }
6353
6354         width = skinframe->qwidth;
6355         height = skinframe->qheight;
6356         skindata = skinframe->qpixels;
6357
6358         if (skinframe->qgeneratenmap)
6359         {
6360                 unsigned char *temp1, *temp2;
6361                 skinframe->qgeneratenmap = false;
6362                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
6363                 temp2 = temp1 + width * height * 4;
6364                 // use either a custom palette or the quake palette
6365                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
6366                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
6367                 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);
6368                 Mem_Free(temp1);
6369         }
6370
6371         if (skinframe->qgenerateglow)
6372         {
6373                 skinframe->qgenerateglow = false;
6374                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
6375         }
6376
6377         if (colormapped)
6378         {
6379                 skinframe->qgeneratebase = false;
6380                 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);
6381                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
6382                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
6383         }
6384         else
6385         {
6386                 skinframe->qgeneratemerged = false;
6387                 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);
6388         }
6389
6390         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
6391         {
6392                 Mem_Free(skinframe->qpixels);
6393                 skinframe->qpixels = NULL;
6394         }
6395 }
6396
6397 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)
6398 {
6399         int i;
6400         skinframe_t *skinframe;
6401
6402         if (cls.state == ca_dedicated)
6403                 return NULL;
6404
6405         // if already loaded just return it, otherwise make a new skinframe
6406         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
6407         if (skinframe && skinframe->base)
6408                 return skinframe;
6409
6410         skinframe->stain = NULL;
6411         skinframe->merged = NULL;
6412         skinframe->base = NULL;
6413         skinframe->pants = NULL;
6414         skinframe->shirt = NULL;
6415         skinframe->nmap = NULL;
6416         skinframe->gloss = NULL;
6417         skinframe->glow = NULL;
6418         skinframe->fog = NULL;
6419         skinframe->reflect = NULL;
6420         skinframe->hasalpha = false;
6421
6422         // if no data was provided, then clearly the caller wanted to get a blank skinframe
6423         if (!skindata)
6424                 return NULL;
6425
6426         if (developer_loading.integer)
6427                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
6428
6429         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
6430         if (textureflags & TEXF_ALPHA)
6431         {
6432                 for (i = 0;i < width * height;i++)
6433                 {
6434                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
6435                         {
6436                                 skinframe->hasalpha = true;
6437                                 break;
6438                         }
6439                 }
6440                 if (r_loadfog && skinframe->hasalpha)
6441                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
6442         }
6443
6444         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
6445         //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]);
6446
6447         return skinframe;
6448 }
6449
6450 skinframe_t *R_SkinFrame_LoadMissing(void)
6451 {
6452         skinframe_t *skinframe;
6453
6454         if (cls.state == ca_dedicated)
6455                 return NULL;
6456
6457         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
6458         skinframe->stain = NULL;
6459         skinframe->merged = NULL;
6460         skinframe->base = NULL;
6461         skinframe->pants = NULL;
6462         skinframe->shirt = NULL;
6463         skinframe->nmap = NULL;
6464         skinframe->gloss = NULL;
6465         skinframe->glow = NULL;
6466         skinframe->fog = NULL;
6467         skinframe->reflect = NULL;
6468         skinframe->hasalpha = false;
6469
6470         skinframe->avgcolor[0] = rand() / RAND_MAX;
6471         skinframe->avgcolor[1] = rand() / RAND_MAX;
6472         skinframe->avgcolor[2] = rand() / RAND_MAX;
6473         skinframe->avgcolor[3] = 1;
6474
6475         return skinframe;
6476 }
6477
6478 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
6479 typedef struct suffixinfo_s
6480 {
6481         const char *suffix;
6482         qboolean flipx, flipy, flipdiagonal;
6483 }
6484 suffixinfo_t;
6485 static suffixinfo_t suffix[3][6] =
6486 {
6487         {
6488                 {"px",   false, false, false},
6489                 {"nx",   false, false, false},
6490                 {"py",   false, false, false},
6491                 {"ny",   false, false, false},
6492                 {"pz",   false, false, false},
6493                 {"nz",   false, false, false}
6494         },
6495         {
6496                 {"posx", false, false, false},
6497                 {"negx", false, false, false},
6498                 {"posy", false, false, false},
6499                 {"negy", false, false, false},
6500                 {"posz", false, false, false},
6501                 {"negz", false, false, false}
6502         },
6503         {
6504                 {"rt",    true, false,  true},
6505                 {"lf",   false,  true,  true},
6506                 {"ft",    true,  true, false},
6507                 {"bk",   false, false, false},
6508                 {"up",    true, false,  true},
6509                 {"dn",    true, false,  true}
6510         }
6511 };
6512
6513 static int componentorder[4] = {0, 1, 2, 3};
6514
6515 rtexture_t *R_LoadCubemap(const char *basename)
6516 {
6517         int i, j, cubemapsize;
6518         unsigned char *cubemappixels, *image_buffer;
6519         rtexture_t *cubemaptexture;
6520         char name[256];
6521         // must start 0 so the first loadimagepixels has no requested width/height
6522         cubemapsize = 0;
6523         cubemappixels = NULL;
6524         cubemaptexture = NULL;
6525         // keep trying different suffix groups (posx, px, rt) until one loads
6526         for (j = 0;j < 3 && !cubemappixels;j++)
6527         {
6528                 // load the 6 images in the suffix group
6529                 for (i = 0;i < 6;i++)
6530                 {
6531                         // generate an image name based on the base and and suffix
6532                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
6533                         // load it
6534                         if ((image_buffer = loadimagepixelsbgra(name, false, false, r_texture_convertsRGB_cubemap.integer != 0, NULL)))
6535                         {
6536                                 // an image loaded, make sure width and height are equal
6537                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
6538                                 {
6539                                         // if this is the first image to load successfully, allocate the cubemap memory
6540                                         if (!cubemappixels && image_width >= 1)
6541                                         {
6542                                                 cubemapsize = image_width;
6543                                                 // note this clears to black, so unavailable sides are black
6544                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
6545                                         }
6546                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
6547                                         if (cubemappixels)
6548                                                 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);
6549                                 }
6550                                 else
6551                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
6552                                 // free the image
6553                                 Mem_Free(image_buffer);
6554                         }
6555                 }
6556         }
6557         // if a cubemap loaded, upload it
6558         if (cubemappixels)
6559         {
6560                 if (developer_loading.integer)
6561                         Con_Printf("loading cubemap \"%s\"\n", basename);
6562
6563                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6564                 Mem_Free(cubemappixels);
6565         }
6566         else
6567         {
6568                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
6569                 if (developer_loading.integer)
6570                 {
6571                         Con_Printf("(tried tried images ");
6572                         for (j = 0;j < 3;j++)
6573                                 for (i = 0;i < 6;i++)
6574                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
6575                         Con_Print(" and was unable to find any of them).\n");
6576                 }
6577         }
6578         return cubemaptexture;
6579 }
6580
6581 rtexture_t *R_GetCubemap(const char *basename)
6582 {
6583         int i;
6584         for (i = 0;i < r_texture_numcubemaps;i++)
6585                 if (!strcasecmp(r_texture_cubemaps[i].basename, basename))
6586                         return r_texture_cubemaps[i].texture ? r_texture_cubemaps[i].texture : r_texture_whitecube;
6587         if (i >= MAX_CUBEMAPS)
6588                 return r_texture_whitecube;
6589         r_texture_numcubemaps++;
6590         strlcpy(r_texture_cubemaps[i].basename, basename, sizeof(r_texture_cubemaps[i].basename));
6591         r_texture_cubemaps[i].texture = R_LoadCubemap(r_texture_cubemaps[i].basename);
6592         return r_texture_cubemaps[i].texture;
6593 }
6594
6595 void R_FreeCubemaps(void)
6596 {
6597         int i;
6598         for (i = 0;i < r_texture_numcubemaps;i++)
6599         {
6600                 if (developer_loading.integer)
6601                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i].basename);
6602                 if (r_texture_cubemaps[i].texture)
6603                         R_FreeTexture(r_texture_cubemaps[i].texture);
6604         }
6605         r_texture_numcubemaps = 0;
6606 }
6607
6608 void R_Main_FreeViewCache(void)
6609 {
6610         if (r_refdef.viewcache.entityvisible)
6611                 Mem_Free(r_refdef.viewcache.entityvisible);
6612         if (r_refdef.viewcache.world_pvsbits)
6613                 Mem_Free(r_refdef.viewcache.world_pvsbits);
6614         if (r_refdef.viewcache.world_leafvisible)
6615                 Mem_Free(r_refdef.viewcache.world_leafvisible);
6616         if (r_refdef.viewcache.world_surfacevisible)
6617                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
6618         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
6619 }
6620
6621 void R_Main_ResizeViewCache(void)
6622 {
6623         int numentities = r_refdef.scene.numentities;
6624         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
6625         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
6626         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
6627         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
6628         if (r_refdef.viewcache.maxentities < numentities)
6629         {
6630                 r_refdef.viewcache.maxentities = numentities;
6631                 if (r_refdef.viewcache.entityvisible)
6632                         Mem_Free(r_refdef.viewcache.entityvisible);
6633                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
6634         }
6635         if (r_refdef.viewcache.world_numclusters != numclusters)
6636         {
6637                 r_refdef.viewcache.world_numclusters = numclusters;
6638                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
6639                 if (r_refdef.viewcache.world_pvsbits)
6640                         Mem_Free(r_refdef.viewcache.world_pvsbits);
6641                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
6642         }
6643         if (r_refdef.viewcache.world_numleafs != numleafs)
6644         {
6645                 r_refdef.viewcache.world_numleafs = numleafs;
6646                 if (r_refdef.viewcache.world_leafvisible)
6647                         Mem_Free(r_refdef.viewcache.world_leafvisible);
6648                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
6649         }
6650         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
6651         {
6652                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
6653                 if (r_refdef.viewcache.world_surfacevisible)
6654                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
6655                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
6656         }
6657 }
6658
6659 extern rtexture_t *loadingscreentexture;
6660 void gl_main_start(void)
6661 {
6662         loadingscreentexture = NULL;
6663         r_texture_blanknormalmap = NULL;
6664         r_texture_white = NULL;
6665         r_texture_grey128 = NULL;
6666         r_texture_black = NULL;
6667         r_texture_whitecube = NULL;
6668         r_texture_normalizationcube = NULL;
6669         r_texture_fogattenuation = NULL;
6670         r_texture_fogheighttexture = NULL;
6671         r_texture_gammaramps = NULL;
6672         r_texture_numcubemaps = 0;
6673
6674         r_loaddds = r_texture_dds_load.integer != 0;
6675         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
6676
6677         switch(vid.renderpath)
6678         {
6679         case RENDERPATH_GL20:
6680         case RENDERPATH_D3D9:
6681         case RENDERPATH_D3D10:
6682         case RENDERPATH_D3D11:
6683         case RENDERPATH_SOFT:
6684                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6685                 Cvar_SetValueQuick(&gl_combine, 1);
6686                 Cvar_SetValueQuick(&r_glsl, 1);
6687                 r_loadnormalmap = true;
6688                 r_loadgloss = true;
6689                 r_loadfog = false;
6690                 break;
6691         case RENDERPATH_GL13:
6692                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6693                 Cvar_SetValueQuick(&gl_combine, 1);
6694                 Cvar_SetValueQuick(&r_glsl, 0);
6695                 r_loadnormalmap = false;
6696                 r_loadgloss = false;
6697                 r_loadfog = true;
6698                 break;
6699         case RENDERPATH_GL11:
6700                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
6701                 Cvar_SetValueQuick(&gl_combine, 0);
6702                 Cvar_SetValueQuick(&r_glsl, 0);
6703                 r_loadnormalmap = false;
6704                 r_loadgloss = false;
6705                 r_loadfog = true;
6706                 break;
6707         case RENDERPATH_GLES2:
6708                 Cvar_SetValueQuick(&r_textureunits, 1);
6709                 Cvar_SetValueQuick(&gl_combine, 1);
6710                 Cvar_SetValueQuick(&r_glsl, 1);
6711                 r_loadnormalmap = true;
6712                 r_loadgloss = false;
6713                 r_loadfog = false;
6714                 break;
6715         }
6716
6717         R_AnimCache_Free();
6718         R_FrameData_Reset();
6719
6720         r_numqueries = 0;
6721         r_maxqueries = 0;
6722         memset(r_queries, 0, sizeof(r_queries));
6723
6724         r_qwskincache = NULL;
6725         r_qwskincache_size = 0;
6726
6727         // set up r_skinframe loading system for textures
6728         memset(&r_skinframe, 0, sizeof(r_skinframe));
6729         r_skinframe.loadsequence = 1;
6730         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
6731
6732         r_main_texturepool = R_AllocTexturePool();
6733         R_BuildBlankTextures();
6734         R_BuildNoTexture();
6735         if (vid.support.arb_texture_cube_map)
6736         {
6737                 R_BuildWhiteCube();
6738                 R_BuildNormalizationCube();
6739         }
6740         r_texture_fogattenuation = NULL;
6741         r_texture_fogheighttexture = NULL;
6742         r_texture_gammaramps = NULL;
6743         //r_texture_fogintensity = NULL;
6744         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6745         memset(&r_waterstate, 0, sizeof(r_waterstate));
6746         r_glsl_permutation = NULL;
6747         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6748         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
6749         glslshaderstring = NULL;
6750 #ifdef SUPPORTD3D
6751         r_hlsl_permutation = NULL;
6752         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6753         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
6754 #endif
6755         hlslshaderstring = NULL;
6756         memset(&r_svbsp, 0, sizeof (r_svbsp));
6757
6758         r_refdef.fogmasktable_density = 0;
6759 }
6760
6761 void gl_main_shutdown(void)
6762 {
6763         R_AnimCache_Free();
6764         R_FrameData_Reset();
6765
6766         R_Main_FreeViewCache();
6767
6768         switch(vid.renderpath)
6769         {
6770         case RENDERPATH_GL11:
6771         case RENDERPATH_GL13:
6772         case RENDERPATH_GL20:
6773         case RENDERPATH_GLES2:
6774                 if (r_maxqueries)
6775                         qglDeleteQueriesARB(r_maxqueries, r_queries);
6776                 break;
6777         case RENDERPATH_D3D9:
6778                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6779                 break;
6780         case RENDERPATH_D3D10:
6781                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6782                 break;
6783         case RENDERPATH_D3D11:
6784                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6785                 break;
6786         case RENDERPATH_SOFT:
6787                 break;
6788         }
6789
6790         r_numqueries = 0;
6791         r_maxqueries = 0;
6792         memset(r_queries, 0, sizeof(r_queries));
6793
6794         r_qwskincache = NULL;
6795         r_qwskincache_size = 0;
6796
6797         // clear out the r_skinframe state
6798         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
6799         memset(&r_skinframe, 0, sizeof(r_skinframe));
6800
6801         if (r_svbsp.nodes)
6802                 Mem_Free(r_svbsp.nodes);
6803         memset(&r_svbsp, 0, sizeof (r_svbsp));
6804         R_FreeTexturePool(&r_main_texturepool);
6805         loadingscreentexture = NULL;
6806         r_texture_blanknormalmap = NULL;
6807         r_texture_white = NULL;
6808         r_texture_grey128 = NULL;
6809         r_texture_black = NULL;
6810         r_texture_whitecube = NULL;
6811         r_texture_normalizationcube = NULL;
6812         r_texture_fogattenuation = NULL;
6813         r_texture_fogheighttexture = NULL;
6814         r_texture_gammaramps = NULL;
6815         r_texture_numcubemaps = 0;
6816         //r_texture_fogintensity = NULL;
6817         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
6818         memset(&r_waterstate, 0, sizeof(r_waterstate));
6819         R_GLSL_Restart_f();
6820
6821         r_glsl_permutation = NULL;
6822         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
6823         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
6824         glslshaderstring = NULL;
6825 #ifdef SUPPORTD3D
6826         r_hlsl_permutation = NULL;
6827         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
6828         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
6829 #endif
6830         hlslshaderstring = NULL;
6831 }
6832
6833 extern void CL_ParseEntityLump(char *entitystring);
6834 void gl_main_newmap(void)
6835 {
6836         // FIXME: move this code to client
6837         char *entities, entname[MAX_QPATH];
6838         if (r_qwskincache)
6839                 Mem_Free(r_qwskincache);
6840         r_qwskincache = NULL;
6841         r_qwskincache_size = 0;
6842         if (cl.worldmodel)
6843         {
6844                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
6845                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
6846                 {
6847                         CL_ParseEntityLump(entities);
6848                         Mem_Free(entities);
6849                         return;
6850                 }
6851                 if (cl.worldmodel->brush.entities)
6852                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
6853         }
6854         R_Main_FreeViewCache();
6855
6856         R_FrameData_Reset();
6857 }
6858
6859 void GL_Main_Init(void)
6860 {
6861         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
6862
6863         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
6864         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
6865         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
6866         if (gamemode == GAME_NEHAHRA)
6867         {
6868                 Cvar_RegisterVariable (&gl_fogenable);
6869                 Cvar_RegisterVariable (&gl_fogdensity);
6870                 Cvar_RegisterVariable (&gl_fogred);
6871                 Cvar_RegisterVariable (&gl_foggreen);
6872                 Cvar_RegisterVariable (&gl_fogblue);
6873                 Cvar_RegisterVariable (&gl_fogstart);
6874                 Cvar_RegisterVariable (&gl_fogend);
6875                 Cvar_RegisterVariable (&gl_skyclip);
6876         }
6877         Cvar_RegisterVariable(&r_motionblur);
6878         Cvar_RegisterVariable(&r_motionblur_maxblur);
6879         Cvar_RegisterVariable(&r_motionblur_bmin);
6880         Cvar_RegisterVariable(&r_motionblur_vmin);
6881         Cvar_RegisterVariable(&r_motionblur_vmax);
6882         Cvar_RegisterVariable(&r_motionblur_vcoeff);
6883         Cvar_RegisterVariable(&r_motionblur_randomize);
6884         Cvar_RegisterVariable(&r_damageblur);
6885         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
6886         Cvar_RegisterVariable(&r_equalize_entities_minambient);
6887         Cvar_RegisterVariable(&r_equalize_entities_by);
6888         Cvar_RegisterVariable(&r_equalize_entities_to);
6889         Cvar_RegisterVariable(&r_depthfirst);
6890         Cvar_RegisterVariable(&r_useinfinitefarclip);
6891         Cvar_RegisterVariable(&r_farclip_base);
6892         Cvar_RegisterVariable(&r_farclip_world);
6893         Cvar_RegisterVariable(&r_nearclip);
6894         Cvar_RegisterVariable(&r_showbboxes);
6895         Cvar_RegisterVariable(&r_showsurfaces);
6896         Cvar_RegisterVariable(&r_showtris);
6897         Cvar_RegisterVariable(&r_shownormals);
6898         Cvar_RegisterVariable(&r_showlighting);
6899         Cvar_RegisterVariable(&r_showshadowvolumes);
6900         Cvar_RegisterVariable(&r_showcollisionbrushes);
6901         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
6902         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
6903         Cvar_RegisterVariable(&r_showdisabledepthtest);
6904         Cvar_RegisterVariable(&r_drawportals);
6905         Cvar_RegisterVariable(&r_drawentities);
6906         Cvar_RegisterVariable(&r_draw2d);
6907         Cvar_RegisterVariable(&r_drawworld);
6908         Cvar_RegisterVariable(&r_cullentities_trace);
6909         Cvar_RegisterVariable(&r_cullentities_trace_samples);
6910         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
6911         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
6912         Cvar_RegisterVariable(&r_cullentities_trace_delay);
6913         Cvar_RegisterVariable(&r_drawviewmodel);
6914         Cvar_RegisterVariable(&r_drawexteriormodel);
6915         Cvar_RegisterVariable(&r_speeds);
6916         Cvar_RegisterVariable(&r_fullbrights);
6917         Cvar_RegisterVariable(&r_wateralpha);
6918         Cvar_RegisterVariable(&r_dynamic);
6919         Cvar_RegisterVariable(&r_fakelight);
6920         Cvar_RegisterVariable(&r_fakelight_intensity);
6921         Cvar_RegisterVariable(&r_fullbright);
6922         Cvar_RegisterVariable(&r_shadows);
6923         Cvar_RegisterVariable(&r_shadows_darken);
6924         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
6925         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
6926         Cvar_RegisterVariable(&r_shadows_throwdistance);
6927         Cvar_RegisterVariable(&r_shadows_throwdirection);
6928         Cvar_RegisterVariable(&r_shadows_focus);
6929         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
6930         Cvar_RegisterVariable(&r_q1bsp_skymasking);
6931         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
6932         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
6933         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
6934         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
6935         Cvar_RegisterVariable(&r_fog_exp2);
6936         Cvar_RegisterVariable(&r_drawfog);
6937         Cvar_RegisterVariable(&r_transparentdepthmasking);
6938         Cvar_RegisterVariable(&r_texture_dds_load);
6939         Cvar_RegisterVariable(&r_texture_dds_save);
6940         Cvar_RegisterVariable(&r_texture_convertsRGB_2d);
6941         Cvar_RegisterVariable(&r_texture_convertsRGB_skin);
6942         Cvar_RegisterVariable(&r_texture_convertsRGB_cubemap);
6943         Cvar_RegisterVariable(&r_texture_convertsRGB_skybox);
6944         Cvar_RegisterVariable(&r_texture_convertsRGB_particles);
6945         Cvar_RegisterVariable(&r_textureunits);
6946         Cvar_RegisterVariable(&gl_combine);
6947         Cvar_RegisterVariable(&r_glsl);
6948         Cvar_RegisterVariable(&r_glsl_deluxemapping);
6949         Cvar_RegisterVariable(&r_glsl_offsetmapping);
6950         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
6951         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
6952         Cvar_RegisterVariable(&r_glsl_postprocess);
6953         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
6954         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
6955         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
6956         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
6957         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
6958         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
6959         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
6960         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
6961
6962         Cvar_RegisterVariable(&r_water);
6963         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
6964         Cvar_RegisterVariable(&r_water_clippingplanebias);
6965         Cvar_RegisterVariable(&r_water_refractdistort);
6966         Cvar_RegisterVariable(&r_water_reflectdistort);
6967         Cvar_RegisterVariable(&r_water_scissormode);
6968         Cvar_RegisterVariable(&r_lerpsprites);
6969         Cvar_RegisterVariable(&r_lerpmodels);
6970         Cvar_RegisterVariable(&r_lerplightstyles);
6971         Cvar_RegisterVariable(&r_waterscroll);
6972         Cvar_RegisterVariable(&r_bloom);
6973         Cvar_RegisterVariable(&r_bloom_colorscale);
6974         Cvar_RegisterVariable(&r_bloom_brighten);
6975         Cvar_RegisterVariable(&r_bloom_blur);
6976         Cvar_RegisterVariable(&r_bloom_resolution);
6977         Cvar_RegisterVariable(&r_bloom_colorexponent);
6978         Cvar_RegisterVariable(&r_bloom_colorsubtract);
6979         Cvar_RegisterVariable(&r_hdr);
6980         Cvar_RegisterVariable(&r_hdr_scenebrightness);
6981         Cvar_RegisterVariable(&r_hdr_glowintensity);
6982         Cvar_RegisterVariable(&r_hdr_range);
6983         Cvar_RegisterVariable(&r_hdr_irisadaptation);
6984         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
6985         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
6986         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
6987         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
6988         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
6989         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
6990         Cvar_RegisterVariable(&developer_texturelogging);
6991         Cvar_RegisterVariable(&gl_lightmaps);
6992         Cvar_RegisterVariable(&r_test);
6993         Cvar_RegisterVariable(&r_glsl_saturation);
6994         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
6995         Cvar_RegisterVariable(&r_framedatasize);
6996         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
6997                 Cvar_SetValue("r_fullbrights", 0);
6998         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
6999
7000         Cvar_RegisterVariable(&r_track_sprites);
7001         Cvar_RegisterVariable(&r_track_sprites_flags);
7002         Cvar_RegisterVariable(&r_track_sprites_scalew);
7003         Cvar_RegisterVariable(&r_track_sprites_scaleh);
7004         Cvar_RegisterVariable(&r_overheadsprites_perspective);
7005         Cvar_RegisterVariable(&r_overheadsprites_pushback);
7006         Cvar_RegisterVariable(&r_overheadsprites_scalex);
7007         Cvar_RegisterVariable(&r_overheadsprites_scaley);
7008 }
7009
7010 extern void R_Textures_Init(void);
7011 extern void GL_Draw_Init(void);
7012 extern void GL_Main_Init(void);
7013 extern void R_Shadow_Init(void);
7014 extern void R_Sky_Init(void);
7015 extern void GL_Surf_Init(void);
7016 extern void R_Particles_Init(void);
7017 extern void R_Explosion_Init(void);
7018 extern void gl_backend_init(void);
7019 extern void Sbar_Init(void);
7020 extern void R_LightningBeams_Init(void);
7021 extern void Mod_RenderInit(void);
7022 extern void Font_Init(void);
7023
7024 void Render_Init(void)
7025 {
7026         gl_backend_init();
7027         R_Textures_Init();
7028         GL_Main_Init();
7029         Font_Init();
7030         GL_Draw_Init();
7031         R_Shadow_Init();
7032         R_Sky_Init();
7033         GL_Surf_Init();
7034         Sbar_Init();
7035         R_Particles_Init();
7036         R_Explosion_Init();
7037         R_LightningBeams_Init();
7038         Mod_RenderInit();
7039 }
7040
7041 /*
7042 ===============
7043 GL_Init
7044 ===============
7045 */
7046 extern char *ENGINE_EXTENSIONS;
7047 void GL_Init (void)
7048 {
7049         gl_renderer = (const char *)qglGetString(GL_RENDERER);
7050         gl_vendor = (const char *)qglGetString(GL_VENDOR);
7051         gl_version = (const char *)qglGetString(GL_VERSION);
7052         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
7053
7054         if (!gl_extensions)
7055                 gl_extensions = "";
7056         if (!gl_platformextensions)
7057                 gl_platformextensions = "";
7058
7059         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
7060         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
7061         Con_Printf("GL_VERSION: %s\n", gl_version);
7062         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
7063         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
7064
7065         VID_CheckExtensions();
7066
7067         // LordHavoc: report supported extensions
7068         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
7069
7070         // clear to black (loading plaque will be seen over this)
7071         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
7072 }
7073
7074 int R_CullBox(const vec3_t mins, const vec3_t maxs)
7075 {
7076         int i;
7077         mplane_t *p;
7078         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7079         {
7080                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
7081                 if (i == 4)
7082                         continue;
7083                 p = r_refdef.view.frustum + i;
7084                 switch(p->signbits)
7085                 {
7086                 default:
7087                 case 0:
7088                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7089                                 return true;
7090                         break;
7091                 case 1:
7092                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7093                                 return true;
7094                         break;
7095                 case 2:
7096                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7097                                 return true;
7098                         break;
7099                 case 3:
7100                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7101                                 return true;
7102                         break;
7103                 case 4:
7104                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7105                                 return true;
7106                         break;
7107                 case 5:
7108                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7109                                 return true;
7110                         break;
7111                 case 6:
7112                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7113                                 return true;
7114                         break;
7115                 case 7:
7116                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7117                                 return true;
7118                         break;
7119                 }
7120         }
7121         return false;
7122 }
7123
7124 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
7125 {
7126         int i;
7127         const mplane_t *p;
7128         for (i = 0;i < numplanes;i++)
7129         {
7130                 p = planes + i;
7131                 switch(p->signbits)
7132                 {
7133                 default:
7134                 case 0:
7135                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7136                                 return true;
7137                         break;
7138                 case 1:
7139                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
7140                                 return true;
7141                         break;
7142                 case 2:
7143                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7144                                 return true;
7145                         break;
7146                 case 3:
7147                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
7148                                 return true;
7149                         break;
7150                 case 4:
7151                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7152                                 return true;
7153                         break;
7154                 case 5:
7155                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
7156                                 return true;
7157                         break;
7158                 case 6:
7159                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7160                                 return true;
7161                         break;
7162                 case 7:
7163                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
7164                                 return true;
7165                         break;
7166                 }
7167         }
7168         return false;
7169 }
7170
7171 //==================================================================================
7172
7173 // LordHavoc: this stores temporary data used within the same frame
7174
7175 typedef struct r_framedata_mem_s
7176 {
7177         struct r_framedata_mem_s *purge; // older mem block to free on next frame
7178         size_t size; // how much usable space
7179         size_t current; // how much space in use
7180         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
7181         size_t wantedsize; // how much space was allocated
7182         unsigned char *data; // start of real data (16byte aligned)
7183 }
7184 r_framedata_mem_t;
7185
7186 static r_framedata_mem_t *r_framedata_mem;
7187
7188 void R_FrameData_Reset(void)
7189 {
7190         while (r_framedata_mem)
7191         {
7192                 r_framedata_mem_t *next = r_framedata_mem->purge;
7193                 Mem_Free(r_framedata_mem);
7194                 r_framedata_mem = next;
7195         }
7196 }
7197
7198 void R_FrameData_Resize(void)
7199 {
7200         size_t wantedsize;
7201         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
7202         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
7203         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
7204         {
7205                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
7206                 newmem->wantedsize = wantedsize;
7207                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
7208                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
7209                 newmem->current = 0;
7210                 newmem->mark = 0;
7211                 newmem->purge = r_framedata_mem;
7212                 r_framedata_mem = newmem;
7213         }
7214 }
7215
7216 void R_FrameData_NewFrame(void)
7217 {
7218         R_FrameData_Resize();
7219         if (!r_framedata_mem)
7220                 return;
7221         // if we ran out of space on the last frame, free the old memory now
7222         while (r_framedata_mem->purge)
7223         {
7224                 // repeatedly remove the second item in the list, leaving only head
7225                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
7226                 Mem_Free(r_framedata_mem->purge);
7227                 r_framedata_mem->purge = next;
7228         }
7229         // reset the current mem pointer
7230         r_framedata_mem->current = 0;
7231         r_framedata_mem->mark = 0;
7232 }
7233
7234 void *R_FrameData_Alloc(size_t size)
7235 {
7236         void *data;
7237
7238         // align to 16 byte boundary - the data pointer is already aligned, so we
7239         // only need to ensure the size of every allocation is also aligned
7240         size = (size + 15) & ~15;
7241
7242         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
7243         {
7244                 // emergency - we ran out of space, allocate more memory
7245                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
7246                 R_FrameData_Resize();
7247         }
7248
7249         data = r_framedata_mem->data + r_framedata_mem->current;
7250         r_framedata_mem->current += size;
7251
7252         // count the usage for stats
7253         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
7254         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
7255
7256         return (void *)data;
7257 }
7258
7259 void *R_FrameData_Store(size_t size, void *data)
7260 {
7261         void *d = R_FrameData_Alloc(size);
7262         if (d && data)
7263                 memcpy(d, data, size);
7264         return d;
7265 }
7266
7267 void R_FrameData_SetMark(void)
7268 {
7269         if (!r_framedata_mem)
7270                 return;
7271         r_framedata_mem->mark = r_framedata_mem->current;
7272 }
7273
7274 void R_FrameData_ReturnToMark(void)
7275 {
7276         if (!r_framedata_mem)
7277                 return;
7278         r_framedata_mem->current = r_framedata_mem->mark;
7279 }
7280
7281 //==================================================================================
7282
7283 // LordHavoc: animcache originally written by Echon, rewritten since then
7284
7285 /**
7286  * Animation cache prevents re-generating mesh data for an animated model
7287  * multiple times in one frame for lighting, shadowing, reflections, etc.
7288  */
7289
7290 void R_AnimCache_Free(void)
7291 {
7292 }
7293
7294 void R_AnimCache_ClearCache(void)
7295 {
7296         int i;
7297         entity_render_t *ent;
7298
7299         for (i = 0;i < r_refdef.scene.numentities;i++)
7300         {
7301                 ent = r_refdef.scene.entities[i];
7302                 ent->animcache_vertex3f = NULL;
7303                 ent->animcache_normal3f = NULL;
7304                 ent->animcache_svector3f = NULL;
7305                 ent->animcache_tvector3f = NULL;
7306                 ent->animcache_vertexmesh = NULL;
7307                 ent->animcache_vertex3fbuffer = NULL;
7308                 ent->animcache_vertexmeshbuffer = NULL;
7309         }
7310 }
7311
7312 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
7313 {
7314         int i;
7315
7316         // check if we need the meshbuffers
7317         if (!vid.useinterleavedarrays)
7318                 return;
7319
7320         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
7321                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
7322         // TODO: upload vertex3f buffer?
7323         if (ent->animcache_vertexmesh)
7324         {
7325                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
7326                 for (i = 0;i < numvertices;i++)
7327                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
7328                 if (ent->animcache_svector3f)
7329                         for (i = 0;i < numvertices;i++)
7330                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
7331                 if (ent->animcache_tvector3f)
7332                         for (i = 0;i < numvertices;i++)
7333                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
7334                 if (ent->animcache_normal3f)
7335                         for (i = 0;i < numvertices;i++)
7336                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
7337                 // TODO: upload vertexmeshbuffer?
7338         }
7339 }
7340
7341 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
7342 {
7343         dp_model_t *model = ent->model;
7344         int numvertices;
7345         // see if it's already cached this frame
7346         if (ent->animcache_vertex3f)
7347         {
7348                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
7349                 if (wantnormals || wanttangents)
7350                 {
7351                         if (ent->animcache_normal3f)
7352                                 wantnormals = false;
7353                         if (ent->animcache_svector3f)
7354                                 wanttangents = false;
7355                         if (wantnormals || wanttangents)
7356                         {
7357                                 numvertices = model->surfmesh.num_vertices;
7358                                 if (wantnormals)
7359                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7360                                 if (wanttangents)
7361                                 {
7362                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7363                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7364                                 }
7365                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
7366                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7367                         }
7368                 }
7369         }
7370         else
7371         {
7372                 // see if this ent is worth caching
7373                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices || (ent->frameblend[0].lerp == 1 && ent->frameblend[0].subframe == 0 && !ent->skeleton))
7374                         return false;
7375                 // get some memory for this entity and generate mesh data
7376                 numvertices = model->surfmesh.num_vertices;
7377                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7378                 if (wantnormals)
7379                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7380                 if (wanttangents)
7381                 {
7382                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7383                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
7384                 }
7385                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
7386                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
7387         }
7388         return true;
7389 }
7390
7391 void R_AnimCache_CacheVisibleEntities(void)
7392 {
7393         int i;
7394         qboolean wantnormals = true;
7395         qboolean wanttangents = !r_showsurfaces.integer;
7396
7397         switch(vid.renderpath)
7398         {
7399         case RENDERPATH_GL20:
7400         case RENDERPATH_D3D9:
7401         case RENDERPATH_D3D10:
7402         case RENDERPATH_D3D11:
7403         case RENDERPATH_GLES2:
7404                 break;
7405         case RENDERPATH_GL13:
7406         case RENDERPATH_GL11:
7407                 wanttangents = false;
7408                 break;
7409         case RENDERPATH_SOFT:
7410                 break;
7411         }
7412
7413         if (r_shownormals.integer)
7414                 wanttangents = wantnormals = true;
7415
7416         // TODO: thread this
7417         // NOTE: R_PrepareRTLights() also caches entities
7418
7419         for (i = 0;i < r_refdef.scene.numentities;i++)
7420                 if (r_refdef.viewcache.entityvisible[i])
7421                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
7422 }
7423
7424 //==================================================================================
7425
7426 static void R_View_UpdateEntityLighting (void)
7427 {
7428         int i;
7429         entity_render_t *ent;
7430         vec3_t tempdiffusenormal, avg;
7431         vec_t f, fa, fd, fdd;
7432         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
7433
7434         for (i = 0;i < r_refdef.scene.numentities;i++)
7435         {
7436                 ent = r_refdef.scene.entities[i];
7437
7438                 // skip unseen models
7439                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
7440                         continue;
7441
7442                 // skip bsp models
7443                 if (ent->model && ent->model->brush.num_leafs)
7444                 {
7445                         // TODO: use modellight for r_ambient settings on world?
7446                         VectorSet(ent->modellight_ambient, 0, 0, 0);
7447                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
7448                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
7449                         continue;
7450                 }
7451
7452                 // fetch the lighting from the worldmodel data
7453                 VectorClear(ent->modellight_ambient);
7454                 VectorClear(ent->modellight_diffuse);
7455                 VectorClear(tempdiffusenormal);
7456                 if ((ent->flags & RENDER_LIGHT) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.LightPoint)
7457                 {
7458                         vec3_t org;
7459                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7460
7461                         // complete lightning for lit sprites
7462                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
7463                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
7464                         {
7465                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
7466                                         org[2] = org[2] + r_overheadsprites_pushback.value;
7467                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7468                         }
7469                         else
7470                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
7471
7472                         if(ent->flags & RENDER_EQUALIZE)
7473                         {
7474                                 // first fix up ambient lighting...
7475                                 if(r_equalize_entities_minambient.value > 0)
7476                                 {
7477                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7478                                         if(fd > 0)
7479                                         {
7480                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
7481                                                 if(fa < r_equalize_entities_minambient.value * fd)
7482                                                 {
7483                                                         // solve:
7484                                                         //   fa'/fd' = minambient
7485                                                         //   fa'+0.25*fd' = fa+0.25*fd
7486                                                         //   ...
7487                                                         //   fa' = fd' * minambient
7488                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
7489                                                         //   ...
7490                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
7491                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
7492                                                         //   ...
7493                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
7494                                                         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
7495                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
7496                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
7497                                                 }
7498                                         }
7499                                 }
7500
7501                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
7502                                 {
7503                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
7504                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
7505                                         f = fa + 0.25 * fd;
7506                                         if(f > 0)
7507                                         {
7508                                                 // adjust brightness and saturation to target
7509                                                 avg[0] = avg[1] = avg[2] = fa / f;
7510                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
7511                                                 avg[0] = avg[1] = avg[2] = fd / f;
7512                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
7513                                         }
7514                                 }
7515                         }
7516                 }
7517                 else // highly rare
7518                         VectorSet(ent->modellight_ambient, 1, 1, 1);
7519
7520                 // move the light direction into modelspace coordinates for lighting code
7521                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
7522                 if(VectorLength2(ent->modellight_lightdir) == 0)
7523                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
7524                 VectorNormalize(ent->modellight_lightdir);
7525         }
7526 }
7527
7528 #define MAX_LINEOFSIGHTTRACES 64
7529
7530 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
7531 {
7532         int i;
7533         vec3_t boxmins, boxmaxs;
7534         vec3_t start;
7535         vec3_t end;
7536         dp_model_t *model = r_refdef.scene.worldmodel;
7537
7538         if (!model || !model->brush.TraceLineOfSight)
7539                 return true;
7540
7541         // expand the box a little
7542         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
7543         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
7544         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
7545         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
7546         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
7547         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
7548
7549         // return true if eye is inside enlarged box
7550         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
7551                 return true;
7552
7553         // try center
7554         VectorCopy(eye, start);
7555         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
7556         if (model->brush.TraceLineOfSight(model, start, end))
7557                 return true;
7558
7559         // try various random positions
7560         for (i = 0;i < numsamples;i++)
7561         {
7562                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
7563                 if (model->brush.TraceLineOfSight(model, start, end))
7564                         return true;
7565         }
7566
7567         return false;
7568 }
7569
7570
7571 static void R_View_UpdateEntityVisible (void)
7572 {
7573         int i;
7574         int renderimask;
7575         int samples;
7576         entity_render_t *ent;
7577
7578         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7579                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
7580                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
7581                 :                                                          RENDER_EXTERIORMODEL;
7582         if (!r_drawviewmodel.integer)
7583                 renderimask |= RENDER_VIEWMODEL;
7584         if (!r_drawexteriormodel.integer)
7585                 renderimask |= RENDER_EXTERIORMODEL;
7586         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
7587         {
7588                 // worldmodel can check visibility
7589                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
7590                 for (i = 0;i < r_refdef.scene.numentities;i++)
7591                 {
7592                         ent = r_refdef.scene.entities[i];
7593                         if (!(ent->flags & renderimask))
7594                         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)))
7595                         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))
7596                                 r_refdef.viewcache.entityvisible[i] = true;
7597                 }
7598                 if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane)
7599                         // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
7600                 {
7601                         for (i = 0;i < r_refdef.scene.numentities;i++)
7602                         {
7603                                 ent = r_refdef.scene.entities[i];
7604                                 if(r_refdef.viewcache.entityvisible[i] && !(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
7605                                 {
7606                                         samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
7607                                         if (samples < 0)
7608                                                 continue; // temp entities do pvs only
7609                                         if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
7610                                                 ent->last_trace_visibility = realtime;
7611                                         if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
7612                                                 r_refdef.viewcache.entityvisible[i] = 0;
7613                                 }
7614                         }
7615                 }
7616         }
7617         else
7618         {
7619                 // no worldmodel or it can't check visibility
7620                 for (i = 0;i < r_refdef.scene.numentities;i++)
7621                 {
7622                         ent = r_refdef.scene.entities[i];
7623                         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));
7624                 }
7625         }
7626 }
7627
7628 /// only used if skyrendermasked, and normally returns false
7629 int R_DrawBrushModelsSky (void)
7630 {
7631         int i, sky;
7632         entity_render_t *ent;
7633
7634         sky = false;
7635         for (i = 0;i < r_refdef.scene.numentities;i++)
7636         {
7637                 if (!r_refdef.viewcache.entityvisible[i])
7638                         continue;
7639                 ent = r_refdef.scene.entities[i];
7640                 if (!ent->model || !ent->model->DrawSky)
7641                         continue;
7642                 ent->model->DrawSky(ent);
7643                 sky = true;
7644         }
7645         return sky;
7646 }
7647
7648 static void R_DrawNoModel(entity_render_t *ent);
7649 static void R_DrawModels(void)
7650 {
7651         int i;
7652         entity_render_t *ent;
7653
7654         for (i = 0;i < r_refdef.scene.numentities;i++)
7655         {
7656                 if (!r_refdef.viewcache.entityvisible[i])
7657                         continue;
7658                 ent = r_refdef.scene.entities[i];
7659                 r_refdef.stats.entities++;
7660                 if (ent->model && ent->model->Draw != NULL)
7661                         ent->model->Draw(ent);
7662                 else
7663                         R_DrawNoModel(ent);
7664         }
7665 }
7666
7667 static void R_DrawModelsDepth(void)
7668 {
7669         int i;
7670         entity_render_t *ent;
7671
7672         for (i = 0;i < r_refdef.scene.numentities;i++)
7673         {
7674                 if (!r_refdef.viewcache.entityvisible[i])
7675                         continue;
7676                 ent = r_refdef.scene.entities[i];
7677                 if (ent->model && ent->model->DrawDepth != NULL)
7678                         ent->model->DrawDepth(ent);
7679         }
7680 }
7681
7682 static void R_DrawModelsDebug(void)
7683 {
7684         int i;
7685         entity_render_t *ent;
7686
7687         for (i = 0;i < r_refdef.scene.numentities;i++)
7688         {
7689                 if (!r_refdef.viewcache.entityvisible[i])
7690                         continue;
7691                 ent = r_refdef.scene.entities[i];
7692                 if (ent->model && ent->model->DrawDebug != NULL)
7693                         ent->model->DrawDebug(ent);
7694         }
7695 }
7696
7697 static void R_DrawModelsAddWaterPlanes(void)
7698 {
7699         int i;
7700         entity_render_t *ent;
7701
7702         for (i = 0;i < r_refdef.scene.numentities;i++)
7703         {
7704                 if (!r_refdef.viewcache.entityvisible[i])
7705                         continue;
7706                 ent = r_refdef.scene.entities[i];
7707                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
7708                         ent->model->DrawAddWaterPlanes(ent);
7709         }
7710 }
7711
7712 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
7713 {
7714         if (r_hdr_irisadaptation.integer)
7715         {
7716                 vec3_t ambient;
7717                 vec3_t diffuse;
7718                 vec3_t diffusenormal;
7719                 vec_t brightness;
7720                 vec_t goal;
7721                 vec_t adjust;
7722                 vec_t current;
7723                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
7724                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
7725                 brightness = max(0.0000001f, brightness);
7726                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
7727                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
7728                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
7729                 current = r_hdr_irisadaptation_value.value;
7730                 if (current < goal)
7731                         current = min(current + adjust, goal);
7732                 else if (current > goal)
7733                         current = max(current - adjust, goal);
7734                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
7735                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
7736         }
7737         else if (r_hdr_irisadaptation_value.value != 1.0f)
7738                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
7739 }
7740
7741 static void R_View_SetFrustum(const int *scissor)
7742 {
7743         int i;
7744         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
7745         vec3_t forward, left, up, origin, v;
7746
7747         if(scissor)
7748         {
7749                 // flipped x coordinates (because x points left here)
7750                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7751                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
7752
7753                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
7754                 switch(vid.renderpath)
7755                 {
7756                         case RENDERPATH_D3D9:
7757                         case RENDERPATH_D3D10:
7758                         case RENDERPATH_D3D11:
7759                         case RENDERPATH_SOFT:
7760                                 // non-flipped y coordinates
7761                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7762                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7763                                 break;
7764                         case RENDERPATH_GL11:
7765                         case RENDERPATH_GL13:
7766                         case RENDERPATH_GL20:
7767                         case RENDERPATH_GLES2:
7768                                 // non-flipped y coordinates
7769                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7770                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
7771                                 break;
7772                 }
7773         }
7774
7775         // we can't trust r_refdef.view.forward and friends in reflected scenes
7776         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
7777
7778 #if 0
7779         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
7780         r_refdef.view.frustum[0].normal[1] = 0 - 0;
7781         r_refdef.view.frustum[0].normal[2] = -1 - 0;
7782         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
7783         r_refdef.view.frustum[1].normal[1] = 0 + 0;
7784         r_refdef.view.frustum[1].normal[2] = -1 + 0;
7785         r_refdef.view.frustum[2].normal[0] = 0 - 0;
7786         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
7787         r_refdef.view.frustum[2].normal[2] = -1 - 0;
7788         r_refdef.view.frustum[3].normal[0] = 0 + 0;
7789         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
7790         r_refdef.view.frustum[3].normal[2] = -1 + 0;
7791 #endif
7792
7793 #if 0
7794         zNear = r_refdef.nearclip;
7795         nudge = 1.0 - 1.0 / (1<<23);
7796         r_refdef.view.frustum[4].normal[0] = 0 - 0;
7797         r_refdef.view.frustum[4].normal[1] = 0 - 0;
7798         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
7799         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
7800         r_refdef.view.frustum[5].normal[0] = 0 + 0;
7801         r_refdef.view.frustum[5].normal[1] = 0 + 0;
7802         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
7803         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
7804 #endif
7805
7806
7807
7808 #if 0
7809         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
7810         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
7811         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
7812         r_refdef.view.frustum[0].dist = m[15] - m[12];
7813
7814         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
7815         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
7816         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
7817         r_refdef.view.frustum[1].dist = m[15] + m[12];
7818
7819         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
7820         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
7821         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
7822         r_refdef.view.frustum[2].dist = m[15] - m[13];
7823
7824         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
7825         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
7826         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
7827         r_refdef.view.frustum[3].dist = m[15] + m[13];
7828
7829         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
7830         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
7831         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
7832         r_refdef.view.frustum[4].dist = m[15] - m[14];
7833
7834         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
7835         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
7836         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
7837         r_refdef.view.frustum[5].dist = m[15] + m[14];
7838 #endif
7839
7840         if (r_refdef.view.useperspective)
7841         {
7842                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
7843                 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]);
7844                 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]);
7845                 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]);
7846                 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]);
7847
7848                 // then the normals from the corners relative to origin
7849                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
7850                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
7851                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
7852                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
7853
7854                 // in a NORMAL view, forward cross left == up
7855                 // in a REFLECTED view, forward cross left == down
7856                 // so our cross products above need to be adjusted for a left handed coordinate system
7857                 CrossProduct(forward, left, v);
7858                 if(DotProduct(v, up) < 0)
7859                 {
7860                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
7861                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
7862                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
7863                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
7864                 }
7865
7866                 // Leaving those out was a mistake, those were in the old code, and they
7867                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
7868                 // I couldn't reproduce it after adding those normalizations. --blub
7869                 VectorNormalize(r_refdef.view.frustum[0].normal);
7870                 VectorNormalize(r_refdef.view.frustum[1].normal);
7871                 VectorNormalize(r_refdef.view.frustum[2].normal);
7872                 VectorNormalize(r_refdef.view.frustum[3].normal);
7873
7874                 // make the corners absolute
7875                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
7876                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
7877                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
7878                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
7879
7880                 // one more normal
7881                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7882
7883                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
7884                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
7885                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
7886                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
7887                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7888         }
7889         else
7890         {
7891                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
7892                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
7893                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
7894                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
7895                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
7896                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
7897                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
7898                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
7899                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
7900                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
7901         }
7902         r_refdef.view.numfrustumplanes = 5;
7903
7904         if (r_refdef.view.useclipplane)
7905         {
7906                 r_refdef.view.numfrustumplanes = 6;
7907                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
7908         }
7909
7910         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
7911                 PlaneClassify(r_refdef.view.frustum + i);
7912
7913         // LordHavoc: note to all quake engine coders, Quake had a special case
7914         // for 90 degrees which assumed a square view (wrong), so I removed it,
7915         // Quake2 has it disabled as well.
7916
7917         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
7918         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
7919         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
7920         //PlaneClassify(&frustum[0]);
7921
7922         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
7923         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
7924         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
7925         //PlaneClassify(&frustum[1]);
7926
7927         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
7928         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
7929         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
7930         //PlaneClassify(&frustum[2]);
7931
7932         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
7933         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
7934         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
7935         //PlaneClassify(&frustum[3]);
7936
7937         // nearclip plane
7938         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
7939         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
7940         //PlaneClassify(&frustum[4]);
7941 }
7942
7943 void R_View_UpdateWithScissor(const int *myscissor)
7944 {
7945         R_Main_ResizeViewCache();
7946         R_View_SetFrustum(myscissor);
7947         R_View_WorldVisibility(r_refdef.view.useclipplane);
7948         R_View_UpdateEntityVisible();
7949         R_View_UpdateEntityLighting();
7950 }
7951
7952 void R_View_Update(void)
7953 {
7954         R_Main_ResizeViewCache();
7955         R_View_SetFrustum(NULL);
7956         R_View_WorldVisibility(r_refdef.view.useclipplane);
7957         R_View_UpdateEntityVisible();
7958         R_View_UpdateEntityLighting();
7959 }
7960
7961 void R_SetupView(qboolean allowwaterclippingplane)
7962 {
7963         const float *customclipplane = NULL;
7964         float plane[4];
7965         if (r_refdef.view.useclipplane && allowwaterclippingplane)
7966         {
7967                 // LordHavoc: couldn't figure out how to make this approach the
7968                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
7969                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
7970                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
7971                         dist = r_refdef.view.clipplane.dist;
7972                 plane[0] = r_refdef.view.clipplane.normal[0];
7973                 plane[1] = r_refdef.view.clipplane.normal[1];
7974                 plane[2] = r_refdef.view.clipplane.normal[2];
7975                 plane[3] = dist;
7976                 customclipplane = plane;
7977         }
7978
7979         if (!r_refdef.view.useperspective)
7980                 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);
7981         else if (vid.stencil && r_useinfinitefarclip.integer)
7982                 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);
7983         else
7984                 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);
7985         R_SetViewport(&r_refdef.view.viewport);
7986 }
7987
7988 void R_EntityMatrix(const matrix4x4_t *matrix)
7989 {
7990         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
7991         {
7992                 gl_modelmatrixchanged = false;
7993                 gl_modelmatrix = *matrix;
7994                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
7995                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
7996                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
7997                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
7998                 CHECKGLERROR
7999                 switch(vid.renderpath)
8000                 {
8001                 case RENDERPATH_D3D9:
8002 #ifdef SUPPORTD3D
8003                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
8004                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
8005 #endif
8006                         break;
8007                 case RENDERPATH_D3D10:
8008                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
8009                         break;
8010                 case RENDERPATH_D3D11:
8011                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
8012                         break;
8013                 case RENDERPATH_GL13:
8014                 case RENDERPATH_GL11:
8015                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
8016                         break;
8017                 case RENDERPATH_SOFT:
8018                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
8019                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
8020                         break;
8021                 case RENDERPATH_GL20:
8022                 case RENDERPATH_GLES2:
8023                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
8024                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
8025                         break;
8026                 }
8027         }
8028 }
8029
8030 void R_ResetViewRendering2D(void)
8031 {
8032         r_viewport_t viewport;
8033         DrawQ_Finish();
8034
8035         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
8036         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);
8037         R_SetViewport(&viewport);
8038         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
8039         GL_Color(1, 1, 1, 1);
8040         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8041         GL_BlendFunc(GL_ONE, GL_ZERO);
8042         GL_ScissorTest(false);
8043         GL_DepthMask(false);
8044         GL_DepthRange(0, 1);
8045         GL_DepthTest(false);
8046         GL_DepthFunc(GL_LEQUAL);
8047         R_EntityMatrix(&identitymatrix);
8048         R_Mesh_ResetTextureState();
8049         GL_PolygonOffset(0, 0);
8050         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8051         switch(vid.renderpath)
8052         {
8053         case RENDERPATH_GL11:
8054         case RENDERPATH_GL13:
8055         case RENDERPATH_GL20:
8056         case RENDERPATH_GLES2:
8057                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8058                 break;
8059         case RENDERPATH_D3D9:
8060         case RENDERPATH_D3D10:
8061         case RENDERPATH_D3D11:
8062         case RENDERPATH_SOFT:
8063                 break;
8064         }
8065         GL_CullFace(GL_NONE);
8066 }
8067
8068 void R_ResetViewRendering3D(void)
8069 {
8070         DrawQ_Finish();
8071
8072         R_SetupView(true);
8073         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
8074         GL_Color(1, 1, 1, 1);
8075         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
8076         GL_BlendFunc(GL_ONE, GL_ZERO);
8077         GL_ScissorTest(true);
8078         GL_DepthMask(true);
8079         GL_DepthRange(0, 1);
8080         GL_DepthTest(true);
8081         GL_DepthFunc(GL_LEQUAL);
8082         R_EntityMatrix(&identitymatrix);
8083         R_Mesh_ResetTextureState();
8084         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
8085         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
8086         switch(vid.renderpath)
8087         {
8088         case RENDERPATH_GL11:
8089         case RENDERPATH_GL13:
8090         case RENDERPATH_GL20:
8091         case RENDERPATH_GLES2:
8092                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
8093                 break;
8094         case RENDERPATH_D3D9:
8095         case RENDERPATH_D3D10:
8096         case RENDERPATH_D3D11:
8097         case RENDERPATH_SOFT:
8098                 break;
8099         }
8100         GL_CullFace(r_refdef.view.cullface_back);
8101 }
8102
8103 /*
8104 ================
8105 R_RenderView_UpdateViewVectors
8106 ================
8107 */
8108 static void R_RenderView_UpdateViewVectors(void)
8109 {
8110         // break apart the view matrix into vectors for various purposes
8111         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
8112         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
8113         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
8114         VectorNegate(r_refdef.view.left, r_refdef.view.right);
8115         // make an inverted copy of the view matrix for tracking sprites
8116         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
8117 }
8118
8119 void R_RenderScene(void);
8120 void R_RenderWaterPlanes(void);
8121
8122 static void R_Water_StartFrame(void)
8123 {
8124         int i;
8125         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
8126         r_waterstate_waterplane_t *p;
8127
8128         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
8129                 return;
8130
8131         switch(vid.renderpath)
8132         {
8133         case RENDERPATH_GL20:
8134         case RENDERPATH_D3D9:
8135         case RENDERPATH_D3D10:
8136         case RENDERPATH_D3D11:
8137         case RENDERPATH_SOFT:
8138         case RENDERPATH_GLES2:
8139                 break;
8140         case RENDERPATH_GL13:
8141         case RENDERPATH_GL11:
8142                 return;
8143         }
8144
8145         // set waterwidth and waterheight to the water resolution that will be
8146         // used (often less than the screen resolution for faster rendering)
8147         waterwidth = (int)bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width);
8148         waterheight = (int)bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height);
8149
8150         // calculate desired texture sizes
8151         // can't use water if the card does not support the texture size
8152         if (!r_water.integer || r_showsurfaces.integer)
8153                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
8154         else if (vid.support.arb_texture_non_power_of_two)
8155         {
8156                 texturewidth = waterwidth;
8157                 textureheight = waterheight;
8158                 camerawidth = waterwidth;
8159                 cameraheight = waterheight;
8160         }
8161         else
8162         {
8163                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
8164                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
8165                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
8166                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
8167         }
8168
8169         // allocate textures as needed
8170         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
8171         {
8172                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8173                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
8174                 {
8175                         if (p->texture_refraction)
8176                                 R_FreeTexture(p->texture_refraction);
8177                         p->texture_refraction = NULL;
8178                         if (p->texture_reflection)
8179                                 R_FreeTexture(p->texture_reflection);
8180                         p->texture_reflection = NULL;
8181                         if (p->texture_camera)
8182                                 R_FreeTexture(p->texture_camera);
8183                         p->texture_camera = NULL;
8184                 }
8185                 memset(&r_waterstate, 0, sizeof(r_waterstate));
8186                 r_waterstate.texturewidth = texturewidth;
8187                 r_waterstate.textureheight = textureheight;
8188                 r_waterstate.camerawidth = camerawidth;
8189                 r_waterstate.cameraheight = cameraheight;
8190         }
8191
8192         if (r_waterstate.texturewidth)
8193         {
8194                 r_waterstate.enabled = true;
8195
8196                 // when doing a reduced render (HDR) we want to use a smaller area
8197                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
8198                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
8199
8200                 // set up variables that will be used in shader setup
8201                 r_waterstate.screenscale[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8202                 r_waterstate.screenscale[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8203                 r_waterstate.screencenter[0] = 0.5f * (float)r_waterstate.waterwidth / (float)r_waterstate.texturewidth;
8204                 r_waterstate.screencenter[1] = 0.5f * (float)r_waterstate.waterheight / (float)r_waterstate.textureheight;
8205         }
8206
8207         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
8208         r_waterstate.numwaterplanes = 0;
8209 }
8210
8211 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
8212 {
8213         int triangleindex, planeindex;
8214         const int *e;
8215         vec3_t vert[3];
8216         vec3_t normal;
8217         vec3_t center;
8218         mplane_t plane;
8219         r_waterstate_waterplane_t *p;
8220         texture_t *t = R_GetCurrentTexture(surface->texture);
8221
8222         // just use the first triangle with a valid normal for any decisions
8223         VectorClear(normal);
8224         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
8225         {
8226                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
8227                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
8228                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
8229                 TriangleNormal(vert[0], vert[1], vert[2], normal);
8230                 if (VectorLength2(normal) >= 0.001)
8231                         break;
8232         }
8233
8234         VectorCopy(normal, plane.normal);
8235         VectorNormalize(plane.normal);
8236         plane.dist = DotProduct(vert[0], plane.normal);
8237         PlaneClassify(&plane);
8238         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
8239         {
8240                 // skip backfaces (except if nocullface is set)
8241                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
8242                         return;
8243                 VectorNegate(plane.normal, plane.normal);
8244                 plane.dist *= -1;
8245                 PlaneClassify(&plane);
8246         }
8247
8248
8249         // find a matching plane if there is one
8250         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8251                 if(p->camera_entity == t->camera_entity)
8252                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
8253                                 break;
8254         if (planeindex >= r_waterstate.maxwaterplanes)
8255                 return; // nothing we can do, out of planes
8256
8257         // if this triangle does not fit any known plane rendered this frame, add one
8258         if (planeindex >= r_waterstate.numwaterplanes)
8259         {
8260                 // store the new plane
8261                 r_waterstate.numwaterplanes++;
8262                 p->plane = plane;
8263                 // clear materialflags and pvs
8264                 p->materialflags = 0;
8265                 p->pvsvalid = false;
8266                 p->camera_entity = t->camera_entity;
8267                 VectorCopy(surface->mins, p->mins);
8268                 VectorCopy(surface->maxs, p->maxs);
8269         }
8270         else
8271         {
8272                 // merge mins/maxs
8273                 p->mins[0] = min(p->mins[0], surface->mins[0]);
8274                 p->mins[1] = min(p->mins[1], surface->mins[1]);
8275                 p->mins[2] = min(p->mins[2], surface->mins[2]);
8276                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
8277                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
8278                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
8279         }
8280         // merge this surface's materialflags into the waterplane
8281         p->materialflags |= t->currentmaterialflags;
8282         if(!(p->materialflags & MATERIALFLAG_CAMERA))
8283         {
8284                 // merge this surface's PVS into the waterplane
8285                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
8286                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
8287                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
8288                 {
8289                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
8290                         p->pvsvalid = true;
8291                 }
8292         }
8293 }
8294
8295 static void R_Water_ProcessPlanes(void)
8296 {
8297         int myscissor[4];
8298         r_refdef_view_t originalview;
8299         r_refdef_view_t myview;
8300         int planeindex;
8301         r_waterstate_waterplane_t *p;
8302         vec3_t visorigin;
8303
8304         originalview = r_refdef.view;
8305
8306         // make sure enough textures are allocated
8307         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8308         {
8309                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8310                 {
8311                         if (!p->texture_refraction)
8312                                 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);
8313                         if (!p->texture_refraction)
8314                                 goto error;
8315                 }
8316                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8317                 {
8318                         if (!p->texture_camera)
8319                                 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);
8320                         if (!p->texture_camera)
8321                                 goto error;
8322                 }
8323
8324                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8325                 {
8326                         if (!p->texture_reflection)
8327                                 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);
8328                         if (!p->texture_reflection)
8329                                 goto error;
8330                 }
8331         }
8332
8333         // render views
8334         r_refdef.view = originalview;
8335         r_refdef.view.showdebug = false;
8336         r_refdef.view.width = r_waterstate.waterwidth;
8337         r_refdef.view.height = r_waterstate.waterheight;
8338         r_refdef.view.useclipplane = true;
8339         myview = r_refdef.view;
8340         r_waterstate.renderingscene = true;
8341         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
8342         {
8343                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
8344                 {
8345                         r_refdef.view = myview;
8346                         if(r_water_scissormode.integer)
8347                         {
8348                                 R_SetupView(true);
8349                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8350                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8351                         }
8352
8353                         // render reflected scene and copy into texture
8354                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
8355                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
8356                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
8357                         r_refdef.view.clipplane = p->plane;
8358
8359                         // reverse the cullface settings for this render
8360                         r_refdef.view.cullface_front = GL_FRONT;
8361                         r_refdef.view.cullface_back = GL_BACK;
8362                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
8363                         {
8364                                 r_refdef.view.usecustompvs = true;
8365                                 if (p->pvsvalid)
8366                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8367                                 else
8368                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
8369                         }
8370
8371                         R_ResetViewRendering3D();
8372                         R_ClearScreen(r_refdef.fogenabled);
8373                         if(r_water_scissormode.integer & 2)
8374                                 R_View_UpdateWithScissor(myscissor);
8375                         else
8376                                 R_View_Update();
8377                         if(r_water_scissormode.integer & 1)
8378                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8379                         R_RenderScene();
8380
8381                         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);
8382                 }
8383
8384                 // render the normal view scene and copy into texture
8385                 // (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)
8386                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
8387                 {
8388                         r_refdef.view = myview;
8389                         if(r_water_scissormode.integer)
8390                         {
8391                                 R_SetupView(true);
8392                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
8393                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
8394                         }
8395
8396                         r_waterstate.renderingrefraction = true;
8397
8398                         r_refdef.view.clipplane = p->plane;
8399                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8400                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8401
8402                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
8403                         {
8404                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8405                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
8406                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8407                                 R_RenderView_UpdateViewVectors();
8408                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8409                                 {
8410                                         r_refdef.view.usecustompvs = true;
8411                                         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);
8412                                 }
8413                         }
8414
8415                         PlaneClassify(&r_refdef.view.clipplane);
8416
8417                         R_ResetViewRendering3D();
8418                         R_ClearScreen(r_refdef.fogenabled);
8419                         if(r_water_scissormode.integer & 2)
8420                                 R_View_UpdateWithScissor(myscissor);
8421                         else
8422                                 R_View_Update();
8423                         if(r_water_scissormode.integer & 1)
8424                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
8425                         R_RenderScene();
8426
8427                         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);
8428                         r_waterstate.renderingrefraction = false;
8429                 }
8430                 else if (p->materialflags & MATERIALFLAG_CAMERA)
8431                 {
8432                         r_refdef.view = myview;
8433
8434                         r_refdef.view.clipplane = p->plane;
8435                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
8436                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
8437
8438                         r_refdef.view.width = r_waterstate.camerawidth;
8439                         r_refdef.view.height = r_waterstate.cameraheight;
8440                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
8441                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
8442
8443                         if(p->camera_entity)
8444                         {
8445                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
8446                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
8447                         }
8448
8449                         // note: all of the view is used for displaying... so
8450                         // there is no use in scissoring
8451
8452                         // reverse the cullface settings for this render
8453                         r_refdef.view.cullface_front = GL_FRONT;
8454                         r_refdef.view.cullface_back = GL_BACK;
8455                         // also reverse the view matrix
8456                         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
8457                         R_RenderView_UpdateViewVectors();
8458                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
8459                         {
8460                                 r_refdef.view.usecustompvs = true;
8461                                 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);
8462                         }
8463                         
8464                         // camera needs no clipplane
8465                         r_refdef.view.useclipplane = false;
8466
8467                         PlaneClassify(&r_refdef.view.clipplane);
8468
8469                         R_ResetViewRendering3D();
8470                         R_ClearScreen(r_refdef.fogenabled);
8471                         R_View_Update();
8472                         R_RenderScene();
8473
8474                         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);
8475                         r_waterstate.renderingrefraction = false;
8476                 }
8477
8478         }
8479         r_waterstate.renderingscene = false;
8480         r_refdef.view = originalview;
8481         R_ResetViewRendering3D();
8482         R_ClearScreen(r_refdef.fogenabled);
8483         R_View_Update();
8484         return;
8485 error:
8486         r_refdef.view = originalview;
8487         r_waterstate.renderingscene = false;
8488         Cvar_SetValueQuick(&r_water, 0);
8489         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
8490         return;
8491 }
8492
8493 void R_Bloom_StartFrame(void)
8494 {
8495         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
8496
8497         switch(vid.renderpath)
8498         {
8499         case RENDERPATH_GL20:
8500         case RENDERPATH_D3D9:
8501         case RENDERPATH_D3D10:
8502         case RENDERPATH_D3D11:
8503         case RENDERPATH_SOFT:
8504         case RENDERPATH_GLES2:
8505                 break;
8506         case RENDERPATH_GL13:
8507         case RENDERPATH_GL11:
8508                 return;
8509         }
8510
8511         // set bloomwidth and bloomheight to the bloom resolution that will be
8512         // used (often less than the screen resolution for faster rendering)
8513         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
8514         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
8515         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
8516         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
8517         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
8518
8519         // calculate desired texture sizes
8520         if (vid.support.arb_texture_non_power_of_two)
8521         {
8522                 screentexturewidth = r_refdef.view.width;
8523                 screentextureheight = r_refdef.view.height;
8524                 bloomtexturewidth = r_bloomstate.bloomwidth;
8525                 bloomtextureheight = r_bloomstate.bloomheight;
8526         }
8527         else
8528         {
8529                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
8530                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
8531                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
8532                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
8533         }
8534
8535         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))
8536         {
8537                 Cvar_SetValueQuick(&r_hdr, 0);
8538                 Cvar_SetValueQuick(&r_bloom, 0);
8539                 Cvar_SetValueQuick(&r_motionblur, 0);
8540                 Cvar_SetValueQuick(&r_damageblur, 0);
8541         }
8542
8543         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)))
8544                 screentexturewidth = screentextureheight = 0;
8545         if (!r_hdr.integer && !r_bloom.integer)
8546                 bloomtexturewidth = bloomtextureheight = 0;
8547
8548         // allocate textures as needed
8549         if (r_bloomstate.screentexturewidth != screentexturewidth || r_bloomstate.screentextureheight != screentextureheight)
8550         {
8551                 if (r_bloomstate.texture_screen)
8552                         R_FreeTexture(r_bloomstate.texture_screen);
8553                 r_bloomstate.texture_screen = NULL;
8554                 r_bloomstate.screentexturewidth = screentexturewidth;
8555                 r_bloomstate.screentextureheight = screentextureheight;
8556                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
8557                         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);
8558         }
8559         if (r_bloomstate.bloomtexturewidth != bloomtexturewidth || r_bloomstate.bloomtextureheight != bloomtextureheight)
8560         {
8561                 if (r_bloomstate.texture_bloom)
8562                         R_FreeTexture(r_bloomstate.texture_bloom);
8563                 r_bloomstate.texture_bloom = NULL;
8564                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
8565                 r_bloomstate.bloomtextureheight = bloomtextureheight;
8566                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
8567                         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);
8568         }
8569
8570         // when doing a reduced render (HDR) we want to use a smaller area
8571         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
8572         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
8573         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
8574         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
8575         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
8576
8577         // set up a texcoord array for the full resolution screen image
8578         // (we have to keep this around to copy back during final render)
8579         r_bloomstate.screentexcoord2f[0] = 0;
8580         r_bloomstate.screentexcoord2f[1] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8581         r_bloomstate.screentexcoord2f[2] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8582         r_bloomstate.screentexcoord2f[3] = (float)r_refdef.view.height    / (float)r_bloomstate.screentextureheight;
8583         r_bloomstate.screentexcoord2f[4] = (float)r_refdef.view.width     / (float)r_bloomstate.screentexturewidth;
8584         r_bloomstate.screentexcoord2f[5] = 0;
8585         r_bloomstate.screentexcoord2f[6] = 0;
8586         r_bloomstate.screentexcoord2f[7] = 0;
8587
8588         // set up a texcoord array for the reduced resolution bloom image
8589         // (which will be additive blended over the screen image)
8590         r_bloomstate.bloomtexcoord2f[0] = 0;
8591         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8592         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8593         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8594         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
8595         r_bloomstate.bloomtexcoord2f[5] = 0;
8596         r_bloomstate.bloomtexcoord2f[6] = 0;
8597         r_bloomstate.bloomtexcoord2f[7] = 0;
8598
8599         switch(vid.renderpath)
8600         {
8601         case RENDERPATH_GL11:
8602         case RENDERPATH_GL13:
8603         case RENDERPATH_GL20:
8604         case RENDERPATH_SOFT:
8605         case RENDERPATH_GLES2:
8606                 break;
8607         case RENDERPATH_D3D9:
8608         case RENDERPATH_D3D10:
8609         case RENDERPATH_D3D11:
8610                 {
8611                         int i;
8612                         for (i = 0;i < 4;i++)
8613                         {
8614                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
8615                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
8616                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
8617                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
8618                         }
8619                 }
8620                 break;
8621         }
8622
8623         if (r_hdr.integer || r_bloom.integer)
8624         {
8625                 r_bloomstate.enabled = true;
8626                 r_bloomstate.hdr = r_hdr.integer != 0;
8627         }
8628
8629         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);
8630 }
8631
8632 void R_Bloom_CopyBloomTexture(float colorscale)
8633 {
8634         r_refdef.stats.bloom++;
8635
8636         // scale down screen texture to the bloom texture size
8637         CHECKGLERROR
8638         R_SetViewport(&r_bloomstate.viewport);
8639         GL_BlendFunc(GL_ONE, GL_ZERO);
8640         GL_Color(colorscale, colorscale, colorscale, 1);
8641         // 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...
8642         switch(vid.renderpath)
8643         {
8644         case RENDERPATH_GL11:
8645         case RENDERPATH_GL13:
8646         case RENDERPATH_GL20:
8647         case RENDERPATH_SOFT:
8648         case RENDERPATH_GLES2:
8649                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8650                 break;
8651         case RENDERPATH_D3D9:
8652         case RENDERPATH_D3D10:
8653         case RENDERPATH_D3D11:
8654                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8655                 break;
8656         }
8657         // TODO: do boxfilter scale-down in shader?
8658         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8659         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8660         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8661
8662         // we now have a bloom image in the framebuffer
8663         // copy it into the bloom image texture for later processing
8664         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
8665         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8666 }
8667
8668 void R_Bloom_CopyHDRTexture(void)
8669 {
8670         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);
8671         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8672 }
8673
8674 void R_Bloom_MakeTexture(void)
8675 {
8676         int x, range, dir;
8677         float xoffset, yoffset, r, brighten;
8678
8679         r_refdef.stats.bloom++;
8680
8681         R_ResetViewRendering2D();
8682
8683         // we have a bloom image in the framebuffer
8684         CHECKGLERROR
8685         R_SetViewport(&r_bloomstate.viewport);
8686
8687         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
8688         {
8689                 x *= 2;
8690                 r = bound(0, r_bloom_colorexponent.value / x, 1);
8691                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
8692                 GL_Color(r,r,r,1);
8693                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
8694                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8695                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8696                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8697
8698                 // copy the vertically blurred bloom view to a texture
8699                 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);
8700                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8701         }
8702
8703         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
8704         brighten = r_bloom_brighten.value;
8705         if (r_hdr.integer)
8706                 brighten *= r_hdr_range.value;
8707         brighten = sqrt(brighten);
8708         if(range >= 1)
8709                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
8710         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1);
8711
8712         for (dir = 0;dir < 2;dir++)
8713         {
8714                 // blend on at multiple vertical offsets to achieve a vertical blur
8715                 // TODO: do offset blends using GLSL
8716                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
8717                 GL_BlendFunc(GL_ONE, GL_ZERO);
8718                 for (x = -range;x <= range;x++)
8719                 {
8720                         if (!dir){xoffset = 0;yoffset = x;}
8721                         else {xoffset = x;yoffset = 0;}
8722                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
8723                         yoffset /= (float)r_bloomstate.bloomtextureheight;
8724                         // compute a texcoord array with the specified x and y offset
8725                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
8726                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8727                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8728                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
8729                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
8730                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
8731                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
8732                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
8733                         // this r value looks like a 'dot' particle, fading sharply to
8734                         // black at the edges
8735                         // (probably not realistic but looks good enough)
8736                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
8737                         //r = brighten/(range*2+1);
8738                         r = brighten / (range * 2 + 1);
8739                         if(range >= 1)
8740                                 r *= (1 - x*x/(float)(range*range));
8741                         GL_Color(r, r, r, 1);
8742                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
8743                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8744                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
8745                         GL_BlendFunc(GL_ONE, GL_ONE);
8746                 }
8747
8748                 // copy the vertically blurred bloom view to a texture
8749                 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);
8750                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
8751         }
8752 }
8753
8754 void R_HDR_RenderBloomTexture(void)
8755 {
8756         int oldwidth, oldheight;
8757         float oldcolorscale;
8758         qboolean oldwaterstate;
8759
8760         oldwaterstate = r_waterstate.enabled;
8761         oldcolorscale = r_refdef.view.colorscale;
8762         oldwidth = r_refdef.view.width;
8763         oldheight = r_refdef.view.height;
8764         r_refdef.view.width = r_bloomstate.bloomwidth;
8765         r_refdef.view.height = r_bloomstate.bloomheight;
8766
8767         if(r_hdr.integer < 2)
8768                 r_waterstate.enabled = false;
8769
8770         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
8771         // TODO: add exposure compensation features
8772         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
8773
8774         r_refdef.view.showdebug = false;
8775         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
8776
8777         R_ResetViewRendering3D();
8778
8779         R_ClearScreen(r_refdef.fogenabled);
8780         if (r_timereport_active)
8781                 R_TimeReport("HDRclear");
8782
8783         R_View_Update();
8784         if (r_timereport_active)
8785                 R_TimeReport("visibility");
8786
8787         // only do secondary renders with HDR if r_hdr is 2 or higher
8788         r_waterstate.numwaterplanes = 0;
8789         if (r_waterstate.enabled)
8790                 R_RenderWaterPlanes();
8791
8792         r_refdef.view.showdebug = true;
8793         R_RenderScene();
8794         r_waterstate.numwaterplanes = 0;
8795
8796         R_ResetViewRendering2D();
8797
8798         R_Bloom_CopyHDRTexture();
8799         R_Bloom_MakeTexture();
8800
8801         // restore the view settings
8802         r_waterstate.enabled = oldwaterstate;
8803         r_refdef.view.width = oldwidth;
8804         r_refdef.view.height = oldheight;
8805         r_refdef.view.colorscale = oldcolorscale;
8806
8807         R_ResetViewRendering3D();
8808
8809         R_ClearScreen(r_refdef.fogenabled);
8810         if (r_timereport_active)
8811                 R_TimeReport("viewclear");
8812 }
8813
8814 static void R_BlendView(void)
8815 {
8816         unsigned int permutation;
8817         float uservecs[4][4];
8818
8819         switch (vid.renderpath)
8820         {
8821         case RENDERPATH_GL20:
8822         case RENDERPATH_D3D9:
8823         case RENDERPATH_D3D10:
8824         case RENDERPATH_D3D11:
8825         case RENDERPATH_SOFT:
8826         case RENDERPATH_GLES2:
8827                 permutation =
8828                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
8829                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
8830                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
8831                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
8832                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
8833
8834                 if (r_bloomstate.texture_screen)
8835                 {
8836                         // make sure the buffer is available
8837                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
8838
8839                         R_ResetViewRendering2D();
8840
8841                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
8842                         {
8843                                 // declare variables
8844                                 float speed;
8845                                 static float avgspeed;
8846
8847                                 speed = VectorLength(cl.movement_velocity);
8848
8849                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
8850                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
8851
8852                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
8853                                 speed = bound(0, speed, 1);
8854                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
8855
8856                                 // calculate values into a standard alpha
8857                                 cl.motionbluralpha = 1 - exp(-
8858                                                 (
8859                                                  (r_motionblur.value * speed / 80)
8860                                                  +
8861                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
8862                                                 )
8863                                                 /
8864                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
8865                                            );
8866
8867                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
8868                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
8869                                 // apply the blur
8870                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
8871                                 {
8872                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8873                                         GL_Color(1, 1, 1, cl.motionbluralpha);
8874                                         switch(vid.renderpath)
8875                                         {
8876                                         case RENDERPATH_GL11:
8877                                         case RENDERPATH_GL13:
8878                                         case RENDERPATH_GL20:
8879                                         case RENDERPATH_SOFT:
8880                                         case RENDERPATH_GLES2:
8881                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8882                                                 break;
8883                                         case RENDERPATH_D3D9:
8884                                         case RENDERPATH_D3D10:
8885                                         case RENDERPATH_D3D11:
8886                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
8887                                                 break;
8888                                         }
8889                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1);
8890                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8891                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8892                                 }
8893                         }
8894
8895                         // copy view into the screen texture
8896                         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);
8897                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
8898                 }
8899                 else if (!r_bloomstate.texture_bloom)
8900                 {
8901                         // we may still have to do view tint...
8902                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
8903                         {
8904                                 // apply a color tint to the whole view
8905                                 R_ResetViewRendering2D();
8906                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8907                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
8908                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
8909                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
8910                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
8911                         }
8912                         break; // no screen processing, no bloom, skip it
8913                 }
8914
8915                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
8916                 {
8917                         // render simple bloom effect
8918                         // copy the screen and shrink it and darken it for the bloom process
8919                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
8920                         // make the bloom texture
8921                         R_Bloom_MakeTexture();
8922                 }
8923
8924 #if _MSC_VER >= 1400
8925 #define sscanf sscanf_s
8926 #endif
8927                 memset(uservecs, 0, sizeof(uservecs));
8928                 if (r_glsl_postprocess_uservec1_enable.integer)
8929                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
8930                 if (r_glsl_postprocess_uservec2_enable.integer)
8931                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
8932                 if (r_glsl_postprocess_uservec3_enable.integer)
8933                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
8934                 if (r_glsl_postprocess_uservec4_enable.integer)
8935                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
8936
8937                 R_ResetViewRendering2D();
8938                 GL_Color(1, 1, 1, 1);
8939                 GL_BlendFunc(GL_ONE, GL_ZERO);
8940
8941                 switch(vid.renderpath)
8942                 {
8943                 case RENDERPATH_GL20:
8944                 case RENDERPATH_GLES2:
8945                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8946                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
8947                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
8948                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
8949                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
8950                         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]);
8951                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8952                         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]);
8953                         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]);
8954                         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]);
8955                         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]);
8956                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
8957                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8958                         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);
8959                         break;
8960                 case RENDERPATH_D3D9:
8961 #ifdef SUPPORTD3D
8962                         // 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...
8963                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8964                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
8965                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8966                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8967                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8968                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8969                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8970                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8971                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8972                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8973                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8974                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
8975                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
8976                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
8977 #endif
8978                         break;
8979                 case RENDERPATH_D3D10:
8980                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8981                         break;
8982                 case RENDERPATH_D3D11:
8983                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
8984                         break;
8985                 case RENDERPATH_SOFT:
8986                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
8987                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
8988                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
8989                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
8990                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
8991                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
8992                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
8993                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
8994                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
8995                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
8996                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
8997                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
8998                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
8999                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
9000                         break;
9001                 default:
9002                         break;
9003                 }
9004                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9005                 r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
9006                 break;
9007         case RENDERPATH_GL13:
9008         case RENDERPATH_GL11:
9009                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
9010                 {
9011                         // apply a color tint to the whole view
9012                         R_ResetViewRendering2D();
9013                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
9014                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
9015                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9016                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9017                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
9018                 }
9019                 break;
9020         }
9021 }
9022
9023 matrix4x4_t r_waterscrollmatrix;
9024
9025 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
9026 {
9027         if (r_refdef.fog_density)
9028         {
9029                 r_refdef.fogcolor[0] = r_refdef.fog_red;
9030                 r_refdef.fogcolor[1] = r_refdef.fog_green;
9031                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
9032
9033                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
9034                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
9035                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
9036                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
9037
9038                 {
9039                         vec3_t fogvec;
9040                         VectorCopy(r_refdef.fogcolor, fogvec);
9041                         //   color.rgb *= ContrastBoost * SceneBrightness;
9042                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
9043                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
9044                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
9045                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
9046                 }
9047         }
9048 }
9049
9050 void R_UpdateVariables(void)
9051 {
9052         R_Textures_Frame();
9053
9054         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
9055
9056         r_refdef.farclip = r_farclip_base.value;
9057         if (r_refdef.scene.worldmodel)
9058                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
9059         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
9060
9061         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
9062                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
9063         r_refdef.polygonfactor = 0;
9064         r_refdef.polygonoffset = 0;
9065         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9066         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
9067
9068         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
9069         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
9070         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
9071         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
9072         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
9073         if (FAKELIGHT_ENABLED)
9074         {
9075                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
9076         }
9077         if (r_showsurfaces.integer)
9078         {
9079                 r_refdef.scene.rtworld = false;
9080                 r_refdef.scene.rtworldshadows = false;
9081                 r_refdef.scene.rtdlight = false;
9082                 r_refdef.scene.rtdlightshadows = false;
9083                 r_refdef.lightmapintensity = 0;
9084         }
9085
9086         if (gamemode == GAME_NEHAHRA)
9087         {
9088                 if (gl_fogenable.integer)
9089                 {
9090                         r_refdef.oldgl_fogenable = true;
9091                         r_refdef.fog_density = gl_fogdensity.value;
9092                         r_refdef.fog_red = gl_fogred.value;
9093                         r_refdef.fog_green = gl_foggreen.value;
9094                         r_refdef.fog_blue = gl_fogblue.value;
9095                         r_refdef.fog_alpha = 1;
9096                         r_refdef.fog_start = 0;
9097                         r_refdef.fog_end = gl_skyclip.value;
9098                         r_refdef.fog_height = 1<<30;
9099                         r_refdef.fog_fadedepth = 128;
9100                 }
9101                 else if (r_refdef.oldgl_fogenable)
9102                 {
9103                         r_refdef.oldgl_fogenable = false;
9104                         r_refdef.fog_density = 0;
9105                         r_refdef.fog_red = 0;
9106                         r_refdef.fog_green = 0;
9107                         r_refdef.fog_blue = 0;
9108                         r_refdef.fog_alpha = 0;
9109                         r_refdef.fog_start = 0;
9110                         r_refdef.fog_end = 0;
9111                         r_refdef.fog_height = 1<<30;
9112                         r_refdef.fog_fadedepth = 128;
9113                 }
9114         }
9115
9116         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
9117         r_refdef.fog_start = max(0, r_refdef.fog_start);
9118         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
9119
9120         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
9121
9122         if (r_refdef.fog_density && r_drawfog.integer)
9123         {
9124                 r_refdef.fogenabled = true;
9125                 // this is the point where the fog reaches 0.9986 alpha, which we
9126                 // consider a good enough cutoff point for the texture
9127                 // (0.9986 * 256 == 255.6)
9128                 if (r_fog_exp2.integer)
9129                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
9130                 else
9131                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
9132                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
9133                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
9134                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
9135                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
9136                         R_BuildFogHeightTexture();
9137                 // fog color was already set
9138                 // update the fog texture
9139                 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)
9140                         R_BuildFogTexture();
9141                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
9142                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
9143         }
9144         else
9145                 r_refdef.fogenabled = false;
9146
9147         switch(vid.renderpath)
9148         {
9149         case RENDERPATH_GL20:
9150         case RENDERPATH_D3D9:
9151         case RENDERPATH_D3D10:
9152         case RENDERPATH_D3D11:
9153         case RENDERPATH_SOFT:
9154         case RENDERPATH_GLES2:
9155                 if(v_glslgamma.integer && !vid_gammatables_trivial)
9156                 {
9157                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
9158                         {
9159                                 // build GLSL gamma texture
9160 #define RAMPWIDTH 256
9161                                 unsigned short ramp[RAMPWIDTH * 3];
9162                                 unsigned char rampbgr[RAMPWIDTH][4];
9163                                 int i;
9164
9165                                 r_texture_gammaramps_serial = vid_gammatables_serial;
9166
9167                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
9168                                 for(i = 0; i < RAMPWIDTH; ++i)
9169                                 {
9170                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9171                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
9172                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
9173                                         rampbgr[i][3] = 0;
9174                                 }
9175                                 if (r_texture_gammaramps)
9176                                 {
9177                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
9178                                 }
9179                                 else
9180                                 {
9181                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
9182                                 }
9183                         }
9184                 }
9185                 else
9186                 {
9187                         // remove GLSL gamma texture
9188                 }
9189                 break;
9190         case RENDERPATH_GL13:
9191         case RENDERPATH_GL11:
9192                 break;
9193         }
9194 }
9195
9196 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
9197 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
9198 /*
9199 ================
9200 R_SelectScene
9201 ================
9202 */
9203 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
9204         if( scenetype != r_currentscenetype ) {
9205                 // store the old scenetype
9206                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
9207                 r_currentscenetype = scenetype;
9208                 // move in the new scene
9209                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
9210         }
9211 }
9212
9213 /*
9214 ================
9215 R_GetScenePointer
9216 ================
9217 */
9218 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
9219 {
9220         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
9221         if( scenetype == r_currentscenetype ) {
9222                 return &r_refdef.scene;
9223         } else {
9224                 return &r_scenes_store[ scenetype ];
9225         }
9226 }
9227
9228 /*
9229 ================
9230 R_RenderView
9231 ================
9232 */
9233 int dpsoftrast_test;
9234 void R_RenderView(void)
9235 {
9236         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
9237
9238         dpsoftrast_test = r_test.integer;
9239
9240         if (r_timereport_active)
9241                 R_TimeReport("start");
9242         r_textureframe++; // used only by R_GetCurrentTexture
9243         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
9244
9245         if(R_CompileShader_CheckStaticParms())
9246                 R_GLSL_Restart_f();
9247
9248         if (!r_drawentities.integer)
9249                 r_refdef.scene.numentities = 0;
9250
9251         R_AnimCache_ClearCache();
9252         R_FrameData_NewFrame();
9253
9254         /* adjust for stereo display */
9255         if(R_Stereo_Active())
9256         {
9257                 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);
9258                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
9259         }
9260
9261         if (r_refdef.view.isoverlay)
9262         {
9263                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
9264                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
9265                 R_TimeReport("depthclear");
9266
9267                 r_refdef.view.showdebug = false;
9268
9269                 r_waterstate.enabled = false;
9270                 r_waterstate.numwaterplanes = 0;
9271
9272                 R_RenderScene();
9273
9274                 r_refdef.view.matrix = originalmatrix;
9275
9276                 CHECKGLERROR
9277                 return;
9278         }
9279
9280         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
9281         {
9282                 r_refdef.view.matrix = originalmatrix;
9283                 return; //Host_Error ("R_RenderView: NULL worldmodel");
9284         }
9285
9286         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
9287
9288         R_RenderView_UpdateViewVectors();
9289
9290         R_Shadow_UpdateWorldLightSelection();
9291
9292         R_Bloom_StartFrame();
9293         R_Water_StartFrame();
9294
9295         CHECKGLERROR
9296         if (r_timereport_active)
9297                 R_TimeReport("viewsetup");
9298
9299         R_ResetViewRendering3D();
9300
9301         if (r_refdef.view.clear || r_refdef.fogenabled)
9302         {
9303                 R_ClearScreen(r_refdef.fogenabled);
9304                 if (r_timereport_active)
9305                         R_TimeReport("viewclear");
9306         }
9307         r_refdef.view.clear = true;
9308
9309         // this produces a bloom texture to be used in R_BlendView() later
9310         if (r_hdr.integer && r_bloomstate.bloomwidth)
9311         {
9312                 R_HDR_RenderBloomTexture();
9313                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
9314                 r_textureframe++; // used only by R_GetCurrentTexture
9315         }
9316
9317         r_refdef.view.showdebug = true;
9318
9319         R_View_Update();
9320         if (r_timereport_active)
9321                 R_TimeReport("visibility");
9322
9323         r_waterstate.numwaterplanes = 0;
9324         if (r_waterstate.enabled)
9325                 R_RenderWaterPlanes();
9326
9327         R_RenderScene();
9328         r_waterstate.numwaterplanes = 0;
9329
9330         R_BlendView();
9331         if (r_timereport_active)
9332                 R_TimeReport("blendview");
9333
9334         GL_Scissor(0, 0, vid.width, vid.height);
9335         GL_ScissorTest(false);
9336
9337         r_refdef.view.matrix = originalmatrix;
9338
9339         CHECKGLERROR
9340 }
9341
9342 void R_RenderWaterPlanes(void)
9343 {
9344         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
9345         {
9346                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
9347                 if (r_timereport_active)
9348                         R_TimeReport("waterworld");
9349         }
9350
9351         // don't let sound skip if going slow
9352         if (r_refdef.scene.extraupdate)
9353                 S_ExtraUpdate ();
9354
9355         R_DrawModelsAddWaterPlanes();
9356         if (r_timereport_active)
9357                 R_TimeReport("watermodels");
9358
9359         if (r_waterstate.numwaterplanes)
9360         {
9361                 R_Water_ProcessPlanes();
9362                 if (r_timereport_active)
9363                         R_TimeReport("waterscenes");
9364         }
9365 }
9366
9367 extern void R_DrawLightningBeams (void);
9368 extern void VM_CL_AddPolygonsToMeshQueue (void);
9369 extern void R_DrawPortals (void);
9370 extern cvar_t cl_locs_show;
9371 static void R_DrawLocs(void);
9372 static void R_DrawEntityBBoxes(void);
9373 static void R_DrawModelDecals(void);
9374 extern void R_DrawModelShadows(void);
9375 extern void R_DrawModelShadowMaps(void);
9376 extern cvar_t cl_decals_newsystem;
9377 extern qboolean r_shadow_usingdeferredprepass;
9378 void R_RenderScene(void)
9379 {
9380         qboolean shadowmapping = false;
9381
9382         if (r_timereport_active)
9383                 R_TimeReport("beginscene");
9384
9385         r_refdef.stats.renders++;
9386
9387         R_UpdateFogColor();
9388
9389         // don't let sound skip if going slow
9390         if (r_refdef.scene.extraupdate)
9391                 S_ExtraUpdate ();
9392
9393         R_MeshQueue_BeginScene();
9394
9395         R_SkyStartFrame();
9396
9397         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);
9398
9399         if (r_timereport_active)
9400                 R_TimeReport("skystartframe");
9401
9402         if (cl.csqc_vidvars.drawworld)
9403         {
9404                 // don't let sound skip if going slow
9405                 if (r_refdef.scene.extraupdate)
9406                         S_ExtraUpdate ();
9407
9408                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
9409                 {
9410                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
9411                         if (r_timereport_active)
9412                                 R_TimeReport("worldsky");
9413                 }
9414
9415                 if (R_DrawBrushModelsSky() && r_timereport_active)
9416                         R_TimeReport("bmodelsky");
9417
9418                 if (skyrendermasked && skyrenderlater)
9419                 {
9420                         // we have to force off the water clipping plane while rendering sky
9421                         R_SetupView(false);
9422                         R_Sky();
9423                         R_SetupView(true);
9424                         if (r_timereport_active)
9425                                 R_TimeReport("sky");
9426                 }
9427         }
9428
9429         R_AnimCache_CacheVisibleEntities();
9430         if (r_timereport_active)
9431                 R_TimeReport("animation");
9432
9433         R_Shadow_PrepareLights();
9434         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
9435                 R_Shadow_PrepareModelShadows();
9436         if (r_timereport_active)
9437                 R_TimeReport("preparelights");
9438
9439         if (R_Shadow_ShadowMappingEnabled())
9440                 shadowmapping = true;
9441
9442         if (r_shadow_usingdeferredprepass)
9443                 R_Shadow_DrawPrepass();
9444
9445         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
9446         {
9447                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
9448                 if (r_timereport_active)
9449                         R_TimeReport("worlddepth");
9450         }
9451         if (r_depthfirst.integer >= 2)
9452         {
9453                 R_DrawModelsDepth();
9454                 if (r_timereport_active)
9455                         R_TimeReport("modeldepth");
9456         }
9457
9458         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
9459         {
9460                 R_DrawModelShadowMaps();
9461                 R_ResetViewRendering3D();
9462                 // don't let sound skip if going slow
9463                 if (r_refdef.scene.extraupdate)
9464                         S_ExtraUpdate ();
9465         }
9466
9467         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
9468         {
9469                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
9470                 if (r_timereport_active)
9471                         R_TimeReport("world");
9472         }
9473
9474         // don't let sound skip if going slow
9475         if (r_refdef.scene.extraupdate)
9476                 S_ExtraUpdate ();
9477
9478         R_DrawModels();
9479         if (r_timereport_active)
9480                 R_TimeReport("models");
9481
9482         // don't let sound skip if going slow
9483         if (r_refdef.scene.extraupdate)
9484                 S_ExtraUpdate ();
9485
9486         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9487         {
9488                 R_DrawModelShadows();
9489                 R_ResetViewRendering3D();
9490                 // don't let sound skip if going slow
9491                 if (r_refdef.scene.extraupdate)
9492                         S_ExtraUpdate ();
9493         }
9494
9495         if (!r_shadow_usingdeferredprepass)
9496         {
9497                 R_Shadow_DrawLights();
9498                 if (r_timereport_active)
9499                         R_TimeReport("rtlights");
9500         }
9501
9502         // don't let sound skip if going slow
9503         if (r_refdef.scene.extraupdate)
9504                 S_ExtraUpdate ();
9505
9506         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
9507         {
9508                 R_DrawModelShadows();
9509                 R_ResetViewRendering3D();
9510                 // don't let sound skip if going slow
9511                 if (r_refdef.scene.extraupdate)
9512                         S_ExtraUpdate ();
9513         }
9514
9515         if (cl.csqc_vidvars.drawworld)
9516         {
9517                 if (cl_decals_newsystem.integer)
9518                 {
9519                         R_DrawModelDecals();
9520                         if (r_timereport_active)
9521                                 R_TimeReport("modeldecals");
9522                 }
9523                 else
9524                 {
9525                         R_DrawDecals();
9526                         if (r_timereport_active)
9527                                 R_TimeReport("decals");
9528                 }
9529
9530                 R_DrawParticles();
9531                 if (r_timereport_active)
9532                         R_TimeReport("particles");
9533
9534                 R_DrawExplosions();
9535                 if (r_timereport_active)
9536                         R_TimeReport("explosions");
9537
9538                 R_DrawLightningBeams();
9539                 if (r_timereport_active)
9540                         R_TimeReport("lightning");
9541         }
9542
9543         VM_CL_AddPolygonsToMeshQueue();
9544
9545         if (r_refdef.view.showdebug)
9546         {
9547                 if (cl_locs_show.integer)
9548                 {
9549                         R_DrawLocs();
9550                         if (r_timereport_active)
9551                                 R_TimeReport("showlocs");
9552                 }
9553
9554                 if (r_drawportals.integer)
9555                 {
9556                         R_DrawPortals();
9557                         if (r_timereport_active)
9558                                 R_TimeReport("portals");
9559                 }
9560
9561                 if (r_showbboxes.value > 0)
9562                 {
9563                         R_DrawEntityBBoxes();
9564                         if (r_timereport_active)
9565                                 R_TimeReport("bboxes");
9566                 }
9567         }
9568
9569         R_MeshQueue_RenderTransparent();
9570         if (r_timereport_active)
9571                 R_TimeReport("drawtrans");
9572
9573         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))
9574         {
9575                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
9576                 if (r_timereport_active)
9577                         R_TimeReport("worlddebug");
9578                 R_DrawModelsDebug();
9579                 if (r_timereport_active)
9580                         R_TimeReport("modeldebug");
9581         }
9582
9583         if (cl.csqc_vidvars.drawworld)
9584         {
9585                 R_Shadow_DrawCoronas();
9586                 if (r_timereport_active)
9587                         R_TimeReport("coronas");
9588         }
9589
9590 #if 0
9591         {
9592                 GL_DepthTest(false);
9593                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
9594                 GL_Color(1, 1, 1, 1);
9595                 qglBegin(GL_POLYGON);
9596                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
9597                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
9598                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
9599                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
9600                 qglEnd();
9601                 qglBegin(GL_POLYGON);
9602                 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]);
9603                 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]);
9604                 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]);
9605                 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]);
9606                 qglEnd();
9607                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
9608         }
9609 #endif
9610
9611         // don't let sound skip if going slow
9612         if (r_refdef.scene.extraupdate)
9613                 S_ExtraUpdate ();
9614
9615         R_ResetViewRendering2D();
9616 }
9617
9618 static const unsigned short bboxelements[36] =
9619 {
9620         5, 1, 3, 5, 3, 7,
9621         6, 2, 0, 6, 0, 4,
9622         7, 3, 2, 7, 2, 6,
9623         4, 0, 1, 4, 1, 5,
9624         4, 5, 7, 4, 7, 6,
9625         1, 0, 2, 1, 2, 3,
9626 };
9627
9628 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
9629 {
9630         int i;
9631         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
9632
9633         RSurf_ActiveWorldEntity();
9634
9635         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9636         GL_DepthMask(false);
9637         GL_DepthRange(0, 1);
9638         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
9639 //      R_Mesh_ResetTextureState();
9640
9641         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
9642         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
9643         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
9644         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
9645         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
9646         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
9647         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
9648         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
9649         R_FillColors(color4f, 8, cr, cg, cb, ca);
9650         if (r_refdef.fogenabled)
9651         {
9652                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
9653                 {
9654                         f1 = RSurf_FogVertex(v);
9655                         f2 = 1 - f1;
9656                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
9657                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
9658                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
9659                 }
9660         }
9661         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
9662         R_Mesh_ResetTextureState();
9663         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9664         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
9665 }
9666
9667 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9668 {
9669         int i;
9670         float color[4];
9671         prvm_edict_t *edict;
9672         prvm_prog_t *prog_save = prog;
9673
9674         // this function draws bounding boxes of server entities
9675         if (!sv.active)
9676                 return;
9677
9678         GL_CullFace(GL_NONE);
9679         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9680
9681         prog = 0;
9682         SV_VM_Begin();
9683         for (i = 0;i < numsurfaces;i++)
9684         {
9685                 edict = PRVM_EDICT_NUM(surfacelist[i]);
9686                 switch ((int)edict->fields.server->solid)
9687                 {
9688                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
9689                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
9690                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
9691                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
9692                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
9693                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
9694                 }
9695                 color[3] *= r_showbboxes.value;
9696                 color[3] = bound(0, color[3], 1);
9697                 GL_DepthTest(!r_showdisabledepthtest.integer);
9698                 GL_CullFace(r_refdef.view.cullface_front);
9699                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
9700         }
9701         SV_VM_End();
9702         prog = prog_save;
9703 }
9704
9705 static void R_DrawEntityBBoxes(void)
9706 {
9707         int i;
9708         prvm_edict_t *edict;
9709         vec3_t center;
9710         prvm_prog_t *prog_save = prog;
9711
9712         // this function draws bounding boxes of server entities
9713         if (!sv.active)
9714                 return;
9715
9716         prog = 0;
9717         SV_VM_Begin();
9718         for (i = 0;i < prog->num_edicts;i++)
9719         {
9720                 edict = PRVM_EDICT_NUM(i);
9721                 if (edict->priv.server->free)
9722                         continue;
9723                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
9724                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.tag_entity)->edict != 0)
9725                         continue;
9726                 if(PRVM_EDICTFIELDVALUE(edict, prog->fieldoffsets.viewmodelforclient)->edict != 0)
9727                         continue;
9728                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
9729                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
9730         }
9731         SV_VM_End();
9732         prog = prog_save;
9733 }
9734
9735 static const int nomodelelement3i[24] =
9736 {
9737         5, 2, 0,
9738         5, 1, 2,
9739         5, 0, 3,
9740         5, 3, 1,
9741         0, 2, 4,
9742         2, 1, 4,
9743         3, 0, 4,
9744         1, 3, 4
9745 };
9746
9747 static const unsigned short nomodelelement3s[24] =
9748 {
9749         5, 2, 0,
9750         5, 1, 2,
9751         5, 0, 3,
9752         5, 3, 1,
9753         0, 2, 4,
9754         2, 1, 4,
9755         3, 0, 4,
9756         1, 3, 4
9757 };
9758
9759 static const float nomodelvertex3f[6*3] =
9760 {
9761         -16,   0,   0,
9762          16,   0,   0,
9763           0, -16,   0,
9764           0,  16,   0,
9765           0,   0, -16,
9766           0,   0,  16
9767 };
9768
9769 static const float nomodelcolor4f[6*4] =
9770 {
9771         0.0f, 0.0f, 0.5f, 1.0f,
9772         0.0f, 0.0f, 0.5f, 1.0f,
9773         0.0f, 0.5f, 0.0f, 1.0f,
9774         0.0f, 0.5f, 0.0f, 1.0f,
9775         0.5f, 0.0f, 0.0f, 1.0f,
9776         0.5f, 0.0f, 0.0f, 1.0f
9777 };
9778
9779 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
9780 {
9781         int i;
9782         float f1, f2, *c;
9783         float color4f[6*4];
9784
9785         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);
9786
9787         // this is only called once per entity so numsurfaces is always 1, and
9788         // surfacelist is always {0}, so this code does not handle batches
9789
9790         if (rsurface.ent_flags & RENDER_ADDITIVE)
9791         {
9792                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
9793                 GL_DepthMask(false);
9794         }
9795         else if (rsurface.colormod[3] < 1)
9796         {
9797                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9798                 GL_DepthMask(false);
9799         }
9800         else
9801         {
9802                 GL_BlendFunc(GL_ONE, GL_ZERO);
9803                 GL_DepthMask(true);
9804         }
9805         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
9806         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
9807         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
9808         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
9809         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
9810         for (i = 0, c = color4f;i < 6;i++, c += 4)
9811         {
9812                 c[0] *= rsurface.colormod[0];
9813                 c[1] *= rsurface.colormod[1];
9814                 c[2] *= rsurface.colormod[2];
9815                 c[3] *= rsurface.colormod[3];
9816         }
9817         if (r_refdef.fogenabled)
9818         {
9819                 for (i = 0, c = color4f;i < 6;i++, c += 4)
9820                 {
9821                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
9822                         f2 = 1 - f1;
9823                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
9824                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
9825                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
9826                 }
9827         }
9828 //      R_Mesh_ResetTextureState();
9829         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
9830         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
9831         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
9832 }
9833
9834 void R_DrawNoModel(entity_render_t *ent)
9835 {
9836         vec3_t org;
9837         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
9838         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
9839                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
9840         else
9841                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
9842 }
9843
9844 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
9845 {
9846         vec3_t right1, right2, diff, normal;
9847
9848         VectorSubtract (org2, org1, normal);
9849
9850         // calculate 'right' vector for start
9851         VectorSubtract (r_refdef.view.origin, org1, diff);
9852         CrossProduct (normal, diff, right1);
9853         VectorNormalize (right1);
9854
9855         // calculate 'right' vector for end
9856         VectorSubtract (r_refdef.view.origin, org2, diff);
9857         CrossProduct (normal, diff, right2);
9858         VectorNormalize (right2);
9859
9860         vert[ 0] = org1[0] + width * right1[0];
9861         vert[ 1] = org1[1] + width * right1[1];
9862         vert[ 2] = org1[2] + width * right1[2];
9863         vert[ 3] = org1[0] - width * right1[0];
9864         vert[ 4] = org1[1] - width * right1[1];
9865         vert[ 5] = org1[2] - width * right1[2];
9866         vert[ 6] = org2[0] - width * right2[0];
9867         vert[ 7] = org2[1] - width * right2[1];
9868         vert[ 8] = org2[2] - width * right2[2];
9869         vert[ 9] = org2[0] + width * right2[0];
9870         vert[10] = org2[1] + width * right2[1];
9871         vert[11] = org2[2] + width * right2[2];
9872 }
9873
9874 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)
9875 {
9876         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
9877         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
9878         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
9879         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
9880         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
9881         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
9882         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
9883         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
9884         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
9885         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
9886         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
9887         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
9888 }
9889
9890 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
9891 {
9892         int i;
9893         float *vertex3f;
9894         float v[3];
9895         VectorSet(v, x, y, z);
9896         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
9897                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
9898                         break;
9899         if (i == mesh->numvertices)
9900         {
9901                 if (mesh->numvertices < mesh->maxvertices)
9902                 {
9903                         VectorCopy(v, vertex3f);
9904                         mesh->numvertices++;
9905                 }
9906                 return mesh->numvertices;
9907         }
9908         else
9909                 return i;
9910 }
9911
9912 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
9913 {
9914         int i;
9915         int *e, element[3];
9916         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9917         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
9918         e = mesh->element3i + mesh->numtriangles * 3;
9919         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
9920         {
9921                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
9922                 if (mesh->numtriangles < mesh->maxtriangles)
9923                 {
9924                         *e++ = element[0];
9925                         *e++ = element[1];
9926                         *e++ = element[2];
9927                         mesh->numtriangles++;
9928                 }
9929                 element[1] = element[2];
9930         }
9931 }
9932
9933 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
9934 {
9935         int i;
9936         int *e, element[3];
9937         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9938         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
9939         e = mesh->element3i + mesh->numtriangles * 3;
9940         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
9941         {
9942                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
9943                 if (mesh->numtriangles < mesh->maxtriangles)
9944                 {
9945                         *e++ = element[0];
9946                         *e++ = element[1];
9947                         *e++ = element[2];
9948                         mesh->numtriangles++;
9949                 }
9950                 element[1] = element[2];
9951         }
9952 }
9953
9954 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
9955 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
9956 {
9957         int planenum, planenum2;
9958         int w;
9959         int tempnumpoints;
9960         mplane_t *plane, *plane2;
9961         double maxdist;
9962         double temppoints[2][256*3];
9963         // figure out how large a bounding box we need to properly compute this brush
9964         maxdist = 0;
9965         for (w = 0;w < numplanes;w++)
9966                 maxdist = max(maxdist, fabs(planes[w].dist));
9967         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
9968         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
9969         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
9970         {
9971                 w = 0;
9972                 tempnumpoints = 4;
9973                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
9974                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
9975                 {
9976                         if (planenum2 == planenum)
9977                                 continue;
9978                         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);
9979                         w = !w;
9980                 }
9981                 if (tempnumpoints < 3)
9982                         continue;
9983                 // generate elements forming a triangle fan for this polygon
9984                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
9985         }
9986 }
9987
9988 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)
9989 {
9990         texturelayer_t *layer;
9991         layer = t->currentlayers + t->currentnumlayers++;
9992         layer->type = type;
9993         layer->depthmask = depthmask;
9994         layer->blendfunc1 = blendfunc1;
9995         layer->blendfunc2 = blendfunc2;
9996         layer->texture = texture;
9997         layer->texmatrix = *matrix;
9998         layer->color[0] = r;
9999         layer->color[1] = g;
10000         layer->color[2] = b;
10001         layer->color[3] = a;
10002 }
10003
10004 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
10005 {
10006         if(parms[0] == 0 && parms[1] == 0)
10007                 return false;
10008         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10009                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
10010                         return false;
10011         return true;
10012 }
10013
10014 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
10015 {
10016         double index, f;
10017         index = parms[2] + r_refdef.scene.time * parms[3];
10018         index -= floor(index);
10019         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
10020         {
10021         default:
10022         case Q3WAVEFUNC_NONE:
10023         case Q3WAVEFUNC_NOISE:
10024         case Q3WAVEFUNC_COUNT:
10025                 f = 0;
10026                 break;
10027         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
10028         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
10029         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
10030         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
10031         case Q3WAVEFUNC_TRIANGLE:
10032                 index *= 4;
10033                 f = index - floor(index);
10034                 if (index < 1)
10035                         f = f;
10036                 else if (index < 2)
10037                         f = 1 - f;
10038                 else if (index < 3)
10039                         f = -f;
10040                 else
10041                         f = -(1 - f);
10042                 break;
10043         }
10044         f = parms[0] + parms[1] * f;
10045         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
10046                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
10047         return (float) f;
10048 }
10049
10050 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
10051 {
10052         int w, h, idx;
10053         float f;
10054         float tcmat[12];
10055         matrix4x4_t matrix, temp;
10056         switch(tcmod->tcmod)
10057         {
10058                 case Q3TCMOD_COUNT:
10059                 case Q3TCMOD_NONE:
10060                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10061                                 matrix = r_waterscrollmatrix;
10062                         else
10063                                 matrix = identitymatrix;
10064                         break;
10065                 case Q3TCMOD_ENTITYTRANSLATE:
10066                         // this is used in Q3 to allow the gamecode to control texcoord
10067                         // scrolling on the entity, which is not supported in darkplaces yet.
10068                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
10069                         break;
10070                 case Q3TCMOD_ROTATE:
10071                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
10072                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * r_refdef.scene.time, 0, 0, 1);
10073                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
10074                         break;
10075                 case Q3TCMOD_SCALE:
10076                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
10077                         break;
10078                 case Q3TCMOD_SCROLL:
10079                         Matrix4x4_CreateTranslate(&matrix, tcmod->parms[0] * r_refdef.scene.time, tcmod->parms[1] * r_refdef.scene.time, 0);
10080                         break;
10081                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
10082                         w = (int) tcmod->parms[0];
10083                         h = (int) tcmod->parms[1];
10084                         f = r_refdef.scene.time / (tcmod->parms[2] * w * h);
10085                         f = f - floor(f);
10086                         idx = (int) floor(f * w * h);
10087                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
10088                         break;
10089                 case Q3TCMOD_STRETCH:
10090                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
10091                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
10092                         break;
10093                 case Q3TCMOD_TRANSFORM:
10094                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
10095                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
10096                         VectorSet(tcmat +  6, 0                   , 0                , 1);
10097                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
10098                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
10099                         break;
10100                 case Q3TCMOD_TURBULENT:
10101                         // this is handled in the RSurf_PrepareVertices function
10102                         matrix = identitymatrix;
10103                         break;
10104         }
10105         temp = *texmatrix;
10106         Matrix4x4_Concat(texmatrix, &matrix, &temp);
10107 }
10108
10109 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
10110 {
10111         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP | TEXF_COMPRESS;
10112         char name[MAX_QPATH];
10113         skinframe_t *skinframe;
10114         unsigned char pixels[296*194];
10115         strlcpy(cache->name, skinname, sizeof(cache->name));
10116         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
10117         if (developer_loading.integer)
10118                 Con_Printf("loading %s\n", name);
10119         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
10120         if (!skinframe || !skinframe->base)
10121         {
10122                 unsigned char *f;
10123                 fs_offset_t filesize;
10124                 skinframe = NULL;
10125                 f = FS_LoadFile(name, tempmempool, true, &filesize);
10126                 if (f)
10127                 {
10128                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
10129                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
10130                         Mem_Free(f);
10131                 }
10132         }
10133         cache->skinframe = skinframe;
10134 }
10135
10136 texture_t *R_GetCurrentTexture(texture_t *t)
10137 {
10138         int i;
10139         const entity_render_t *ent = rsurface.entity;
10140         dp_model_t *model = ent->model;
10141         q3shaderinfo_layer_tcmod_t *tcmod;
10142
10143         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
10144                 return t->currentframe;
10145         t->update_lastrenderframe = r_textureframe;
10146         t->update_lastrenderentity = (void *)ent;
10147
10148         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
10149                 t->camera_entity = ent->entitynumber;
10150         else
10151                 t->camera_entity = 0;
10152
10153         // switch to an alternate material if this is a q1bsp animated material
10154         {
10155                 texture_t *texture = t;
10156                 int s = rsurface.ent_skinnum;
10157                 if ((unsigned int)s >= (unsigned int)model->numskins)
10158                         s = 0;
10159                 if (model->skinscenes)
10160                 {
10161                         if (model->skinscenes[s].framecount > 1)
10162                                 s = model->skinscenes[s].firstframe + (unsigned int) (r_refdef.scene.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
10163                         else
10164                                 s = model->skinscenes[s].firstframe;
10165                 }
10166                 if (s > 0)
10167                         t = t + s * model->num_surfaces;
10168                 if (t->animated)
10169                 {
10170                         // use an alternate animation if the entity's frame is not 0,
10171                         // and only if the texture has an alternate animation
10172                         if (rsurface.ent_alttextures && t->anim_total[1])
10173                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[1]) : 0];
10174                         else
10175                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(r_refdef.scene.time * 5.0f) % t->anim_total[0]) : 0];
10176                 }
10177                 texture->currentframe = t;
10178         }
10179
10180         // update currentskinframe to be a qw skin or animation frame
10181         if (rsurface.ent_qwskin >= 0)
10182         {
10183                 i = rsurface.ent_qwskin;
10184                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
10185                 {
10186                         r_qwskincache_size = cl.maxclients;
10187                         if (r_qwskincache)
10188                                 Mem_Free(r_qwskincache);
10189                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
10190                 }
10191                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
10192                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
10193                 t->currentskinframe = r_qwskincache[i].skinframe;
10194                 if (t->currentskinframe == NULL)
10195                         t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10196         }
10197         else if (t->numskinframes >= 2)
10198                 t->currentskinframe = t->skinframes[(unsigned int)(t->skinframerate * (cl.time - rsurface.ent_shadertime)) % t->numskinframes];
10199         if (t->backgroundnumskinframes >= 2)
10200                 t->backgroundcurrentskinframe = t->backgroundskinframes[(unsigned int)(t->backgroundskinframerate * (cl.time - rsurface.ent_shadertime)) % t->backgroundnumskinframes];
10201
10202         t->currentmaterialflags = t->basematerialflags;
10203         t->currentalpha = rsurface.colormod[3];
10204         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer))
10205                 t->currentalpha *= r_wateralpha.value;
10206         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
10207                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
10208         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
10209                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
10210         if (!(rsurface.ent_flags & RENDER_LIGHT))
10211                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
10212         else if (FAKELIGHT_ENABLED)
10213         {
10214                         // no modellight if using fakelight for the map
10215         }
10216         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
10217         {
10218                 // pick a model lighting mode
10219                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
10220                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
10221                 else
10222                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
10223         }
10224         if (rsurface.ent_flags & RENDER_ADDITIVE)
10225                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10226         else if (t->currentalpha < 1)
10227                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
10228         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
10229                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
10230         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
10231                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
10232         if (t->backgroundnumskinframes)
10233                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
10234         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
10235         {
10236                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
10237                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
10238         }
10239         else
10240                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
10241         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
10242                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
10243
10244         // there is no tcmod
10245         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
10246         {
10247                 t->currenttexmatrix = r_waterscrollmatrix;
10248                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
10249         }
10250         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
10251         {
10252                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
10253                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
10254         }
10255
10256         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10257                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
10258         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
10259                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
10260
10261         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
10262         if (t->currentskinframe->qpixels)
10263                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
10264         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
10265         if (!t->basetexture)
10266                 t->basetexture = r_texture_notexture;
10267         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
10268         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
10269         t->nmaptexture = t->currentskinframe->nmap;
10270         if (!t->nmaptexture)
10271                 t->nmaptexture = r_texture_blanknormalmap;
10272         t->glosstexture = r_texture_black;
10273         t->glowtexture = t->currentskinframe->glow;
10274         t->fogtexture = t->currentskinframe->fog;
10275         t->reflectmasktexture = t->currentskinframe->reflect;
10276         if (t->backgroundnumskinframes)
10277         {
10278                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
10279                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
10280                 t->backgroundglosstexture = r_texture_black;
10281                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
10282                 if (!t->backgroundnmaptexture)
10283                         t->backgroundnmaptexture = r_texture_blanknormalmap;
10284         }
10285         else
10286         {
10287                 t->backgroundbasetexture = r_texture_white;
10288                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10289                 t->backgroundglosstexture = r_texture_black;
10290                 t->backgroundglowtexture = NULL;
10291         }
10292         t->specularpower = r_shadow_glossexponent.value;
10293         // TODO: store reference values for these in the texture?
10294         t->specularscale = 0;
10295         if (r_shadow_gloss.integer > 0)
10296         {
10297                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
10298                 {
10299                         if (r_shadow_glossintensity.value > 0)
10300                         {
10301                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
10302                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
10303                                 t->specularscale = r_shadow_glossintensity.value;
10304                         }
10305                 }
10306                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
10307                 {
10308                         t->glosstexture = r_texture_white;
10309                         t->backgroundglosstexture = r_texture_white;
10310                         t->specularscale = r_shadow_gloss2intensity.value;
10311                         t->specularpower = r_shadow_gloss2exponent.value;
10312                 }
10313         }
10314         t->specularscale *= t->specularscalemod;
10315         t->specularpower *= t->specularpowermod;
10316
10317         // lightmaps mode looks bad with dlights using actual texturing, so turn
10318         // off the colormap and glossmap, but leave the normalmap on as it still
10319         // accurately represents the shading involved
10320         if (gl_lightmaps.integer)
10321         {
10322                 t->basetexture = r_texture_grey128;
10323                 t->pantstexture = r_texture_black;
10324                 t->shirttexture = r_texture_black;
10325                 t->nmaptexture = r_texture_blanknormalmap;
10326                 t->glosstexture = r_texture_black;
10327                 t->glowtexture = NULL;
10328                 t->fogtexture = NULL;
10329                 t->reflectmasktexture = NULL;
10330                 t->backgroundbasetexture = NULL;
10331                 t->backgroundnmaptexture = r_texture_blanknormalmap;
10332                 t->backgroundglosstexture = r_texture_black;
10333                 t->backgroundglowtexture = NULL;
10334                 t->specularscale = 0;
10335                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
10336         }
10337
10338         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
10339         VectorClear(t->dlightcolor);
10340         t->currentnumlayers = 0;
10341         if (t->currentmaterialflags & MATERIALFLAG_WALL)
10342         {
10343                 int blendfunc1, blendfunc2;
10344                 qboolean depthmask;
10345                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
10346                 {
10347                         blendfunc1 = GL_SRC_ALPHA;
10348                         blendfunc2 = GL_ONE;
10349                 }
10350                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
10351                 {
10352                         blendfunc1 = GL_SRC_ALPHA;
10353                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
10354                 }
10355                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10356                 {
10357                         blendfunc1 = t->customblendfunc[0];
10358                         blendfunc2 = t->customblendfunc[1];
10359                 }
10360                 else
10361                 {
10362                         blendfunc1 = GL_ONE;
10363                         blendfunc2 = GL_ZERO;
10364                 }
10365                 // don't colormod evilblend textures
10366                 if(!R_BlendFuncAllowsColormod(blendfunc1, blendfunc2))
10367                         VectorSet(t->lightmapcolor, 1, 1, 1);
10368                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
10369                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10370                 {
10371                         // fullbright is not affected by r_refdef.lightmapintensity
10372                         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]);
10373                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10374                                 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]);
10375                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10376                                 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]);
10377                 }
10378                 else
10379                 {
10380                         vec3_t ambientcolor;
10381                         float colorscale;
10382                         // set the color tint used for lights affecting this surface
10383                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
10384                         colorscale = 2;
10385                         // q3bsp has no lightmap updates, so the lightstylevalue that
10386                         // would normally be baked into the lightmap must be
10387                         // applied to the color
10388                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
10389                         if (model->type == mod_brushq3)
10390                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
10391                         colorscale *= r_refdef.lightmapintensity;
10392                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
10393                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
10394                         // basic lit geometry
10395                         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]);
10396                         // add pants/shirt if needed
10397                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10398                                 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]);
10399                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10400                                 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]);
10401                         // now add ambient passes if needed
10402                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
10403                         {
10404                                 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]);
10405                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
10406                                         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]);
10407                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
10408                                         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]);
10409                         }
10410                 }
10411                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
10412                         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]);
10413                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
10414                 {
10415                         // if this is opaque use alpha blend which will darken the earlier
10416                         // passes cheaply.
10417                         //
10418                         // if this is an alpha blended material, all the earlier passes
10419                         // were darkened by fog already, so we only need to add the fog
10420                         // color ontop through the fog mask texture
10421                         //
10422                         // if this is an additive blended material, all the earlier passes
10423                         // were darkened by fog already, and we should not add fog color
10424                         // (because the background was not darkened, there is no fog color
10425                         // that was lost behind it).
10426                         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]);
10427                 }
10428         }
10429
10430         return t->currentframe;
10431 }
10432
10433 rsurfacestate_t rsurface;
10434
10435 void RSurf_ActiveWorldEntity(void)
10436 {
10437         dp_model_t *model = r_refdef.scene.worldmodel;
10438         //if (rsurface.entity == r_refdef.scene.worldentity)
10439         //      return;
10440         rsurface.entity = r_refdef.scene.worldentity;
10441         rsurface.skeleton = NULL;
10442         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
10443         rsurface.ent_skinnum = 0;
10444         rsurface.ent_qwskin = -1;
10445         rsurface.ent_shadertime = 0;
10446         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
10447         rsurface.matrix = identitymatrix;
10448         rsurface.inversematrix = identitymatrix;
10449         rsurface.matrixscale = 1;
10450         rsurface.inversematrixscale = 1;
10451         R_EntityMatrix(&identitymatrix);
10452         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
10453         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
10454         rsurface.fograngerecip = r_refdef.fograngerecip;
10455         rsurface.fogheightfade = r_refdef.fogheightfade;
10456         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
10457         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10458         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10459         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10460         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10461         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10462         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10463         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
10464         rsurface.colormod[3] = 1;
10465         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);
10466         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10467         rsurface.frameblend[0].lerp = 1;
10468         rsurface.ent_alttextures = false;
10469         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10470         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10471         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10472         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10473         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10474         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10475         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10476         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10477         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10478         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10479         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10480         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10481         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10482         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10483         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10484         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10485         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10486         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10487         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10488         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10489         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10490         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10491         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10492         rsurface.modelelement3i = model->surfmesh.data_element3i;
10493         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10494         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10495         rsurface.modelelement3s = model->surfmesh.data_element3s;
10496         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10497         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10498         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10499         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10500         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10501         rsurface.modelsurfaces = model->data_surfaces;
10502         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10503         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10504         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10505         rsurface.modelgeneratedvertex = false;
10506         rsurface.batchgeneratedvertex = false;
10507         rsurface.batchfirstvertex = 0;
10508         rsurface.batchnumvertices = 0;
10509         rsurface.batchfirsttriangle = 0;
10510         rsurface.batchnumtriangles = 0;
10511         rsurface.batchvertex3f  = NULL;
10512         rsurface.batchvertex3f_vertexbuffer = NULL;
10513         rsurface.batchvertex3f_bufferoffset = 0;
10514         rsurface.batchsvector3f = NULL;
10515         rsurface.batchsvector3f_vertexbuffer = NULL;
10516         rsurface.batchsvector3f_bufferoffset = 0;
10517         rsurface.batchtvector3f = NULL;
10518         rsurface.batchtvector3f_vertexbuffer = NULL;
10519         rsurface.batchtvector3f_bufferoffset = 0;
10520         rsurface.batchnormal3f  = NULL;
10521         rsurface.batchnormal3f_vertexbuffer = NULL;
10522         rsurface.batchnormal3f_bufferoffset = 0;
10523         rsurface.batchlightmapcolor4f = NULL;
10524         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10525         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10526         rsurface.batchtexcoordtexture2f = NULL;
10527         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10528         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10529         rsurface.batchtexcoordlightmap2f = NULL;
10530         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10531         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10532         rsurface.batchvertexmesh = NULL;
10533         rsurface.batchvertexmeshbuffer = NULL;
10534         rsurface.batchvertex3fbuffer = NULL;
10535         rsurface.batchelement3i = NULL;
10536         rsurface.batchelement3i_indexbuffer = NULL;
10537         rsurface.batchelement3i_bufferoffset = 0;
10538         rsurface.batchelement3s = NULL;
10539         rsurface.batchelement3s_indexbuffer = NULL;
10540         rsurface.batchelement3s_bufferoffset = 0;
10541         rsurface.passcolor4f = NULL;
10542         rsurface.passcolor4f_vertexbuffer = NULL;
10543         rsurface.passcolor4f_bufferoffset = 0;
10544 }
10545
10546 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
10547 {
10548         dp_model_t *model = ent->model;
10549         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
10550         //      return;
10551         rsurface.entity = (entity_render_t *)ent;
10552         rsurface.skeleton = ent->skeleton;
10553         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
10554         rsurface.ent_skinnum = ent->skinnum;
10555         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;
10556         rsurface.ent_shadertime = ent->shadertime;
10557         rsurface.ent_flags = ent->flags;
10558         rsurface.matrix = ent->matrix;
10559         rsurface.inversematrix = ent->inversematrix;
10560         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10561         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10562         R_EntityMatrix(&rsurface.matrix);
10563         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10564         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10565         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10566         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10567         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10568         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10569         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
10570         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
10571         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
10572         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
10573         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
10574         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
10575         rsurface.colormod[3] = ent->alpha;
10576         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
10577         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
10578         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
10579         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10580         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10581         if (ent->model->brush.submodel && !prepass)
10582         {
10583                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
10584                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
10585         }
10586         if (model->surfmesh.isanimated && model->AnimateVertices && (rsurface.frameblend[0].lerp != 1 || rsurface.frameblend[0].subframe != 0))
10587         {
10588                 if (ent->animcache_vertex3f)
10589                 {
10590                         rsurface.modelvertex3f = ent->animcache_vertex3f;
10591                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
10592                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
10593                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
10594                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
10595                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
10596                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
10597                 }
10598                 else if (wanttangents)
10599                 {
10600                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10601                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10602                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10603                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10604                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
10605                         rsurface.modelvertexmesh = NULL;
10606                         rsurface.modelvertexmeshbuffer = NULL;
10607                         rsurface.modelvertex3fbuffer = NULL;
10608                 }
10609                 else if (wantnormals)
10610                 {
10611                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10612                         rsurface.modelsvector3f = NULL;
10613                         rsurface.modeltvector3f = NULL;
10614                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10615                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
10616                         rsurface.modelvertexmesh = NULL;
10617                         rsurface.modelvertexmeshbuffer = NULL;
10618                         rsurface.modelvertex3fbuffer = NULL;
10619                 }
10620                 else
10621                 {
10622                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
10623                         rsurface.modelsvector3f = NULL;
10624                         rsurface.modeltvector3f = NULL;
10625                         rsurface.modelnormal3f = NULL;
10626                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
10627                         rsurface.modelvertexmesh = NULL;
10628                         rsurface.modelvertexmeshbuffer = NULL;
10629                         rsurface.modelvertex3fbuffer = NULL;
10630                 }
10631                 rsurface.modelvertex3f_vertexbuffer = 0;
10632                 rsurface.modelvertex3f_bufferoffset = 0;
10633                 rsurface.modelsvector3f_vertexbuffer = 0;
10634                 rsurface.modelsvector3f_bufferoffset = 0;
10635                 rsurface.modeltvector3f_vertexbuffer = 0;
10636                 rsurface.modeltvector3f_bufferoffset = 0;
10637                 rsurface.modelnormal3f_vertexbuffer = 0;
10638                 rsurface.modelnormal3f_bufferoffset = 0;
10639                 rsurface.modelgeneratedvertex = true;
10640         }
10641         else
10642         {
10643                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
10644                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10645                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
10646                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
10647                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10648                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
10649                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
10650                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10651                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
10652                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
10653                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10654                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
10655                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
10656                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
10657                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
10658                 rsurface.modelgeneratedvertex = false;
10659         }
10660         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
10661         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10662         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
10663         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
10664         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10665         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
10666         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
10667         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
10668         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
10669         rsurface.modelelement3i = model->surfmesh.data_element3i;
10670         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
10671         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
10672         rsurface.modelelement3s = model->surfmesh.data_element3s;
10673         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
10674         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
10675         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
10676         rsurface.modelnumvertices = model->surfmesh.num_vertices;
10677         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
10678         rsurface.modelsurfaces = model->data_surfaces;
10679         rsurface.batchgeneratedvertex = false;
10680         rsurface.batchfirstvertex = 0;
10681         rsurface.batchnumvertices = 0;
10682         rsurface.batchfirsttriangle = 0;
10683         rsurface.batchnumtriangles = 0;
10684         rsurface.batchvertex3f  = NULL;
10685         rsurface.batchvertex3f_vertexbuffer = NULL;
10686         rsurface.batchvertex3f_bufferoffset = 0;
10687         rsurface.batchsvector3f = NULL;
10688         rsurface.batchsvector3f_vertexbuffer = NULL;
10689         rsurface.batchsvector3f_bufferoffset = 0;
10690         rsurface.batchtvector3f = NULL;
10691         rsurface.batchtvector3f_vertexbuffer = NULL;
10692         rsurface.batchtvector3f_bufferoffset = 0;
10693         rsurface.batchnormal3f  = NULL;
10694         rsurface.batchnormal3f_vertexbuffer = NULL;
10695         rsurface.batchnormal3f_bufferoffset = 0;
10696         rsurface.batchlightmapcolor4f = NULL;
10697         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10698         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10699         rsurface.batchtexcoordtexture2f = NULL;
10700         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10701         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10702         rsurface.batchtexcoordlightmap2f = NULL;
10703         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10704         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10705         rsurface.batchvertexmesh = NULL;
10706         rsurface.batchvertexmeshbuffer = NULL;
10707         rsurface.batchvertex3fbuffer = NULL;
10708         rsurface.batchelement3i = NULL;
10709         rsurface.batchelement3i_indexbuffer = NULL;
10710         rsurface.batchelement3i_bufferoffset = 0;
10711         rsurface.batchelement3s = NULL;
10712         rsurface.batchelement3s_indexbuffer = NULL;
10713         rsurface.batchelement3s_bufferoffset = 0;
10714         rsurface.passcolor4f = NULL;
10715         rsurface.passcolor4f_vertexbuffer = NULL;
10716         rsurface.passcolor4f_bufferoffset = 0;
10717 }
10718
10719 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)
10720 {
10721         rsurface.entity = r_refdef.scene.worldentity;
10722         rsurface.skeleton = NULL;
10723         rsurface.ent_skinnum = 0;
10724         rsurface.ent_qwskin = -1;
10725         rsurface.ent_shadertime = shadertime;
10726         rsurface.ent_flags = entflags;
10727         rsurface.modelnumvertices = numvertices;
10728         rsurface.modelnumtriangles = numtriangles;
10729         rsurface.matrix = *matrix;
10730         rsurface.inversematrix = *inversematrix;
10731         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
10732         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
10733         R_EntityMatrix(&rsurface.matrix);
10734         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
10735         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
10736         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
10737         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
10738         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
10739         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
10740         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
10741         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
10742         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
10743         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
10744         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
10745         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
10746         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);
10747         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
10748         rsurface.frameblend[0].lerp = 1;
10749         rsurface.ent_alttextures = false;
10750         rsurface.basepolygonfactor = r_refdef.polygonfactor;
10751         rsurface.basepolygonoffset = r_refdef.polygonoffset;
10752         if (wanttangents)
10753         {
10754                 rsurface.modelvertex3f = (float *)vertex3f;
10755                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10756                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10757                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10758         }
10759         else if (wantnormals)
10760         {
10761                 rsurface.modelvertex3f = (float *)vertex3f;
10762                 rsurface.modelsvector3f = NULL;
10763                 rsurface.modeltvector3f = NULL;
10764                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10765         }
10766         else
10767         {
10768                 rsurface.modelvertex3f = (float *)vertex3f;
10769                 rsurface.modelsvector3f = NULL;
10770                 rsurface.modeltvector3f = NULL;
10771                 rsurface.modelnormal3f = NULL;
10772         }
10773         rsurface.modelvertexmesh = NULL;
10774         rsurface.modelvertexmeshbuffer = NULL;
10775         rsurface.modelvertex3fbuffer = NULL;
10776         rsurface.modelvertex3f_vertexbuffer = 0;
10777         rsurface.modelvertex3f_bufferoffset = 0;
10778         rsurface.modelsvector3f_vertexbuffer = 0;
10779         rsurface.modelsvector3f_bufferoffset = 0;
10780         rsurface.modeltvector3f_vertexbuffer = 0;
10781         rsurface.modeltvector3f_bufferoffset = 0;
10782         rsurface.modelnormal3f_vertexbuffer = 0;
10783         rsurface.modelnormal3f_bufferoffset = 0;
10784         rsurface.modelgeneratedvertex = true;
10785         rsurface.modellightmapcolor4f  = (float *)color4f;
10786         rsurface.modellightmapcolor4f_vertexbuffer = 0;
10787         rsurface.modellightmapcolor4f_bufferoffset = 0;
10788         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
10789         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
10790         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
10791         rsurface.modeltexcoordlightmap2f  = NULL;
10792         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
10793         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
10794         rsurface.modelelement3i = (int *)element3i;
10795         rsurface.modelelement3i_indexbuffer = NULL;
10796         rsurface.modelelement3i_bufferoffset = 0;
10797         rsurface.modelelement3s = (unsigned short *)element3s;
10798         rsurface.modelelement3s_indexbuffer = NULL;
10799         rsurface.modelelement3s_bufferoffset = 0;
10800         rsurface.modellightmapoffsets = NULL;
10801         rsurface.modelsurfaces = NULL;
10802         rsurface.batchgeneratedvertex = false;
10803         rsurface.batchfirstvertex = 0;
10804         rsurface.batchnumvertices = 0;
10805         rsurface.batchfirsttriangle = 0;
10806         rsurface.batchnumtriangles = 0;
10807         rsurface.batchvertex3f  = NULL;
10808         rsurface.batchvertex3f_vertexbuffer = NULL;
10809         rsurface.batchvertex3f_bufferoffset = 0;
10810         rsurface.batchsvector3f = NULL;
10811         rsurface.batchsvector3f_vertexbuffer = NULL;
10812         rsurface.batchsvector3f_bufferoffset = 0;
10813         rsurface.batchtvector3f = NULL;
10814         rsurface.batchtvector3f_vertexbuffer = NULL;
10815         rsurface.batchtvector3f_bufferoffset = 0;
10816         rsurface.batchnormal3f  = NULL;
10817         rsurface.batchnormal3f_vertexbuffer = NULL;
10818         rsurface.batchnormal3f_bufferoffset = 0;
10819         rsurface.batchlightmapcolor4f = NULL;
10820         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
10821         rsurface.batchlightmapcolor4f_bufferoffset = 0;
10822         rsurface.batchtexcoordtexture2f = NULL;
10823         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10824         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10825         rsurface.batchtexcoordlightmap2f = NULL;
10826         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
10827         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
10828         rsurface.batchvertexmesh = NULL;
10829         rsurface.batchvertexmeshbuffer = NULL;
10830         rsurface.batchvertex3fbuffer = NULL;
10831         rsurface.batchelement3i = NULL;
10832         rsurface.batchelement3i_indexbuffer = NULL;
10833         rsurface.batchelement3i_bufferoffset = 0;
10834         rsurface.batchelement3s = NULL;
10835         rsurface.batchelement3s_indexbuffer = NULL;
10836         rsurface.batchelement3s_bufferoffset = 0;
10837         rsurface.passcolor4f = NULL;
10838         rsurface.passcolor4f_vertexbuffer = NULL;
10839         rsurface.passcolor4f_bufferoffset = 0;
10840
10841         if (rsurface.modelnumvertices && rsurface.modelelement3i)
10842         {
10843                 if ((wantnormals || wanttangents) && !normal3f)
10844                 {
10845                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10846                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
10847                 }
10848                 if (wanttangents && !svector3f)
10849                 {
10850                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10851                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
10852                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
10853                 }
10854         }
10855 }
10856
10857 float RSurf_FogPoint(const float *v)
10858 {
10859         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10860         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
10861         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
10862         float FogHeightFade = r_refdef.fogheightfade;
10863         float fogfrac;
10864         unsigned int fogmasktableindex;
10865         if (r_refdef.fogplaneviewabove)
10866                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10867         else
10868                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10869         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
10870         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10871 }
10872
10873 float RSurf_FogVertex(const float *v)
10874 {
10875         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
10876         float FogPlaneViewDist = rsurface.fogplaneviewdist;
10877         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
10878         float FogHeightFade = rsurface.fogheightfade;
10879         float fogfrac;
10880         unsigned int fogmasktableindex;
10881         if (r_refdef.fogplaneviewabove)
10882                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
10883         else
10884                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
10885         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
10886         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
10887 }
10888
10889 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
10890 {
10891         int i;
10892         for (i = 0;i < numelements;i++)
10893                 outelement3i[i] = inelement3i[i] + adjust;
10894 }
10895
10896 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
10897 extern cvar_t gl_vbo;
10898 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
10899 {
10900         int deformindex;
10901         int firsttriangle;
10902         int numtriangles;
10903         int firstvertex;
10904         int endvertex;
10905         int numvertices;
10906         int surfacefirsttriangle;
10907         int surfacenumtriangles;
10908         int surfacefirstvertex;
10909         int surfaceendvertex;
10910         int surfacenumvertices;
10911         int batchnumvertices;
10912         int batchnumtriangles;
10913         int needsupdate;
10914         int i, j;
10915         qboolean gaps;
10916         qboolean dynamicvertex;
10917         float amplitude;
10918         float animpos;
10919         float scale;
10920         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
10921         float waveparms[4];
10922         q3shaderinfo_deform_t *deform;
10923         const msurface_t *surface, *firstsurface;
10924         r_vertexmesh_t *vertexmesh;
10925         if (!texturenumsurfaces)
10926                 return;
10927         // find vertex range of this surface batch
10928         gaps = false;
10929         firstsurface = texturesurfacelist[0];
10930         firsttriangle = firstsurface->num_firsttriangle;
10931         batchnumvertices = 0;
10932         batchnumtriangles = 0;
10933         firstvertex = endvertex = firstsurface->num_firstvertex;
10934         for (i = 0;i < texturenumsurfaces;i++)
10935         {
10936                 surface = texturesurfacelist[i];
10937                 if (surface != firstsurface + i)
10938                         gaps = true;
10939                 surfacefirstvertex = surface->num_firstvertex;
10940                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
10941                 surfacenumvertices = surface->num_vertices;
10942                 surfacenumtriangles = surface->num_triangles;
10943                 if (firstvertex > surfacefirstvertex)
10944                         firstvertex = surfacefirstvertex;
10945                 if (endvertex < surfaceendvertex)
10946                         endvertex = surfaceendvertex;
10947                 batchnumvertices += surfacenumvertices;
10948                 batchnumtriangles += surfacenumtriangles;
10949         }
10950
10951         // we now know the vertex range used, and if there are any gaps in it
10952         rsurface.batchfirstvertex = firstvertex;
10953         rsurface.batchnumvertices = endvertex - firstvertex;
10954         rsurface.batchfirsttriangle = firsttriangle;
10955         rsurface.batchnumtriangles = batchnumtriangles;
10956
10957         // this variable holds flags for which properties have been updated that
10958         // may require regenerating vertexmesh array...
10959         needsupdate = 0;
10960
10961         // check if any dynamic vertex processing must occur
10962         dynamicvertex = false;
10963
10964         // if there is a chance of animated vertex colors, it's a dynamic batch
10965         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
10966         {
10967                 dynamicvertex = true;
10968                 batchneed |= BATCHNEED_NOGAPS;
10969                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
10970         }
10971
10972         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
10973         {
10974                 switch (deform->deform)
10975                 {
10976                 default:
10977                 case Q3DEFORM_PROJECTIONSHADOW:
10978                 case Q3DEFORM_TEXT0:
10979                 case Q3DEFORM_TEXT1:
10980                 case Q3DEFORM_TEXT2:
10981                 case Q3DEFORM_TEXT3:
10982                 case Q3DEFORM_TEXT4:
10983                 case Q3DEFORM_TEXT5:
10984                 case Q3DEFORM_TEXT6:
10985                 case Q3DEFORM_TEXT7:
10986                 case Q3DEFORM_NONE:
10987                         break;
10988                 case Q3DEFORM_AUTOSPRITE:
10989                         dynamicvertex = true;
10990                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10991                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10992                         break;
10993                 case Q3DEFORM_AUTOSPRITE2:
10994                         dynamicvertex = true;
10995                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
10996                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
10997                         break;
10998                 case Q3DEFORM_NORMAL:
10999                         dynamicvertex = true;
11000                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11001                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11002                         break;
11003                 case Q3DEFORM_WAVE:
11004                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11005                                 break; // if wavefunc is a nop, ignore this transform
11006                         dynamicvertex = true;
11007                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11008                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11009                         break;
11010                 case Q3DEFORM_BULGE:
11011                         dynamicvertex = true;
11012                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11013                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
11014                         break;
11015                 case Q3DEFORM_MOVE:
11016                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11017                                 break; // if wavefunc is a nop, ignore this transform
11018                         dynamicvertex = true;
11019                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11020                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
11021                         break;
11022                 }
11023         }
11024         switch(rsurface.texture->tcgen.tcgen)
11025         {
11026         default:
11027         case Q3TCGEN_TEXTURE:
11028                 break;
11029         case Q3TCGEN_LIGHTMAP:
11030                 dynamicvertex = true;
11031                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
11032                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
11033                 break;
11034         case Q3TCGEN_VECTOR:
11035                 dynamicvertex = true;
11036                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
11037                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11038                 break;
11039         case Q3TCGEN_ENVIRONMENT:
11040                 dynamicvertex = true;
11041                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
11042                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11043                 break;
11044         }
11045         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11046         {
11047                 dynamicvertex = true;
11048                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
11049                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
11050         }
11051
11052         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11053         {
11054                 dynamicvertex = true;
11055                 batchneed |= BATCHNEED_NOGAPS;
11056                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
11057         }
11058
11059         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
11060         {
11061                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
11062                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
11063                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
11064                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
11065                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
11066                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
11067                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
11068         }
11069
11070         // when the model data has no vertex buffer (dynamic mesh), we need to
11071         // eliminate gaps
11072         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
11073                 batchneed |= BATCHNEED_NOGAPS;
11074
11075         // if needsupdate, we have to do a dynamic vertex batch for sure
11076         if (needsupdate & batchneed)
11077                 dynamicvertex = true;
11078
11079         // see if we need to build vertexmesh from arrays
11080         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
11081                 dynamicvertex = true;
11082
11083         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
11084         // also some drivers strongly dislike firstvertex
11085         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
11086                 dynamicvertex = true;
11087
11088         rsurface.batchvertex3f = rsurface.modelvertex3f;
11089         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
11090         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
11091         rsurface.batchsvector3f = rsurface.modelsvector3f;
11092         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
11093         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
11094         rsurface.batchtvector3f = rsurface.modeltvector3f;
11095         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
11096         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
11097         rsurface.batchnormal3f = rsurface.modelnormal3f;
11098         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
11099         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
11100         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
11101         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
11102         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
11103         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
11104         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
11105         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
11106         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
11107         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
11108         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
11109         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
11110         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
11111         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
11112         rsurface.batchelement3i = rsurface.modelelement3i;
11113         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
11114         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
11115         rsurface.batchelement3s = rsurface.modelelement3s;
11116         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
11117         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
11118
11119         // if any dynamic vertex processing has to occur in software, we copy the
11120         // entire surface list together before processing to rebase the vertices
11121         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
11122         //
11123         // if any gaps exist and we do not have a static vertex buffer, we have to
11124         // copy the surface list together to avoid wasting upload bandwidth on the
11125         // vertices in the gaps.
11126         //
11127         // if gaps exist and we have a static vertex buffer, we still have to
11128         // combine the index buffer ranges into one dynamic index buffer.
11129         //
11130         // in all cases we end up with data that can be drawn in one call.
11131
11132         if (!dynamicvertex)
11133         {
11134                 // static vertex data, just set pointers...
11135                 rsurface.batchgeneratedvertex = false;
11136                 // if there are gaps, we want to build a combined index buffer,
11137                 // otherwise use the original static buffer with an appropriate offset
11138                 if (gaps)
11139                 {
11140                         // build a new triangle elements array for this batch
11141                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11142                         rsurface.batchfirsttriangle = 0;
11143                         numtriangles = 0;
11144                         for (i = 0;i < texturenumsurfaces;i++)
11145                         {
11146                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11147                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11148                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
11149                                 numtriangles += surfacenumtriangles;
11150                         }
11151                         rsurface.batchelement3i_indexbuffer = NULL;
11152                         rsurface.batchelement3i_bufferoffset = 0;
11153                         rsurface.batchelement3s = NULL;
11154                         rsurface.batchelement3s_indexbuffer = NULL;
11155                         rsurface.batchelement3s_bufferoffset = 0;
11156                         if (endvertex <= 65536)
11157                         {
11158                                 // make a 16bit (unsigned short) index array if possible
11159                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11160                                 for (i = 0;i < numtriangles*3;i++)
11161                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11162                         }
11163                 }
11164                 return;
11165         }
11166
11167         // something needs software processing, do it for real...
11168         // we only directly handle separate array data in this case and then
11169         // generate interleaved data if needed...
11170         rsurface.batchgeneratedvertex = true;
11171
11172         // now copy the vertex data into a combined array and make an index array
11173         // (this is what Quake3 does all the time)
11174         //if (gaps || rsurface.batchfirstvertex)
11175         {
11176                 rsurface.batchvertex3fbuffer = NULL;
11177                 rsurface.batchvertexmesh = NULL;
11178                 rsurface.batchvertexmeshbuffer = NULL;
11179                 rsurface.batchvertex3f = NULL;
11180                 rsurface.batchvertex3f_vertexbuffer = NULL;
11181                 rsurface.batchvertex3f_bufferoffset = 0;
11182                 rsurface.batchsvector3f = NULL;
11183                 rsurface.batchsvector3f_vertexbuffer = NULL;
11184                 rsurface.batchsvector3f_bufferoffset = 0;
11185                 rsurface.batchtvector3f = NULL;
11186                 rsurface.batchtvector3f_vertexbuffer = NULL;
11187                 rsurface.batchtvector3f_bufferoffset = 0;
11188                 rsurface.batchnormal3f = NULL;
11189                 rsurface.batchnormal3f_vertexbuffer = NULL;
11190                 rsurface.batchnormal3f_bufferoffset = 0;
11191                 rsurface.batchlightmapcolor4f = NULL;
11192                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11193                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11194                 rsurface.batchtexcoordtexture2f = NULL;
11195                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11196                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11197                 rsurface.batchtexcoordlightmap2f = NULL;
11198                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
11199                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
11200                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
11201                 rsurface.batchelement3i_indexbuffer = NULL;
11202                 rsurface.batchelement3i_bufferoffset = 0;
11203                 rsurface.batchelement3s = NULL;
11204                 rsurface.batchelement3s_indexbuffer = NULL;
11205                 rsurface.batchelement3s_bufferoffset = 0;
11206                 // we'll only be setting up certain arrays as needed
11207                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11208                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11209                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11210                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11211                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
11212                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11213                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
11214                 {
11215                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11216                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11217                 }
11218                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
11219                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11220                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
11221                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11222                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
11223                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11224                 numvertices = 0;
11225                 numtriangles = 0;
11226                 for (i = 0;i < texturenumsurfaces;i++)
11227                 {
11228                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
11229                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
11230                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
11231                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
11232                         // copy only the data requested
11233                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
11234                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
11235                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
11236                         {
11237                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
11238                                         memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11239                                 if ((batchneed & BATCHNEED_ARRAY_NORMAL) && rsurface.modelnormal3f)
11240                                         memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11241                                 if ((batchneed & BATCHNEED_ARRAY_VECTOR) && rsurface.modelsvector3f)
11242                                 {
11243                                         memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11244                                         memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
11245                                 }
11246                                 if ((batchneed & BATCHNEED_ARRAY_VERTEXCOLOR) && rsurface.modellightmapcolor4f)
11247                                         memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
11248                                 if ((batchneed & BATCHNEED_ARRAY_TEXCOORD) && rsurface.modeltexcoordtexture2f)
11249                                         memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11250                                 if ((batchneed & BATCHNEED_ARRAY_LIGHTMAP) && rsurface.modeltexcoordlightmap2f)
11251                                         memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
11252                         }
11253                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
11254                         numvertices += surfacenumvertices;
11255                         numtriangles += surfacenumtriangles;
11256                 }
11257
11258                 // generate a 16bit index array as well if possible
11259                 // (in general, dynamic batches fit)
11260                 if (numvertices <= 65536)
11261                 {
11262                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
11263                         for (i = 0;i < numtriangles*3;i++)
11264                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
11265                 }
11266
11267                 // since we've copied everything, the batch now starts at 0
11268                 rsurface.batchfirstvertex = 0;
11269                 rsurface.batchnumvertices = batchnumvertices;
11270                 rsurface.batchfirsttriangle = 0;
11271                 rsurface.batchnumtriangles = batchnumtriangles;
11272         }
11273
11274         // q1bsp surfaces rendered in vertex color mode have to have colors
11275         // calculated based on lightstyles
11276         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
11277         {
11278                 // generate color arrays for the surfaces in this list
11279                 int c[4];
11280                 int scale;
11281                 int size3;
11282                 const int *offsets;
11283                 const unsigned char *lm;
11284                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
11285                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
11286                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
11287                 numvertices = 0;
11288                 for (i = 0;i < texturenumsurfaces;i++)
11289                 {
11290                         surface = texturesurfacelist[i];
11291                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
11292                         surfacenumvertices = surface->num_vertices;
11293                         if (surface->lightmapinfo->samples)
11294                         {
11295                                 for (j = 0;j < surfacenumvertices;j++)
11296                                 {
11297                                         lm = surface->lightmapinfo->samples + offsets[j];
11298                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
11299                                         VectorScale(lm, scale, c);
11300                                         if (surface->lightmapinfo->styles[1] != 255)
11301                                         {
11302                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
11303                                                 lm += size3;
11304                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
11305                                                 VectorMA(c, scale, lm, c);
11306                                                 if (surface->lightmapinfo->styles[2] != 255)
11307                                                 {
11308                                                         lm += size3;
11309                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
11310                                                         VectorMA(c, scale, lm, c);
11311                                                         if (surface->lightmapinfo->styles[3] != 255)
11312                                                         {
11313                                                                 lm += size3;
11314                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
11315                                                                 VectorMA(c, scale, lm, c);
11316                                                         }
11317                                                 }
11318                                         }
11319                                         c[0] >>= 7;
11320                                         c[1] >>= 7;
11321                                         c[2] >>= 7;
11322                                         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);
11323                                         numvertices++;
11324                                 }
11325                         }
11326                         else
11327                         {
11328                                 for (j = 0;j < surfacenumvertices;j++)
11329                                 {
11330                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
11331                                         numvertices++;
11332                                 }
11333                         }
11334                 }
11335         }
11336
11337         // if vertices are deformed (sprite flares and things in maps, possibly
11338         // water waves, bulges and other deformations), modify the copied vertices
11339         // in place
11340         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform;deformindex++, deform++)
11341         {
11342                 switch (deform->deform)
11343                 {
11344                 default:
11345                 case Q3DEFORM_PROJECTIONSHADOW:
11346                 case Q3DEFORM_TEXT0:
11347                 case Q3DEFORM_TEXT1:
11348                 case Q3DEFORM_TEXT2:
11349                 case Q3DEFORM_TEXT3:
11350                 case Q3DEFORM_TEXT4:
11351                 case Q3DEFORM_TEXT5:
11352                 case Q3DEFORM_TEXT6:
11353                 case Q3DEFORM_TEXT7:
11354                 case Q3DEFORM_NONE:
11355                         break;
11356                 case Q3DEFORM_AUTOSPRITE:
11357                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11358                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11359                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11360                         VectorNormalize(newforward);
11361                         VectorNormalize(newright);
11362                         VectorNormalize(newup);
11363 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11364 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11365 //                      rsurface.batchvertex3f_bufferoffset = 0;
11366 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
11367 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
11368 //                      rsurface.batchsvector3f_bufferoffset = 0;
11369 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
11370 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
11371 //                      rsurface.batchtvector3f_bufferoffset = 0;
11372 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11373 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11374 //                      rsurface.batchnormal3f_bufferoffset = 0;
11375                         // a single autosprite surface can contain multiple sprites...
11376                         for (j = 0;j < batchnumvertices - 3;j += 4)
11377                         {
11378                                 VectorClear(center);
11379                                 for (i = 0;i < 4;i++)
11380                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11381                                 VectorScale(center, 0.25f, center);
11382                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
11383                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
11384                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
11385                                 for (i = 0;i < 4;i++)
11386                                 {
11387                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
11388                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
11389                                 }
11390                         }
11391                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
11392                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11393                         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);
11394                         break;
11395                 case Q3DEFORM_AUTOSPRITE2:
11396                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
11397                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
11398                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
11399                         VectorNormalize(newforward);
11400                         VectorNormalize(newright);
11401                         VectorNormalize(newup);
11402 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11403 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11404 //                      rsurface.batchvertex3f_bufferoffset = 0;
11405                         {
11406                                 const float *v1, *v2;
11407                                 vec3_t start, end;
11408                                 float f, l;
11409                                 struct
11410                                 {
11411                                         float length2;
11412                                         const float *v1;
11413                                         const float *v2;
11414                                 }
11415                                 shortest[2];
11416                                 memset(shortest, 0, sizeof(shortest));
11417                                 // a single autosprite surface can contain multiple sprites...
11418                                 for (j = 0;j < batchnumvertices - 3;j += 4)
11419                                 {
11420                                         VectorClear(center);
11421                                         for (i = 0;i < 4;i++)
11422                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
11423                                         VectorScale(center, 0.25f, center);
11424                                         // find the two shortest edges, then use them to define the
11425                                         // axis vectors for rotating around the central axis
11426                                         for (i = 0;i < 6;i++)
11427                                         {
11428                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
11429                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
11430                                                 l = VectorDistance2(v1, v2);
11431                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
11432                                                 if (v1[2] != v2[2])
11433                                                         l += (1.0f / 1024.0f);
11434                                                 if (shortest[0].length2 > l || i == 0)
11435                                                 {
11436                                                         shortest[1] = shortest[0];
11437                                                         shortest[0].length2 = l;
11438                                                         shortest[0].v1 = v1;
11439                                                         shortest[0].v2 = v2;
11440                                                 }
11441                                                 else if (shortest[1].length2 > l || i == 1)
11442                                                 {
11443                                                         shortest[1].length2 = l;
11444                                                         shortest[1].v1 = v1;
11445                                                         shortest[1].v2 = v2;
11446                                                 }
11447                                         }
11448                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
11449                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
11450                                         // this calculates the right vector from the shortest edge
11451                                         // and the up vector from the edge midpoints
11452                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
11453                                         VectorNormalize(right);
11454                                         VectorSubtract(end, start, up);
11455                                         VectorNormalize(up);
11456                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
11457                                         VectorSubtract(rsurface.localvieworigin, center, forward);
11458                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
11459                                         VectorNegate(forward, forward);
11460                                         VectorReflect(forward, 0, up, forward);
11461                                         VectorNormalize(forward);
11462                                         CrossProduct(up, forward, newright);
11463                                         VectorNormalize(newright);
11464                                         // rotate the quad around the up axis vector, this is made
11465                                         // especially easy by the fact we know the quad is flat,
11466                                         // so we only have to subtract the center position and
11467                                         // measure distance along the right vector, and then
11468                                         // multiply that by the newright vector and add back the
11469                                         // center position
11470                                         // we also need to subtract the old position to undo the
11471                                         // displacement from the center, which we do with a
11472                                         // DotProduct, the subtraction/addition of center is also
11473                                         // optimized into DotProducts here
11474                                         l = DotProduct(right, center);
11475                                         for (i = 0;i < 4;i++)
11476                                         {
11477                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
11478                                                 f = DotProduct(right, v1) - l;
11479                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
11480                                         }
11481                                 }
11482                         }
11483                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
11484                         {
11485 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11486 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
11487 //                              rsurface.batchnormal3f_bufferoffset = 0;
11488                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11489                         }
11490                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11491                         {
11492 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11493 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11494 //                              rsurface.batchsvector3f_bufferoffset = 0;
11495 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11496 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11497 //                              rsurface.batchtvector3f_bufferoffset = 0;
11498                                 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);
11499                         }
11500                         break;
11501                 case Q3DEFORM_NORMAL:
11502                         // deform the normals to make reflections wavey
11503                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11504                         rsurface.batchnormal3f_vertexbuffer = NULL;
11505                         rsurface.batchnormal3f_bufferoffset = 0;
11506                         for (j = 0;j < batchnumvertices;j++)
11507                         {
11508                                 float vertex[3];
11509                                 float *normal = rsurface.batchnormal3f + 3*j;
11510                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
11511                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], r_refdef.scene.time * deform->parms[1]);
11512                                 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]);
11513                                 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]);
11514                                 VectorNormalize(normal);
11515                         }
11516                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11517                         {
11518 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11519 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11520 //                              rsurface.batchsvector3f_bufferoffset = 0;
11521 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11522 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11523 //                              rsurface.batchtvector3f_bufferoffset = 0;
11524                                 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);
11525                         }
11526                         break;
11527                 case Q3DEFORM_WAVE:
11528                         // deform vertex array to make wavey water and flags and such
11529                         waveparms[0] = deform->waveparms[0];
11530                         waveparms[1] = deform->waveparms[1];
11531                         waveparms[2] = deform->waveparms[2];
11532                         waveparms[3] = deform->waveparms[3];
11533                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
11534                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11535                         // this is how a divisor of vertex influence on deformation
11536                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
11537                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11538 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11539 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11540 //                      rsurface.batchvertex3f_bufferoffset = 0;
11541 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11542 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11543 //                      rsurface.batchnormal3f_bufferoffset = 0;
11544                         for (j = 0;j < batchnumvertices;j++)
11545                         {
11546                                 // if the wavefunc depends on time, evaluate it per-vertex
11547                                 if (waveparms[3])
11548                                 {
11549                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
11550                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
11551                                 }
11552                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11553                         }
11554                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11555                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11556                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11557                         {
11558 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11559 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11560 //                              rsurface.batchsvector3f_bufferoffset = 0;
11561 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11562 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11563 //                              rsurface.batchtvector3f_bufferoffset = 0;
11564                                 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);
11565                         }
11566                         break;
11567                 case Q3DEFORM_BULGE:
11568                         // deform vertex array to make the surface have moving bulges
11569 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11570 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11571 //                      rsurface.batchvertex3f_bufferoffset = 0;
11572 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
11573 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
11574 //                      rsurface.batchnormal3f_bufferoffset = 0;
11575                         for (j = 0;j < batchnumvertices;j++)
11576                         {
11577                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + r_refdef.scene.time * deform->parms[2]) * deform->parms[1];
11578                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
11579                         }
11580                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
11581                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
11582                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
11583                         {
11584 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11585 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
11586 //                              rsurface.batchsvector3f_bufferoffset = 0;
11587 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
11588 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
11589 //                              rsurface.batchtvector3f_bufferoffset = 0;
11590                                 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);
11591                         }
11592                         break;
11593                 case Q3DEFORM_MOVE:
11594                         // deform vertex array
11595                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
11596                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
11597                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
11598                         VectorScale(deform->parms, scale, waveparms);
11599 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
11600 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
11601 //                      rsurface.batchvertex3f_bufferoffset = 0;
11602                         for (j = 0;j < batchnumvertices;j++)
11603                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
11604                         break;
11605                 }
11606         }
11607
11608         // generate texcoords based on the chosen texcoord source
11609         switch(rsurface.texture->tcgen.tcgen)
11610         {
11611         default:
11612         case Q3TCGEN_TEXTURE:
11613                 break;
11614         case Q3TCGEN_LIGHTMAP:
11615 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11616 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11617 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11618                 if (rsurface.batchtexcoordlightmap2f)
11619                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
11620                 break;
11621         case Q3TCGEN_VECTOR:
11622 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11623 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11624 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11625                 for (j = 0;j < batchnumvertices;j++)
11626                 {
11627                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
11628                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
11629                 }
11630                 break;
11631         case Q3TCGEN_ENVIRONMENT:
11632                 // make environment reflections using a spheremap
11633                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11634                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11635                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11636                 for (j = 0;j < batchnumvertices;j++)
11637                 {
11638                         // identical to Q3A's method, but executed in worldspace so
11639                         // carried models can be shiny too
11640
11641                         float viewer[3], d, reflected[3], worldreflected[3];
11642
11643                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
11644                         // VectorNormalize(viewer);
11645
11646                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
11647
11648                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
11649                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
11650                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
11651                         // note: this is proportinal to viewer, so we can normalize later
11652
11653                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
11654                         VectorNormalize(worldreflected);
11655
11656                         // note: this sphere map only uses world x and z!
11657                         // so positive and negative y will LOOK THE SAME.
11658                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
11659                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
11660                 }
11661                 break;
11662         }
11663         // the only tcmod that needs software vertex processing is turbulent, so
11664         // check for it here and apply the changes if needed
11665         // and we only support that as the first one
11666         // (handling a mixture of turbulent and other tcmods would be problematic
11667         //  without punting it entirely to a software path)
11668         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
11669         {
11670                 amplitude = rsurface.texture->tcmods[0].parms[1];
11671                 animpos = rsurface.texture->tcmods[0].parms[2] + r_refdef.scene.time * rsurface.texture->tcmods[0].parms[3];
11672 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
11673 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
11674 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
11675                 for (j = 0;j < batchnumvertices;j++)
11676                 {
11677                         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);
11678                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
11679                 }
11680         }
11681
11682         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
11683         {
11684                 // convert the modified arrays to vertex structs
11685 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
11686 //              rsurface.batchvertexmeshbuffer = NULL;
11687                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
11688                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11689                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
11690                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
11691                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11692                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
11693                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
11694                 {
11695                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11696                         {
11697                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
11698                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
11699                         }
11700                 }
11701                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
11702                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11703                                 Vector4Scale(rsurface.batchlightmapcolor4f + 4*j, 255.0f, vertexmesh->color4ub);
11704                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
11705                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11706                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
11707                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
11708                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
11709                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
11710         }
11711 }
11712
11713 void RSurf_DrawBatch(void)
11714 {
11715         // sometimes a zero triangle surface (usually a degenerate patch) makes it
11716         // through the pipeline, killing it earlier in the pipeline would have
11717         // per-surface overhead rather than per-batch overhead, so it's best to
11718         // reject it here, before it hits glDraw.
11719         if (rsurface.batchnumtriangles == 0)
11720                 return;
11721 #if 0
11722         // batch debugging code
11723         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
11724         {
11725                 int i;
11726                 int j;
11727                 int c;
11728                 const int *e;
11729                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
11730                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
11731                 {
11732                         c = e[i];
11733                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
11734                         {
11735                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
11736                                 {
11737                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
11738                                                 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);
11739                                         break;
11740                                 }
11741                         }
11742                 }
11743         }
11744 #endif
11745         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);
11746 }
11747
11748 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
11749 {
11750         // pick the closest matching water plane
11751         int planeindex, vertexindex, bestplaneindex = -1;
11752         float d, bestd;
11753         vec3_t vert;
11754         const float *v;
11755         r_waterstate_waterplane_t *p;
11756         qboolean prepared = false;
11757         bestd = 0;
11758         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
11759         {
11760                 if(p->camera_entity != rsurface.texture->camera_entity)
11761                         continue;
11762                 d = 0;
11763                 if(!prepared)
11764                 {
11765                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11766                         prepared = true;
11767                         if(rsurface.batchnumvertices == 0)
11768                                 break;
11769                 }
11770                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
11771                 {
11772                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
11773                         d += fabs(PlaneDiff(vert, &p->plane));
11774                 }
11775                 if (bestd > d || bestplaneindex < 0)
11776                 {
11777                         bestd = d;
11778                         bestplaneindex = planeindex;
11779                 }
11780         }
11781         return bestplaneindex;
11782         // NOTE: this MAY return a totally unrelated water plane; we can ignore
11783         // this situation though, as it might be better to render single larger
11784         // batches with useless stuff (backface culled for example) than to
11785         // render multiple smaller batches
11786 }
11787
11788 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
11789 {
11790         int i;
11791         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11792         rsurface.passcolor4f_vertexbuffer = 0;
11793         rsurface.passcolor4f_bufferoffset = 0;
11794         for (i = 0;i < rsurface.batchnumvertices;i++)
11795                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
11796 }
11797
11798 static void RSurf_DrawBatch_GL11_ApplyFog(void)
11799 {
11800         int i;
11801         float f;
11802         const float *v;
11803         const float *c;
11804         float *c2;
11805         if (rsurface.passcolor4f)
11806         {
11807                 // generate color arrays
11808                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11809                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11810                 rsurface.passcolor4f_vertexbuffer = 0;
11811                 rsurface.passcolor4f_bufferoffset = 0;
11812                 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)
11813                 {
11814                         f = RSurf_FogVertex(v);
11815                         c2[0] = c[0] * f;
11816                         c2[1] = c[1] * f;
11817                         c2[2] = c[2] * f;
11818                         c2[3] = c[3];
11819                 }
11820         }
11821         else
11822         {
11823                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11824                 rsurface.passcolor4f_vertexbuffer = 0;
11825                 rsurface.passcolor4f_bufferoffset = 0;
11826                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
11827                 {
11828                         f = RSurf_FogVertex(v);
11829                         c2[0] = f;
11830                         c2[1] = f;
11831                         c2[2] = f;
11832                         c2[3] = 1;
11833                 }
11834         }
11835 }
11836
11837 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
11838 {
11839         int i;
11840         float f;
11841         const float *v;
11842         const float *c;
11843         float *c2;
11844         if (!rsurface.passcolor4f)
11845                 return;
11846         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11847         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11848         rsurface.passcolor4f_vertexbuffer = 0;
11849         rsurface.passcolor4f_bufferoffset = 0;
11850         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)
11851         {
11852                 f = RSurf_FogVertex(v);
11853                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
11854                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
11855                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
11856                 c2[3] = c[3];
11857         }
11858 }
11859
11860 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
11861 {
11862         int i;
11863         const float *c;
11864         float *c2;
11865         if (!rsurface.passcolor4f)
11866                 return;
11867         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11868         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11869         rsurface.passcolor4f_vertexbuffer = 0;
11870         rsurface.passcolor4f_bufferoffset = 0;
11871         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11872         {
11873                 c2[0] = c[0] * r;
11874                 c2[1] = c[1] * g;
11875                 c2[2] = c[2] * b;
11876                 c2[3] = c[3] * a;
11877         }
11878 }
11879
11880 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
11881 {
11882         int i;
11883         const float *c;
11884         float *c2;
11885         if (!rsurface.passcolor4f)
11886                 return;
11887         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
11888         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11889         rsurface.passcolor4f_vertexbuffer = 0;
11890         rsurface.passcolor4f_bufferoffset = 0;
11891         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
11892         {
11893                 c2[0] = c[0] + r_refdef.scene.ambient;
11894                 c2[1] = c[1] + r_refdef.scene.ambient;
11895                 c2[2] = c[2] + r_refdef.scene.ambient;
11896                 c2[3] = c[3];
11897         }
11898 }
11899
11900 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11901 {
11902         // TODO: optimize
11903         rsurface.passcolor4f = NULL;
11904         rsurface.passcolor4f_vertexbuffer = 0;
11905         rsurface.passcolor4f_bufferoffset = 0;
11906         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11907         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11908         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11909         GL_Color(r, g, b, a);
11910         R_Mesh_TexBind(0, rsurface.lightmaptexture);
11911         RSurf_DrawBatch();
11912 }
11913
11914 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11915 {
11916         // TODO: optimize applyfog && applycolor case
11917         // just apply fog if necessary, and tint the fog color array if necessary
11918         rsurface.passcolor4f = NULL;
11919         rsurface.passcolor4f_vertexbuffer = 0;
11920         rsurface.passcolor4f_bufferoffset = 0;
11921         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11922         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11923         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11924         GL_Color(r, g, b, a);
11925         RSurf_DrawBatch();
11926 }
11927
11928 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11929 {
11930         // TODO: optimize
11931         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11932         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11933         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11934         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11935         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11936         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11937         GL_Color(r, g, b, a);
11938         RSurf_DrawBatch();
11939 }
11940
11941 static void RSurf_DrawBatch_GL11_ClampColor(void)
11942 {
11943         int i;
11944         const float *c1;
11945         float *c2;
11946         if (!rsurface.passcolor4f)
11947                 return;
11948         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
11949         {
11950                 c2[0] = bound(0.0f, c1[0], 1.0f);
11951                 c2[1] = bound(0.0f, c1[1], 1.0f);
11952                 c2[2] = bound(0.0f, c1[2], 1.0f);
11953                 c2[3] = bound(0.0f, c1[3], 1.0f);
11954         }
11955 }
11956
11957 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
11958 {
11959         int i;
11960         float f;
11961         const float *v;
11962         const float *n;
11963         float *c;
11964         //vec3_t eyedir;
11965
11966         // fake shading
11967         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
11968         rsurface.passcolor4f_vertexbuffer = 0;
11969         rsurface.passcolor4f_bufferoffset = 0;
11970         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)
11971         {
11972                 f = -DotProduct(r_refdef.view.forward, n);
11973                 f = max(0, f);
11974                 f = f * 0.85 + 0.15; // work around so stuff won't get black
11975                 f *= r_refdef.lightmapintensity;
11976                 Vector4Set(c, f, f, f, 1);
11977         }
11978 }
11979
11980 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
11981 {
11982         RSurf_DrawBatch_GL11_ApplyFakeLight();
11983         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
11984         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
11985         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
11986         GL_Color(r, g, b, a);
11987         RSurf_DrawBatch();
11988 }
11989
11990 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
11991 {
11992         int i;
11993         float f;
11994         float alpha;
11995         const float *v;
11996         const float *n;
11997         float *c;
11998         vec3_t ambientcolor;
11999         vec3_t diffusecolor;
12000         vec3_t lightdir;
12001         // TODO: optimize
12002         // model lighting
12003         VectorCopy(rsurface.modellight_lightdir, lightdir);
12004         f = 0.5f * r_refdef.lightmapintensity;
12005         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
12006         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
12007         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
12008         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
12009         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
12010         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
12011         alpha = *a;
12012         if (VectorLength2(diffusecolor) > 0)
12013         {
12014                 // q3-style directional shading
12015                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
12016                 rsurface.passcolor4f_vertexbuffer = 0;
12017                 rsurface.passcolor4f_bufferoffset = 0;
12018                 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)
12019                 {
12020                         if ((f = DotProduct(n, lightdir)) > 0)
12021                                 VectorMA(ambientcolor, f, diffusecolor, c);
12022                         else
12023                                 VectorCopy(ambientcolor, c);
12024                         c[3] = alpha;
12025                 }
12026                 *r = 1;
12027                 *g = 1;
12028                 *b = 1;
12029                 *a = 1;
12030                 *applycolor = false;
12031         }
12032         else
12033         {
12034                 *r = ambientcolor[0];
12035                 *g = ambientcolor[1];
12036                 *b = ambientcolor[2];
12037                 rsurface.passcolor4f = NULL;
12038                 rsurface.passcolor4f_vertexbuffer = 0;
12039                 rsurface.passcolor4f_bufferoffset = 0;
12040         }
12041 }
12042
12043 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
12044 {
12045         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
12046         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
12047         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
12048         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
12049         GL_Color(r, g, b, a);
12050         RSurf_DrawBatch();
12051 }
12052
12053 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
12054 {
12055         int i;
12056         float f;
12057         const float *v;
12058         float *c;
12059         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
12060         {
12061                 f = 1 - RSurf_FogVertex(v);
12062                 c[0] = r;
12063                 c[1] = g;
12064                 c[2] = b;
12065                 c[3] = f * a;
12066         }
12067 }
12068
12069 void RSurf_SetupDepthAndCulling(void)
12070 {
12071         // submodels are biased to avoid z-fighting with world surfaces that they
12072         // may be exactly overlapping (avoids z-fighting artifacts on certain
12073         // doors and things in Quake maps)
12074         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
12075         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
12076         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
12077         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12078 }
12079
12080 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12081 {
12082         // transparent sky would be ridiculous
12083         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12084                 return;
12085         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12086         skyrenderlater = true;
12087         RSurf_SetupDepthAndCulling();
12088         GL_DepthMask(true);
12089         // LordHavoc: HalfLife maps have freaky skypolys so don't use
12090         // skymasking on them, and Quake3 never did sky masking (unlike
12091         // software Quake and software Quake2), so disable the sky masking
12092         // in Quake3 maps as it causes problems with q3map2 sky tricks,
12093         // and skymasking also looks very bad when noclipping outside the
12094         // level, so don't use it then either.
12095         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis)
12096         {
12097                 R_Mesh_ResetTextureState();
12098                 if (skyrendermasked)
12099                 {
12100                         R_SetupShader_DepthOrShadow();
12101                         // depth-only (masking)
12102                         GL_ColorMask(0,0,0,0);
12103                         // just to make sure that braindead drivers don't draw
12104                         // anything despite that colormask...
12105                         GL_BlendFunc(GL_ZERO, GL_ONE);
12106                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12107                         if (rsurface.batchvertex3fbuffer)
12108                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12109                         else
12110                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12111                 }
12112                 else
12113                 {
12114                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12115                         // fog sky
12116                         GL_BlendFunc(GL_ONE, GL_ZERO);
12117                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12118                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
12119                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12120                 }
12121                 RSurf_DrawBatch();
12122                 if (skyrendermasked)
12123                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12124         }
12125         R_Mesh_ResetTextureState();
12126         GL_Color(1, 1, 1, 1);
12127 }
12128
12129 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
12130 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
12131 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12132 {
12133         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
12134                 return;
12135         if (prepass)
12136         {
12137                 // render screenspace normalmap to texture
12138                 GL_DepthMask(true);
12139                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL);
12140                 RSurf_DrawBatch();
12141                 return;
12142         }
12143
12144         // bind lightmap texture
12145
12146         // water/refraction/reflection/camera surfaces have to be handled specially
12147         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
12148         {
12149                 int start, end, startplaneindex;
12150                 for (start = 0;start < texturenumsurfaces;start = end)
12151                 {
12152                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
12153                         if(startplaneindex < 0)
12154                         {
12155                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
12156                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
12157                                 end = start + 1;
12158                                 continue;
12159                         }
12160                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
12161                                 ;
12162                         // now that we have a batch using the same planeindex, render it
12163                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
12164                         {
12165                                 // render water or distortion background
12166                                 GL_DepthMask(true);
12167                                 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));
12168                                 RSurf_DrawBatch();
12169                                 // blend surface on top
12170                                 GL_DepthMask(false);
12171                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL);
12172                                 RSurf_DrawBatch();
12173                         }
12174                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
12175                         {
12176                                 // render surface with reflection texture as input
12177                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12178                                 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));
12179                                 RSurf_DrawBatch();
12180                         }
12181                 }
12182                 return;
12183         }
12184
12185         // render surface batch normally
12186         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
12187         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL);
12188         RSurf_DrawBatch();
12189 }
12190
12191 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12192 {
12193         // OpenGL 1.3 path - anything not completely ancient
12194         qboolean applycolor;
12195         qboolean applyfog;
12196         int layerindex;
12197         const texturelayer_t *layer;
12198         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);
12199         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12200
12201         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12202         {
12203                 vec4_t layercolor;
12204                 int layertexrgbscale;
12205                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12206                 {
12207                         if (layerindex == 0)
12208                                 GL_AlphaTest(true);
12209                         else
12210                         {
12211                                 GL_AlphaTest(false);
12212                                 GL_DepthFunc(GL_EQUAL);
12213                         }
12214                 }
12215                 GL_DepthMask(layer->depthmask && writedepth);
12216                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12217                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
12218                 {
12219                         layertexrgbscale = 4;
12220                         VectorScale(layer->color, 0.25f, layercolor);
12221                 }
12222                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
12223                 {
12224                         layertexrgbscale = 2;
12225                         VectorScale(layer->color, 0.5f, layercolor);
12226                 }
12227                 else
12228                 {
12229                         layertexrgbscale = 1;
12230                         VectorScale(layer->color, 1.0f, layercolor);
12231                 }
12232                 layercolor[3] = layer->color[3];
12233                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
12234                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12235                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12236                 switch (layer->type)
12237                 {
12238                 case TEXTURELAYERTYPE_LITTEXTURE:
12239                         // single-pass lightmapped texture with 2x rgbscale
12240                         R_Mesh_TexBind(0, r_texture_white);
12241                         R_Mesh_TexMatrix(0, NULL);
12242                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12243                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12244                         R_Mesh_TexBind(1, layer->texture);
12245                         R_Mesh_TexMatrix(1, &layer->texmatrix);
12246                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12247                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12248                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12249                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12250                         else if (FAKELIGHT_ENABLED)
12251                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12252                         else if (rsurface.uselightmaptexture)
12253                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12254                         else
12255                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12256                         break;
12257                 case TEXTURELAYERTYPE_TEXTURE:
12258                         // singletexture unlit texture with transparency support
12259                         R_Mesh_TexBind(0, layer->texture);
12260                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12261                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12262                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12263                         R_Mesh_TexBind(1, 0);
12264                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12265                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
12266                         break;
12267                 case TEXTURELAYERTYPE_FOG:
12268                         // singletexture fogging
12269                         if (layer->texture)
12270                         {
12271                                 R_Mesh_TexBind(0, layer->texture);
12272                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12273                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
12274                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12275                         }
12276                         else
12277                         {
12278                                 R_Mesh_TexBind(0, 0);
12279                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12280                         }
12281                         R_Mesh_TexBind(1, 0);
12282                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12283                         // generate a color array for the fog pass
12284                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12285                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
12286                         RSurf_DrawBatch();
12287                         break;
12288                 default:
12289                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12290                 }
12291         }
12292         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12293         {
12294                 GL_DepthFunc(GL_LEQUAL);
12295                 GL_AlphaTest(false);
12296         }
12297 }
12298
12299 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12300 {
12301         // OpenGL 1.1 - crusty old voodoo path
12302         qboolean applyfog;
12303         int layerindex;
12304         const texturelayer_t *layer;
12305         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);
12306         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
12307
12308         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
12309         {
12310                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12311                 {
12312                         if (layerindex == 0)
12313                                 GL_AlphaTest(true);
12314                         else
12315                         {
12316                                 GL_AlphaTest(false);
12317                                 GL_DepthFunc(GL_EQUAL);
12318                         }
12319                 }
12320                 GL_DepthMask(layer->depthmask && writedepth);
12321                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
12322                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
12323                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
12324                 switch (layer->type)
12325                 {
12326                 case TEXTURELAYERTYPE_LITTEXTURE:
12327                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
12328                         {
12329                                 // two-pass lit texture with 2x rgbscale
12330                                 // first the lightmap pass
12331                                 R_Mesh_TexBind(0, r_texture_white);
12332                                 R_Mesh_TexMatrix(0, NULL);
12333                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12334                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
12335                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12336                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
12337                                 else if (FAKELIGHT_ENABLED)
12338                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
12339                                 else if (rsurface.uselightmaptexture)
12340                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
12341                                 else
12342                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
12343                                 // then apply the texture to it
12344                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
12345                                 R_Mesh_TexBind(0, layer->texture);
12346                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12347                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12348                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12349                                 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);
12350                         }
12351                         else
12352                         {
12353                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
12354                                 R_Mesh_TexBind(0, layer->texture);
12355                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12356                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12357                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12358                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12359                                         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);
12360                                 else
12361                                         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);
12362                         }
12363                         break;
12364                 case TEXTURELAYERTYPE_TEXTURE:
12365                         // singletexture unlit texture with transparency support
12366                         R_Mesh_TexBind(0, layer->texture);
12367                         R_Mesh_TexMatrix(0, &layer->texmatrix);
12368                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12369                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12370                         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);
12371                         break;
12372                 case TEXTURELAYERTYPE_FOG:
12373                         // singletexture fogging
12374                         if (layer->texture)
12375                         {
12376                                 R_Mesh_TexBind(0, layer->texture);
12377                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
12378                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
12379                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
12380                         }
12381                         else
12382                         {
12383                                 R_Mesh_TexBind(0, 0);
12384                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
12385                         }
12386                         // generate a color array for the fog pass
12387                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
12388                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
12389                         RSurf_DrawBatch();
12390                         break;
12391                 default:
12392                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
12393                 }
12394         }
12395         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12396         {
12397                 GL_DepthFunc(GL_LEQUAL);
12398                 GL_AlphaTest(false);
12399         }
12400 }
12401
12402 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
12403 {
12404         int vi;
12405         int j;
12406         r_vertexgeneric_t *batchvertex;
12407         float c[4];
12408
12409 //      R_Mesh_ResetTextureState();
12410         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12411
12412         if(rsurface.texture && rsurface.texture->currentskinframe)
12413         {
12414                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
12415                 c[3] *= rsurface.texture->currentalpha;
12416         }
12417         else
12418         {
12419                 c[0] = 1;
12420                 c[1] = 0;
12421                 c[2] = 1;
12422                 c[3] = 1;
12423         }
12424
12425         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
12426         {
12427                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
12428                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
12429                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
12430         }
12431
12432         // brighten it up (as texture value 127 means "unlit")
12433         c[0] *= 2 * r_refdef.view.colorscale;
12434         c[1] *= 2 * r_refdef.view.colorscale;
12435         c[2] *= 2 * r_refdef.view.colorscale;
12436
12437         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
12438                 c[3] *= r_wateralpha.value;
12439
12440         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
12441         {
12442                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12443                 GL_DepthMask(false);
12444         }
12445         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
12446         {
12447                 GL_BlendFunc(GL_ONE, GL_ONE);
12448                 GL_DepthMask(false);
12449         }
12450         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
12451         {
12452                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
12453                 GL_DepthMask(false);
12454         }
12455         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
12456         {
12457                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
12458                 GL_DepthMask(false);
12459         }
12460         else
12461         {
12462                 GL_BlendFunc(GL_ONE, GL_ZERO);
12463                 GL_DepthMask(writedepth);
12464         }
12465
12466         if (r_showsurfaces.integer == 3)
12467         {
12468                 rsurface.passcolor4f = NULL;
12469
12470                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
12471                 {
12472                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12473
12474                         rsurface.passcolor4f = NULL;
12475                         rsurface.passcolor4f_vertexbuffer = 0;
12476                         rsurface.passcolor4f_bufferoffset = 0;
12477                 }
12478                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
12479                 {
12480                         qboolean applycolor = true;
12481                         float one = 1.0;
12482
12483                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12484
12485                         r_refdef.lightmapintensity = 1;
12486                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
12487                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12488                 }
12489                 else if (FAKELIGHT_ENABLED)
12490                 {
12491                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12492
12493                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
12494                         RSurf_DrawBatch_GL11_ApplyFakeLight();
12495                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
12496                 }
12497                 else
12498                 {
12499                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12500
12501                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
12502                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
12503                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
12504                 }
12505
12506                 if(!rsurface.passcolor4f)
12507                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
12508
12509                 RSurf_DrawBatch_GL11_ApplyAmbient();
12510                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
12511                 if(r_refdef.fogenabled)
12512                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
12513                 RSurf_DrawBatch_GL11_ClampColor();
12514
12515                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
12516                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
12517                 RSurf_DrawBatch();
12518         }
12519         else if (!r_refdef.view.showdebug)
12520         {
12521                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12522                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12523                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12524                 {
12525                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12526                         Vector4Set(batchvertex[vi].color4ub, 0, 0, 0, 255);
12527                 }
12528                 R_Mesh_PrepareVertices_Generic_Unlock();
12529                 RSurf_DrawBatch();
12530         }
12531         else if (r_showsurfaces.integer == 4)
12532         {
12533                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12534                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
12535                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
12536                 {
12537                         unsigned char c = vi << 3;
12538                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12539                         Vector4Set(batchvertex[vi].color4ub, c, c, c, 255);
12540                 }
12541                 R_Mesh_PrepareVertices_Generic_Unlock();
12542                 RSurf_DrawBatch();
12543         }
12544         else if (r_showsurfaces.integer == 2)
12545         {
12546                 const int *e;
12547                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12548                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
12549                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
12550                 {
12551                         unsigned char c = (j + rsurface.batchfirsttriangle) << 3;
12552                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
12553                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
12554                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
12555                         Vector4Set(batchvertex[j*3+0].color4ub, c, c, c, 255);
12556                         Vector4Set(batchvertex[j*3+1].color4ub, c, c, c, 255);
12557                         Vector4Set(batchvertex[j*3+2].color4ub, c, c, c, 255);
12558                 }
12559                 R_Mesh_PrepareVertices_Generic_Unlock();
12560                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
12561         }
12562         else
12563         {
12564                 int texturesurfaceindex;
12565                 int k;
12566                 const msurface_t *surface;
12567                 unsigned char surfacecolor4ub[4];
12568                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
12569                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
12570                 vi = 0;
12571                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
12572                 {
12573                         surface = texturesurfacelist[texturesurfaceindex];
12574                         k = (int)(((size_t)surface) / sizeof(msurface_t));
12575                         Vector4Set(surfacecolor4ub, (k & 0xF) << 4, (k & 0xF0), (k & 0xF00) >> 4, 255);
12576                         for (j = 0;j < surface->num_vertices;j++)
12577                         {
12578                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
12579                                 Vector4Copy(surfacecolor4ub, batchvertex[vi].color4ub);
12580                                 vi++;
12581                         }
12582                 }
12583                 R_Mesh_PrepareVertices_Generic_Unlock();
12584                 RSurf_DrawBatch();
12585         }
12586 }
12587
12588 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12589 {
12590         CHECKGLERROR
12591         RSurf_SetupDepthAndCulling();
12592         if (r_showsurfaces.integer)
12593         {
12594                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12595                 return;
12596         }
12597         switch (vid.renderpath)
12598         {
12599         case RENDERPATH_GL20:
12600         case RENDERPATH_D3D9:
12601         case RENDERPATH_D3D10:
12602         case RENDERPATH_D3D11:
12603         case RENDERPATH_SOFT:
12604         case RENDERPATH_GLES2:
12605                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12606                 break;
12607         case RENDERPATH_GL13:
12608                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12609                 break;
12610         case RENDERPATH_GL11:
12611                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12612                 break;
12613         }
12614         CHECKGLERROR
12615 }
12616
12617 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
12618 {
12619         CHECKGLERROR
12620         RSurf_SetupDepthAndCulling();
12621         if (r_showsurfaces.integer)
12622         {
12623                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
12624                 return;
12625         }
12626         switch (vid.renderpath)
12627         {
12628         case RENDERPATH_GL20:
12629         case RENDERPATH_D3D9:
12630         case RENDERPATH_D3D10:
12631         case RENDERPATH_D3D11:
12632         case RENDERPATH_SOFT:
12633         case RENDERPATH_GLES2:
12634                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12635                 break;
12636         case RENDERPATH_GL13:
12637                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
12638                 break;
12639         case RENDERPATH_GL11:
12640                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
12641                 break;
12642         }
12643         CHECKGLERROR
12644 }
12645
12646 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12647 {
12648         int i, j;
12649         int texturenumsurfaces, endsurface;
12650         texture_t *texture;
12651         const msurface_t *surface;
12652 #define MAXBATCH_TRANSPARENTSURFACES 256
12653         const msurface_t *texturesurfacelist[MAXBATCH_TRANSPARENTSURFACES];
12654
12655         // if the model is static it doesn't matter what value we give for
12656         // wantnormals and wanttangents, so this logic uses only rules applicable
12657         // to a model, knowing that they are meaningless otherwise
12658         if (ent == r_refdef.scene.worldentity)
12659                 RSurf_ActiveWorldEntity();
12660         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12661                 RSurf_ActiveModelEntity(ent, false, false, false);
12662         else
12663         {
12664                 switch (vid.renderpath)
12665                 {
12666                 case RENDERPATH_GL20:
12667                 case RENDERPATH_D3D9:
12668                 case RENDERPATH_D3D10:
12669                 case RENDERPATH_D3D11:
12670                 case RENDERPATH_SOFT:
12671                 case RENDERPATH_GLES2:
12672                         RSurf_ActiveModelEntity(ent, true, true, false);
12673                         break;
12674                 case RENDERPATH_GL13:
12675                 case RENDERPATH_GL11:
12676                         RSurf_ActiveModelEntity(ent, true, false, false);
12677                         break;
12678                 }
12679         }
12680
12681         if (r_transparentdepthmasking.integer)
12682         {
12683                 qboolean setup = false;
12684                 for (i = 0;i < numsurfaces;i = j)
12685                 {
12686                         j = i + 1;
12687                         surface = rsurface.modelsurfaces + surfacelist[i];
12688                         texture = surface->texture;
12689                         rsurface.texture = R_GetCurrentTexture(texture);
12690                         rsurface.lightmaptexture = NULL;
12691                         rsurface.deluxemaptexture = NULL;
12692                         rsurface.uselightmaptexture = false;
12693                         // scan ahead until we find a different texture
12694                         endsurface = min(i + 1024, numsurfaces);
12695                         texturenumsurfaces = 0;
12696                         texturesurfacelist[texturenumsurfaces++] = surface;
12697                         for (;j < endsurface;j++)
12698                         {
12699                                 surface = rsurface.modelsurfaces + surfacelist[j];
12700                                 if (texture != surface->texture)
12701                                         break;
12702                                 texturesurfacelist[texturenumsurfaces++] = surface;
12703                         }
12704                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
12705                                 continue;
12706                         // render the range of surfaces as depth
12707                         if (!setup)
12708                         {
12709                                 setup = true;
12710                                 GL_ColorMask(0,0,0,0);
12711                                 GL_Color(1,1,1,1);
12712                                 GL_DepthTest(true);
12713                                 GL_BlendFunc(GL_ONE, GL_ZERO);
12714                                 GL_DepthMask(true);
12715 //                              R_Mesh_ResetTextureState();
12716                                 R_SetupShader_DepthOrShadow();
12717                         }
12718                         RSurf_SetupDepthAndCulling();
12719                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12720                         if (rsurface.batchvertex3fbuffer)
12721                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12722                         else
12723                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12724                         RSurf_DrawBatch();
12725                 }
12726                 if (setup)
12727                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
12728         }
12729
12730         for (i = 0;i < numsurfaces;i = j)
12731         {
12732                 j = i + 1;
12733                 surface = rsurface.modelsurfaces + surfacelist[i];
12734                 texture = surface->texture;
12735                 rsurface.texture = R_GetCurrentTexture(texture);
12736                 // scan ahead until we find a different texture
12737                 endsurface = min(i + MAXBATCH_TRANSPARENTSURFACES, numsurfaces);
12738                 texturenumsurfaces = 0;
12739                 texturesurfacelist[texturenumsurfaces++] = surface;
12740                 if(FAKELIGHT_ENABLED)
12741                 {
12742                         rsurface.lightmaptexture = NULL;
12743                         rsurface.deluxemaptexture = NULL;
12744                         rsurface.uselightmaptexture = false;
12745                         for (;j < endsurface;j++)
12746                         {
12747                                 surface = rsurface.modelsurfaces + surfacelist[j];
12748                                 if (texture != surface->texture)
12749                                         break;
12750                                 texturesurfacelist[texturenumsurfaces++] = surface;
12751                         }
12752                 }
12753                 else
12754                 {
12755                         rsurface.lightmaptexture = surface->lightmaptexture;
12756                         rsurface.deluxemaptexture = surface->deluxemaptexture;
12757                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
12758                         for (;j < endsurface;j++)
12759                         {
12760                                 surface = rsurface.modelsurfaces + surfacelist[j];
12761                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
12762                                         break;
12763                                 texturesurfacelist[texturenumsurfaces++] = surface;
12764                         }
12765                 }
12766                 // render the range of surfaces
12767                 if (ent == r_refdef.scene.worldentity)
12768                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12769                 else
12770                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
12771         }
12772         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12773 }
12774
12775 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
12776 {
12777         // transparent surfaces get pushed off into the transparent queue
12778         int surfacelistindex;
12779         const msurface_t *surface;
12780         vec3_t tempcenter, center;
12781         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
12782         {
12783                 surface = texturesurfacelist[surfacelistindex];
12784                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
12785                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
12786                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
12787                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
12788                 if (queueentity->transparent_offset) // transparent offset
12789                 {
12790                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
12791                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
12792                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
12793                 }
12794                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
12795         }
12796 }
12797
12798 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
12799 {
12800         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
12801                 return;
12802         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
12803                 return;
12804         RSurf_SetupDepthAndCulling();
12805         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
12806         if (rsurface.batchvertex3fbuffer)
12807                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
12808         else
12809                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
12810         RSurf_DrawBatch();
12811 }
12812
12813 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
12814 {
12815         const entity_render_t *queueentity = r_refdef.scene.worldentity;
12816         CHECKGLERROR
12817         if (depthonly)
12818                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12819         else if (prepass)
12820         {
12821                 if (!rsurface.texture->currentnumlayers)
12822                         return;
12823                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12824                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12825                 else
12826                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12827         }
12828         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12829                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12830         else if (!rsurface.texture->currentnumlayers)
12831                 return;
12832         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12833         {
12834                 // in the deferred case, transparent surfaces were queued during prepass
12835                 if (!r_shadow_usingdeferredprepass)
12836                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12837         }
12838         else
12839         {
12840                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12841                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12842         }
12843         CHECKGLERROR
12844 }
12845
12846 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12847 {
12848         int i, j;
12849         texture_t *texture;
12850         R_FrameData_SetMark();
12851         // break the surface list down into batches by texture and use of lightmapping
12852         for (i = 0;i < numsurfaces;i = j)
12853         {
12854                 j = i + 1;
12855                 // texture is the base texture pointer, rsurface.texture is the
12856                 // current frame/skin the texture is directing us to use (for example
12857                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12858                 // use skin 1 instead)
12859                 texture = surfacelist[i]->texture;
12860                 rsurface.texture = R_GetCurrentTexture(texture);
12861                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12862                 {
12863                         // if this texture is not the kind we want, skip ahead to the next one
12864                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12865                                 ;
12866                         continue;
12867                 }
12868                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12869                 {
12870                         rsurface.lightmaptexture = NULL;
12871                         rsurface.deluxemaptexture = NULL;
12872                         rsurface.uselightmaptexture = false;
12873                         // simply scan ahead until we find a different texture or lightmap state
12874                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12875                                 ;
12876                 }
12877                 else
12878                 {
12879                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12880                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12881                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12882                         // simply scan ahead until we find a different texture or lightmap state
12883                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12884                                 ;
12885                 }
12886                 // render the range of surfaces
12887                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
12888         }
12889         R_FrameData_ReturnToMark();
12890 }
12891
12892 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
12893 {
12894         CHECKGLERROR
12895         if (depthonly)
12896                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
12897         else if (prepass)
12898         {
12899                 if (!rsurface.texture->currentnumlayers)
12900                         return;
12901                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
12902                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12903                 else
12904                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
12905         }
12906         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && !r_showsurfaces.integer)
12907                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
12908         else if (!rsurface.texture->currentnumlayers)
12909                 return;
12910         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
12911         {
12912                 // in the deferred case, transparent surfaces were queued during prepass
12913                 if (!r_shadow_usingdeferredprepass)
12914                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
12915         }
12916         else
12917         {
12918                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
12919                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
12920         }
12921         CHECKGLERROR
12922 }
12923
12924 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
12925 {
12926         int i, j;
12927         texture_t *texture;
12928         R_FrameData_SetMark();
12929         // break the surface list down into batches by texture and use of lightmapping
12930         for (i = 0;i < numsurfaces;i = j)
12931         {
12932                 j = i + 1;
12933                 // texture is the base texture pointer, rsurface.texture is the
12934                 // current frame/skin the texture is directing us to use (for example
12935                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
12936                 // use skin 1 instead)
12937                 texture = surfacelist[i]->texture;
12938                 rsurface.texture = R_GetCurrentTexture(texture);
12939                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
12940                 {
12941                         // if this texture is not the kind we want, skip ahead to the next one
12942                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12943                                 ;
12944                         continue;
12945                 }
12946                 if(FAKELIGHT_ENABLED || depthonly || prepass)
12947                 {
12948                         rsurface.lightmaptexture = NULL;
12949                         rsurface.deluxemaptexture = NULL;
12950                         rsurface.uselightmaptexture = false;
12951                         // simply scan ahead until we find a different texture or lightmap state
12952                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
12953                                 ;
12954                 }
12955                 else
12956                 {
12957                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
12958                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
12959                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
12960                         // simply scan ahead until we find a different texture or lightmap state
12961                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
12962                                 ;
12963                 }
12964                 // render the range of surfaces
12965                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
12966         }
12967         R_FrameData_ReturnToMark();
12968 }
12969
12970 float locboxvertex3f[6*4*3] =
12971 {
12972         1,0,1, 1,0,0, 1,1,0, 1,1,1,
12973         0,1,1, 0,1,0, 0,0,0, 0,0,1,
12974         1,1,1, 1,1,0, 0,1,0, 0,1,1,
12975         0,0,1, 0,0,0, 1,0,0, 1,0,1,
12976         0,0,1, 1,0,1, 1,1,1, 0,1,1,
12977         1,0,0, 0,0,0, 0,1,0, 1,1,0
12978 };
12979
12980 unsigned short locboxelements[6*2*3] =
12981 {
12982          0, 1, 2, 0, 2, 3,
12983          4, 5, 6, 4, 6, 7,
12984          8, 9,10, 8,10,11,
12985         12,13,14, 12,14,15,
12986         16,17,18, 16,18,19,
12987         20,21,22, 20,22,23
12988 };
12989
12990 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
12991 {
12992         int i, j;
12993         cl_locnode_t *loc = (cl_locnode_t *)ent;
12994         vec3_t mins, size;
12995         float vertex3f[6*4*3];
12996         CHECKGLERROR
12997         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12998         GL_DepthMask(false);
12999         GL_DepthRange(0, 1);
13000         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13001         GL_DepthTest(true);
13002         GL_CullFace(GL_NONE);
13003         R_EntityMatrix(&identitymatrix);
13004
13005 //      R_Mesh_ResetTextureState();
13006
13007         i = surfacelist[0];
13008         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13009                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13010                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
13011                         surfacelist[0] < 0 ? 0.5f : 0.125f);
13012
13013         if (VectorCompare(loc->mins, loc->maxs))
13014         {
13015                 VectorSet(size, 2, 2, 2);
13016                 VectorMA(loc->mins, -0.5f, size, mins);
13017         }
13018         else
13019         {
13020                 VectorCopy(loc->mins, mins);
13021                 VectorSubtract(loc->maxs, loc->mins, size);
13022         }
13023
13024         for (i = 0;i < 6*4*3;)
13025                 for (j = 0;j < 3;j++, i++)
13026                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
13027
13028         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
13029         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13030         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
13031 }
13032
13033 void R_DrawLocs(void)
13034 {
13035         int index;
13036         cl_locnode_t *loc, *nearestloc;
13037         vec3_t center;
13038         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
13039         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
13040         {
13041                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
13042                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
13043         }
13044 }
13045
13046 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
13047 {
13048         if (decalsystem->decals)
13049                 Mem_Free(decalsystem->decals);
13050         memset(decalsystem, 0, sizeof(*decalsystem));
13051 }
13052
13053 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)
13054 {
13055         tridecal_t *decal;
13056         tridecal_t *decals;
13057         int i;
13058
13059         // expand or initialize the system
13060         if (decalsystem->maxdecals <= decalsystem->numdecals)
13061         {
13062                 decalsystem_t old = *decalsystem;
13063                 qboolean useshortelements;
13064                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
13065                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
13066                 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)));
13067                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
13068                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
13069                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
13070                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
13071                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
13072                 if (decalsystem->numdecals)
13073                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
13074                 if (old.decals)
13075                         Mem_Free(old.decals);
13076                 for (i = 0;i < decalsystem->maxdecals*3;i++)
13077                         decalsystem->element3i[i] = i;
13078                 if (useshortelements)
13079                         for (i = 0;i < decalsystem->maxdecals*3;i++)
13080                                 decalsystem->element3s[i] = i;
13081         }
13082
13083         // grab a decal and search for another free slot for the next one
13084         decals = decalsystem->decals;
13085         decal = decalsystem->decals + (i = decalsystem->freedecal++);
13086         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4ub[0][3];i++)
13087                 ;
13088         decalsystem->freedecal = i;
13089         if (decalsystem->numdecals <= i)
13090                 decalsystem->numdecals = i + 1;
13091
13092         // initialize the decal
13093         decal->lived = 0;
13094         decal->triangleindex = triangleindex;
13095         decal->surfaceindex = surfaceindex;
13096         decal->decalsequence = decalsequence;
13097         decal->color4ub[0][0] = (unsigned char)(c0[0]*255.0f);
13098         decal->color4ub[0][1] = (unsigned char)(c0[1]*255.0f);
13099         decal->color4ub[0][2] = (unsigned char)(c0[2]*255.0f);
13100         decal->color4ub[0][3] = 255;
13101         decal->color4ub[1][0] = (unsigned char)(c1[0]*255.0f);
13102         decal->color4ub[1][1] = (unsigned char)(c1[1]*255.0f);
13103         decal->color4ub[1][2] = (unsigned char)(c1[2]*255.0f);
13104         decal->color4ub[1][3] = 255;
13105         decal->color4ub[2][0] = (unsigned char)(c2[0]*255.0f);
13106         decal->color4ub[2][1] = (unsigned char)(c2[1]*255.0f);
13107         decal->color4ub[2][2] = (unsigned char)(c2[2]*255.0f);
13108         decal->color4ub[2][3] = 255;
13109         decal->vertex3f[0][0] = v0[0];
13110         decal->vertex3f[0][1] = v0[1];
13111         decal->vertex3f[0][2] = v0[2];
13112         decal->vertex3f[1][0] = v1[0];
13113         decal->vertex3f[1][1] = v1[1];
13114         decal->vertex3f[1][2] = v1[2];
13115         decal->vertex3f[2][0] = v2[0];
13116         decal->vertex3f[2][1] = v2[1];
13117         decal->vertex3f[2][2] = v2[2];
13118         decal->texcoord2f[0][0] = t0[0];
13119         decal->texcoord2f[0][1] = t0[1];
13120         decal->texcoord2f[1][0] = t1[0];
13121         decal->texcoord2f[1][1] = t1[1];
13122         decal->texcoord2f[2][0] = t2[0];
13123         decal->texcoord2f[2][1] = t2[1];
13124 }
13125
13126 extern cvar_t cl_decals_bias;
13127 extern cvar_t cl_decals_models;
13128 extern cvar_t cl_decals_newsystem_intensitymultiplier;
13129 // baseparms, parms, temps
13130 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)
13131 {
13132         int cornerindex;
13133         int index;
13134         float v[9][3];
13135         const float *vertex3f;
13136         int numpoints;
13137         float points[2][9][3];
13138         float temp[3];
13139         float tc[9][2];
13140         float f;
13141         float c[9][4];
13142         const int *e;
13143
13144         e = rsurface.modelelement3i + 3*triangleindex;
13145
13146         vertex3f = rsurface.modelvertex3f;
13147
13148         for (cornerindex = 0;cornerindex < 3;cornerindex++)
13149         {
13150                 index = 3*e[cornerindex];
13151                 VectorCopy(vertex3f + index, v[cornerindex]);
13152         }
13153         // cull backfaces
13154         //TriangleNormal(v[0], v[1], v[2], normal);
13155         //if (DotProduct(normal, localnormal) < 0.0f)
13156         //      continue;
13157         // clip by each of the box planes formed from the projection matrix
13158         // if anything survives, we emit the decal
13159         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]);
13160         if (numpoints < 3)
13161                 return;
13162         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]);
13163         if (numpoints < 3)
13164                 return;
13165         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]);
13166         if (numpoints < 3)
13167                 return;
13168         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]);
13169         if (numpoints < 3)
13170                 return;
13171         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]);
13172         if (numpoints < 3)
13173                 return;
13174         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]);
13175         if (numpoints < 3)
13176                 return;
13177         // some part of the triangle survived, so we have to accept it...
13178         if (dynamic)
13179         {
13180                 // dynamic always uses the original triangle
13181                 numpoints = 3;
13182                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
13183                 {
13184                         index = 3*e[cornerindex];
13185                         VectorCopy(vertex3f + index, v[cornerindex]);
13186                 }
13187         }
13188         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
13189         {
13190                 // convert vertex positions to texcoords
13191                 Matrix4x4_Transform(projection, v[cornerindex], temp);
13192                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
13193                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
13194                 // calculate distance fade from the projection origin
13195                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
13196                 f = bound(0.0f, f, 1.0f);
13197                 c[cornerindex][0] = r * f;
13198                 c[cornerindex][1] = g * f;
13199                 c[cornerindex][2] = b * f;
13200                 c[cornerindex][3] = 1.0f;
13201                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
13202         }
13203         if (dynamic)
13204                 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);
13205         else
13206                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
13207                         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);
13208 }
13209 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)
13210 {
13211         matrix4x4_t projection;
13212         decalsystem_t *decalsystem;
13213         qboolean dynamic;
13214         dp_model_t *model;
13215         const msurface_t *surface;
13216         const msurface_t *surfaces;
13217         const int *surfacelist;
13218         const texture_t *texture;
13219         int numtriangles;
13220         int numsurfacelist;
13221         int surfacelistindex;
13222         int surfaceindex;
13223         int triangleindex;
13224         float localorigin[3];
13225         float localnormal[3];
13226         float localmins[3];
13227         float localmaxs[3];
13228         float localsize;
13229         //float normal[3];
13230         float planes[6][4];
13231         float angles[3];
13232         bih_t *bih;
13233         int bih_triangles_count;
13234         int bih_triangles[256];
13235         int bih_surfaces[256];
13236
13237         decalsystem = &ent->decalsystem;
13238         model = ent->model;
13239         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
13240         {
13241                 R_DecalSystem_Reset(&ent->decalsystem);
13242                 return;
13243         }
13244
13245         if (!model->brush.data_leafs && !cl_decals_models.integer)
13246         {
13247                 if (decalsystem->model)
13248                         R_DecalSystem_Reset(decalsystem);
13249                 return;
13250         }
13251
13252         if (decalsystem->model != model)
13253                 R_DecalSystem_Reset(decalsystem);
13254         decalsystem->model = model;
13255
13256         RSurf_ActiveModelEntity(ent, false, false, false);
13257
13258         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
13259         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
13260         VectorNormalize(localnormal);
13261         localsize = worldsize*rsurface.inversematrixscale;
13262         localmins[0] = localorigin[0] - localsize;
13263         localmins[1] = localorigin[1] - localsize;
13264         localmins[2] = localorigin[2] - localsize;
13265         localmaxs[0] = localorigin[0] + localsize;
13266         localmaxs[1] = localorigin[1] + localsize;
13267         localmaxs[2] = localorigin[2] + localsize;
13268
13269         //VectorCopy(localnormal, planes[4]);
13270         //VectorVectors(planes[4], planes[2], planes[0]);
13271         AnglesFromVectors(angles, localnormal, NULL, false);
13272         AngleVectors(angles, planes[0], planes[2], planes[4]);
13273         VectorNegate(planes[0], planes[1]);
13274         VectorNegate(planes[2], planes[3]);
13275         VectorNegate(planes[4], planes[5]);
13276         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
13277         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
13278         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
13279         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
13280         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
13281         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
13282
13283 #if 1
13284 // works
13285 {
13286         matrix4x4_t forwardprojection;
13287         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
13288         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
13289 }
13290 #else
13291 // broken
13292 {
13293         float projectionvector[4][3];
13294         VectorScale(planes[0], ilocalsize, projectionvector[0]);
13295         VectorScale(planes[2], ilocalsize, projectionvector[1]);
13296         VectorScale(planes[4], ilocalsize, projectionvector[2]);
13297         projectionvector[0][0] = planes[0][0] * ilocalsize;
13298         projectionvector[0][1] = planes[1][0] * ilocalsize;
13299         projectionvector[0][2] = planes[2][0] * ilocalsize;
13300         projectionvector[1][0] = planes[0][1] * ilocalsize;
13301         projectionvector[1][1] = planes[1][1] * ilocalsize;
13302         projectionvector[1][2] = planes[2][1] * ilocalsize;
13303         projectionvector[2][0] = planes[0][2] * ilocalsize;
13304         projectionvector[2][1] = planes[1][2] * ilocalsize;
13305         projectionvector[2][2] = planes[2][2] * ilocalsize;
13306         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
13307         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
13308         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
13309         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
13310 }
13311 #endif
13312
13313         dynamic = model->surfmesh.isanimated;
13314         numsurfacelist = model->nummodelsurfaces;
13315         surfacelist = model->sortedmodelsurfaces;
13316         surfaces = model->data_surfaces;
13317
13318         bih = NULL;
13319         bih_triangles_count = -1;
13320         if(!dynamic)
13321         {
13322                 if(model->render_bih.numleafs)
13323                         bih = &model->render_bih;
13324                 else if(model->collision_bih.numleafs)
13325                         bih = &model->collision_bih;
13326         }
13327         if(bih)
13328                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
13329         if(bih_triangles_count == 0)
13330                 return;
13331         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
13332                 return;
13333         if(bih_triangles_count > 0)
13334         {
13335                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
13336                 {
13337                         surfaceindex = bih_surfaces[triangleindex];
13338                         surface = surfaces + surfaceindex;
13339                         texture = surface->texture;
13340                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13341                                 continue;
13342                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13343                                 continue;
13344                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
13345                 }
13346         }
13347         else
13348         {
13349                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
13350                 {
13351                         surfaceindex = surfacelist[surfacelistindex];
13352                         surface = surfaces + surfaceindex;
13353                         // check cull box first because it rejects more than any other check
13354                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
13355                                 continue;
13356                         // skip transparent surfaces
13357                         texture = surface->texture;
13358                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
13359                                 continue;
13360                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
13361                                 continue;
13362                         numtriangles = surface->num_triangles;
13363                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
13364                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
13365                 }
13366         }
13367 }
13368
13369 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
13370 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)
13371 {
13372         int renderentityindex;
13373         float worldmins[3];
13374         float worldmaxs[3];
13375         entity_render_t *ent;
13376
13377         if (!cl_decals_newsystem.integer)
13378                 return;
13379
13380         worldmins[0] = worldorigin[0] - worldsize;
13381         worldmins[1] = worldorigin[1] - worldsize;
13382         worldmins[2] = worldorigin[2] - worldsize;
13383         worldmaxs[0] = worldorigin[0] + worldsize;
13384         worldmaxs[1] = worldorigin[1] + worldsize;
13385         worldmaxs[2] = worldorigin[2] + worldsize;
13386
13387         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13388
13389         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
13390         {
13391                 ent = r_refdef.scene.entities[renderentityindex];
13392                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
13393                         continue;
13394
13395                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
13396         }
13397 }
13398
13399 typedef struct r_decalsystem_splatqueue_s
13400 {
13401         vec3_t worldorigin;
13402         vec3_t worldnormal;
13403         float color[4];
13404         float tcrange[4];
13405         float worldsize;
13406         int decalsequence;
13407 }
13408 r_decalsystem_splatqueue_t;
13409
13410 int r_decalsystem_numqueued = 0;
13411 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
13412
13413 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)
13414 {
13415         r_decalsystem_splatqueue_t *queue;
13416
13417         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
13418                 return;
13419
13420         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
13421         VectorCopy(worldorigin, queue->worldorigin);
13422         VectorCopy(worldnormal, queue->worldnormal);
13423         Vector4Set(queue->color, r, g, b, a);
13424         Vector4Set(queue->tcrange, s1, t1, s2, t2);
13425         queue->worldsize = worldsize;
13426         queue->decalsequence = cl.decalsequence++;
13427 }
13428
13429 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
13430 {
13431         int i;
13432         r_decalsystem_splatqueue_t *queue;
13433
13434         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
13435                 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);
13436         r_decalsystem_numqueued = 0;
13437 }
13438
13439 extern cvar_t cl_decals_max;
13440 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
13441 {
13442         int i;
13443         decalsystem_t *decalsystem = &ent->decalsystem;
13444         int numdecals;
13445         int killsequence;
13446         tridecal_t *decal;
13447         float frametime;
13448         float lifetime;
13449
13450         if (!decalsystem->numdecals)
13451                 return;
13452
13453         if (r_showsurfaces.integer)
13454                 return;
13455
13456         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13457         {
13458                 R_DecalSystem_Reset(decalsystem);
13459                 return;
13460         }
13461
13462         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
13463         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
13464
13465         if (decalsystem->lastupdatetime)
13466                 frametime = (cl.time - decalsystem->lastupdatetime);
13467         else
13468                 frametime = 0;
13469         decalsystem->lastupdatetime = cl.time;
13470         decal = decalsystem->decals;
13471         numdecals = decalsystem->numdecals;
13472
13473         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13474         {
13475                 if (decal->color4ub[0][3])
13476                 {
13477                         decal->lived += frametime;
13478                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
13479                         {
13480                                 memset(decal, 0, sizeof(*decal));
13481                                 if (decalsystem->freedecal > i)
13482                                         decalsystem->freedecal = i;
13483                         }
13484                 }
13485         }
13486         decal = decalsystem->decals;
13487         while (numdecals > 0 && !decal[numdecals-1].color4ub[0][3])
13488                 numdecals--;
13489
13490         // collapse the array by shuffling the tail decals into the gaps
13491         for (;;)
13492         {
13493                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4ub[0][3])
13494                         decalsystem->freedecal++;
13495                 if (decalsystem->freedecal == numdecals)
13496                         break;
13497                 decal[decalsystem->freedecal] = decal[--numdecals];
13498         }
13499
13500         decalsystem->numdecals = numdecals;
13501
13502         if (numdecals <= 0)
13503         {
13504                 // if there are no decals left, reset decalsystem
13505                 R_DecalSystem_Reset(decalsystem);
13506         }
13507 }
13508
13509 extern skinframe_t *decalskinframe;
13510 static void R_DrawModelDecals_Entity(entity_render_t *ent)
13511 {
13512         int i;
13513         decalsystem_t *decalsystem = &ent->decalsystem;
13514         int numdecals;
13515         tridecal_t *decal;
13516         float faderate;
13517         float alpha;
13518         float *v3f;
13519         float *c4f;
13520         float *t2f;
13521         const int *e;
13522         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
13523         int numtris = 0;
13524
13525         numdecals = decalsystem->numdecals;
13526         if (!numdecals)
13527                 return;
13528
13529         if (r_showsurfaces.integer)
13530                 return;
13531
13532         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
13533         {
13534                 R_DecalSystem_Reset(decalsystem);
13535                 return;
13536         }
13537
13538         // if the model is static it doesn't matter what value we give for
13539         // wantnormals and wanttangents, so this logic uses only rules applicable
13540         // to a model, knowing that they are meaningless otherwise
13541         if (ent == r_refdef.scene.worldentity)
13542                 RSurf_ActiveWorldEntity();
13543         else
13544                 RSurf_ActiveModelEntity(ent, false, false, false);
13545
13546         decalsystem->lastupdatetime = cl.time;
13547         decal = decalsystem->decals;
13548
13549         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
13550
13551         // update vertex positions for animated models
13552         v3f = decalsystem->vertex3f;
13553         c4f = decalsystem->color4f;
13554         t2f = decalsystem->texcoord2f;
13555         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
13556         {
13557                 if (!decal->color4ub[0][3])
13558                         continue;
13559
13560                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
13561                         continue;
13562
13563                 // update color values for fading decals
13564                 if (decal->lived >= cl_decals_time.value)
13565                 {
13566                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
13567                         alpha *= (1.0f/255.0f);
13568                 }
13569                 else
13570                         alpha = 1.0f/255.0f;
13571
13572                 c4f[ 0] = decal->color4ub[0][0] * alpha;
13573                 c4f[ 1] = decal->color4ub[0][1] * alpha;
13574                 c4f[ 2] = decal->color4ub[0][2] * alpha;
13575                 c4f[ 3] = 1;
13576                 c4f[ 4] = decal->color4ub[1][0] * alpha;
13577                 c4f[ 5] = decal->color4ub[1][1] * alpha;
13578                 c4f[ 6] = decal->color4ub[1][2] * alpha;
13579                 c4f[ 7] = 1;
13580                 c4f[ 8] = decal->color4ub[2][0] * alpha;
13581                 c4f[ 9] = decal->color4ub[2][1] * alpha;
13582                 c4f[10] = decal->color4ub[2][2] * alpha;
13583                 c4f[11] = 1;
13584
13585                 t2f[0] = decal->texcoord2f[0][0];
13586                 t2f[1] = decal->texcoord2f[0][1];
13587                 t2f[2] = decal->texcoord2f[1][0];
13588                 t2f[3] = decal->texcoord2f[1][1];
13589                 t2f[4] = decal->texcoord2f[2][0];
13590                 t2f[5] = decal->texcoord2f[2][1];
13591
13592                 // update vertex positions for animated models
13593                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
13594                 {
13595                         e = rsurface.modelelement3i + 3*decal->triangleindex;
13596                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
13597                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
13598                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
13599                 }
13600                 else
13601                 {
13602                         VectorCopy(decal->vertex3f[0], v3f);
13603                         VectorCopy(decal->vertex3f[1], v3f + 3);
13604                         VectorCopy(decal->vertex3f[2], v3f + 6);
13605                 }
13606
13607                 if (r_refdef.fogenabled)
13608                 {
13609                         alpha = RSurf_FogVertex(v3f);
13610                         VectorScale(c4f, alpha, c4f);
13611                         alpha = RSurf_FogVertex(v3f + 3);
13612                         VectorScale(c4f + 4, alpha, c4f + 4);
13613                         alpha = RSurf_FogVertex(v3f + 6);
13614                         VectorScale(c4f + 8, alpha, c4f + 8);
13615                 }
13616
13617                 v3f += 9;
13618                 c4f += 12;
13619                 t2f += 6;
13620                 numtris++;
13621         }
13622
13623         if (numtris > 0)
13624         {
13625                 r_refdef.stats.drawndecals += numtris;
13626
13627                 // now render the decals all at once
13628                 // (this assumes they all use one particle font texture!)
13629                 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);
13630 //              R_Mesh_ResetTextureState();
13631                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
13632                 GL_DepthMask(false);
13633                 GL_DepthRange(0, 1);
13634                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
13635                 GL_DepthTest(true);
13636                 GL_CullFace(GL_NONE);
13637                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
13638                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1);
13639                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
13640         }
13641 }
13642
13643 static void R_DrawModelDecals(void)
13644 {
13645         int i, numdecals;
13646
13647         // fade faster when there are too many decals
13648         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13649         for (i = 0;i < r_refdef.scene.numentities;i++)
13650                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13651
13652         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
13653         for (i = 0;i < r_refdef.scene.numentities;i++)
13654                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13655                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
13656
13657         R_DecalSystem_ApplySplatEntitiesQueue();
13658
13659         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
13660         for (i = 0;i < r_refdef.scene.numentities;i++)
13661                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
13662
13663         r_refdef.stats.totaldecals += numdecals;
13664
13665         if (r_showsurfaces.integer)
13666                 return;
13667
13668         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
13669
13670         for (i = 0;i < r_refdef.scene.numentities;i++)
13671         {
13672                 if (!r_refdef.viewcache.entityvisible[i])
13673                         continue;
13674                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
13675                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
13676         }
13677 }
13678
13679 extern cvar_t mod_collision_bih;
13680 void R_DrawDebugModel(void)
13681 {
13682         entity_render_t *ent = rsurface.entity;
13683         int i, j, k, l, flagsmask;
13684         const msurface_t *surface;
13685         dp_model_t *model = ent->model;
13686         vec3_t v;
13687
13688         switch(vid.renderpath)
13689         {
13690         case RENDERPATH_GL11:
13691         case RENDERPATH_GL13:
13692         case RENDERPATH_GL20:
13693                 break;
13694         case RENDERPATH_D3D9:
13695                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13696                 return;
13697         case RENDERPATH_D3D10:
13698                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13699                 return;
13700         case RENDERPATH_D3D11:
13701                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13702                 return;
13703         case RENDERPATH_SOFT:
13704                 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13705                 return;
13706         case RENDERPATH_GLES2:
13707                 //Con_DPrintf("FIXME GLES2 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
13708                 return;
13709         }
13710
13711         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
13712
13713 //      R_Mesh_ResetTextureState();
13714         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1);
13715         GL_DepthRange(0, 1);
13716         GL_DepthTest(!r_showdisabledepthtest.integer);
13717         GL_DepthMask(false);
13718         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13719
13720         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
13721         {
13722                 int triangleindex;
13723                 int bihleafindex;
13724                 qboolean cullbox = ent == r_refdef.scene.worldentity;
13725                 const q3mbrush_t *brush;
13726                 const bih_t *bih = &model->collision_bih;
13727                 const bih_leaf_t *bihleaf;
13728                 float vertex3f[3][3];
13729                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
13730                 cullbox = false;
13731                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
13732                 {
13733                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
13734                                 continue;
13735                         switch (bihleaf->type)
13736                         {
13737                         case BIH_BRUSH:
13738                                 brush = model->brush.data_brushes + bihleaf->itemindex;
13739                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
13740                                 {
13741                                         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);
13742                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
13743                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
13744                                 }
13745                                 break;
13746                         case BIH_COLLISIONTRIANGLE:
13747                                 triangleindex = bihleaf->itemindex;
13748                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
13749                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
13750                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
13751                                 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);
13752                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13753                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13754                                 break;
13755                         case BIH_RENDERTRIANGLE:
13756                                 triangleindex = bihleaf->itemindex;
13757                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
13758                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
13759                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
13760                                 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);
13761                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
13762                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
13763                                 break;
13764                         }
13765                 }
13766         }
13767
13768         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
13769
13770         if (r_showtris.integer || (r_shownormals.value != 0))
13771         {
13772                 if (r_showdisabledepthtest.integer)
13773                 {
13774                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
13775                         GL_DepthMask(false);
13776                 }
13777                 else
13778                 {
13779                         GL_BlendFunc(GL_ONE, GL_ZERO);
13780                         GL_DepthMask(true);
13781                 }
13782                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
13783                 {
13784                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
13785                                 continue;
13786                         rsurface.texture = R_GetCurrentTexture(surface->texture);
13787                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
13788                         {
13789                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
13790                                 if (r_showtris.value > 0)
13791                                 {
13792                                         if (!rsurface.texture->currentlayers->depthmask)
13793                                                 GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
13794                                         else if (ent == r_refdef.scene.worldentity)
13795                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
13796                                         else
13797                                                 GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
13798                                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
13799                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
13800                                         RSurf_DrawBatch();
13801                                         qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
13802                                         CHECKGLERROR
13803                                 }
13804                                 if (r_shownormals.value < 0)
13805                                 {
13806                                         qglBegin(GL_LINES);
13807                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13808                                         {
13809                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13810                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13811                                                 qglVertex3f(v[0], v[1], v[2]);
13812                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13813                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13814                                                 qglVertex3f(v[0], v[1], v[2]);
13815                                         }
13816                                         qglEnd();
13817                                         CHECKGLERROR
13818                                 }
13819                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
13820                                 {
13821                                         qglBegin(GL_LINES);
13822                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13823                                         {
13824                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13825                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
13826                                                 qglVertex3f(v[0], v[1], v[2]);
13827                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
13828                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13829                                                 qglVertex3f(v[0], v[1], v[2]);
13830                                         }
13831                                         qglEnd();
13832                                         CHECKGLERROR
13833                                         qglBegin(GL_LINES);
13834                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13835                                         {
13836                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13837                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
13838                                                 qglVertex3f(v[0], v[1], v[2]);
13839                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
13840                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13841                                                 qglVertex3f(v[0], v[1], v[2]);
13842                                         }
13843                                         qglEnd();
13844                                         CHECKGLERROR
13845                                         qglBegin(GL_LINES);
13846                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
13847                                         {
13848                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
13849                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
13850                                                 qglVertex3f(v[0], v[1], v[2]);
13851                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
13852                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
13853                                                 qglVertex3f(v[0], v[1], v[2]);
13854                                         }
13855                                         qglEnd();
13856                                         CHECKGLERROR
13857                                 }
13858                         }
13859                 }
13860                 rsurface.texture = NULL;
13861         }
13862 }
13863
13864 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
13865 int r_maxsurfacelist = 0;
13866 const msurface_t **r_surfacelist = NULL;
13867 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13868 {
13869         int i, j, endj, flagsmask;
13870         dp_model_t *model = r_refdef.scene.worldmodel;
13871         msurface_t *surfaces;
13872         unsigned char *update;
13873         int numsurfacelist = 0;
13874         if (model == NULL)
13875                 return;
13876
13877         if (r_maxsurfacelist < model->num_surfaces)
13878         {
13879                 r_maxsurfacelist = model->num_surfaces;
13880                 if (r_surfacelist)
13881                         Mem_Free((msurface_t**)r_surfacelist);
13882                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13883         }
13884
13885         RSurf_ActiveWorldEntity();
13886
13887         surfaces = model->data_surfaces;
13888         update = model->brushq1.lightmapupdateflags;
13889
13890         // update light styles on this submodel
13891         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
13892         {
13893                 model_brush_lightstyleinfo_t *style;
13894                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
13895                 {
13896                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
13897                         {
13898                                 int *list = style->surfacelist;
13899                                 style->value = r_refdef.scene.lightstylevalue[style->style];
13900                                 for (j = 0;j < style->numsurfaces;j++)
13901                                         update[list[j]] = true;
13902                         }
13903                 }
13904         }
13905
13906         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
13907
13908         if (debug)
13909         {
13910                 R_DrawDebugModel();
13911                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13912                 return;
13913         }
13914
13915         rsurface.lightmaptexture = NULL;
13916         rsurface.deluxemaptexture = NULL;
13917         rsurface.uselightmaptexture = false;
13918         rsurface.texture = NULL;
13919         rsurface.rtlight = NULL;
13920         numsurfacelist = 0;
13921         // add visible surfaces to draw list
13922         for (i = 0;i < model->nummodelsurfaces;i++)
13923         {
13924                 j = model->sortedmodelsurfaces[i];
13925                 if (r_refdef.viewcache.world_surfacevisible[j])
13926                         r_surfacelist[numsurfacelist++] = surfaces + j;
13927         }
13928         // update lightmaps if needed
13929         if (model->brushq1.firstrender)
13930         {
13931                 model->brushq1.firstrender = false;
13932                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13933                         if (update[j])
13934                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13935         }
13936         else if (update)
13937         {
13938                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
13939                         if (r_refdef.viewcache.world_surfacevisible[j])
13940                                 if (update[j])
13941                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
13942         }
13943         // don't do anything if there were no surfaces
13944         if (!numsurfacelist)
13945         {
13946                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13947                 return;
13948         }
13949         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
13950
13951         // add to stats if desired
13952         if (r_speeds.integer && !skysurfaces && !depthonly)
13953         {
13954                 r_refdef.stats.world_surfaces += numsurfacelist;
13955                 for (j = 0;j < numsurfacelist;j++)
13956                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
13957         }
13958
13959         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
13960 }
13961
13962 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
13963 {
13964         int i, j, endj, flagsmask;
13965         dp_model_t *model = ent->model;
13966         msurface_t *surfaces;
13967         unsigned char *update;
13968         int numsurfacelist = 0;
13969         if (model == NULL)
13970                 return;
13971
13972         if (r_maxsurfacelist < model->num_surfaces)
13973         {
13974                 r_maxsurfacelist = model->num_surfaces;
13975                 if (r_surfacelist)
13976                         Mem_Free((msurface_t **)r_surfacelist);
13977                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
13978         }
13979
13980         // if the model is static it doesn't matter what value we give for
13981         // wantnormals and wanttangents, so this logic uses only rules applicable
13982         // to a model, knowing that they are meaningless otherwise
13983         if (ent == r_refdef.scene.worldentity)
13984                 RSurf_ActiveWorldEntity();
13985         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
13986                 RSurf_ActiveModelEntity(ent, false, false, false);
13987         else if (prepass)
13988                 RSurf_ActiveModelEntity(ent, true, true, true);
13989         else if (depthonly)
13990         {
13991                 switch (vid.renderpath)
13992                 {
13993                 case RENDERPATH_GL20:
13994                 case RENDERPATH_D3D9:
13995                 case RENDERPATH_D3D10:
13996                 case RENDERPATH_D3D11:
13997                 case RENDERPATH_SOFT:
13998                 case RENDERPATH_GLES2:
13999                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
14000                         break;
14001                 case RENDERPATH_GL13:
14002                 case RENDERPATH_GL11:
14003                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
14004                         break;
14005                 }
14006         }
14007         else
14008         {
14009                 switch (vid.renderpath)
14010                 {
14011                 case RENDERPATH_GL20:
14012                 case RENDERPATH_D3D9:
14013                 case RENDERPATH_D3D10:
14014                 case RENDERPATH_D3D11:
14015                 case RENDERPATH_SOFT:
14016                 case RENDERPATH_GLES2:
14017                         RSurf_ActiveModelEntity(ent, true, true, false);
14018                         break;
14019                 case RENDERPATH_GL13:
14020                 case RENDERPATH_GL11:
14021                         RSurf_ActiveModelEntity(ent, true, false, false);
14022                         break;
14023                 }
14024         }
14025
14026         surfaces = model->data_surfaces;
14027         update = model->brushq1.lightmapupdateflags;
14028
14029         // update light styles
14030         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
14031         {
14032                 model_brush_lightstyleinfo_t *style;
14033                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
14034                 {
14035                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
14036                         {
14037                                 int *list = style->surfacelist;
14038                                 style->value = r_refdef.scene.lightstylevalue[style->style];
14039                                 for (j = 0;j < style->numsurfaces;j++)
14040                                         update[list[j]] = true;
14041                         }
14042                 }
14043         }
14044
14045         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
14046
14047         if (debug)
14048         {
14049                 R_DrawDebugModel();
14050                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14051                 return;
14052         }
14053
14054         rsurface.lightmaptexture = NULL;
14055         rsurface.deluxemaptexture = NULL;
14056         rsurface.uselightmaptexture = false;
14057         rsurface.texture = NULL;
14058         rsurface.rtlight = NULL;
14059         numsurfacelist = 0;
14060         // add visible surfaces to draw list
14061         for (i = 0;i < model->nummodelsurfaces;i++)
14062                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
14063         // don't do anything if there were no surfaces
14064         if (!numsurfacelist)
14065         {
14066                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14067                 return;
14068         }
14069         // update lightmaps if needed
14070         if (update)
14071         {
14072                 int updated = 0;
14073                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14074                 {
14075                         if (update[j])
14076                         {
14077                                 updated++;
14078                                 R_BuildLightMap(ent, surfaces + j);
14079                         }
14080                 }
14081         }
14082         if (update)
14083                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
14084                         if (update[j])
14085                                 R_BuildLightMap(ent, surfaces + j);
14086         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
14087
14088         // add to stats if desired
14089         if (r_speeds.integer && !skysurfaces && !depthonly)
14090         {
14091                 r_refdef.stats.entities_surfaces += numsurfacelist;
14092                 for (j = 0;j < numsurfacelist;j++)
14093                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
14094         }
14095
14096         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
14097 }
14098
14099 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
14100 {
14101         static texture_t texture;
14102         static msurface_t surface;
14103         const msurface_t *surfacelist = &surface;
14104
14105         // fake enough texture and surface state to render this geometry
14106
14107         texture.update_lastrenderframe = -1; // regenerate this texture
14108         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
14109         texture.currentskinframe = skinframe;
14110         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
14111         texture.offsetmapping = OFFSETMAPPING_OFF;
14112         texture.offsetscale = 1;
14113         texture.specularscalemod = 1;
14114         texture.specularpowermod = 1;
14115
14116         surface.texture = &texture;
14117         surface.num_triangles = numtriangles;
14118         surface.num_firsttriangle = firsttriangle;
14119         surface.num_vertices = numvertices;
14120         surface.num_firstvertex = firstvertex;
14121
14122         // now render it
14123         rsurface.texture = R_GetCurrentTexture(surface.texture);
14124         rsurface.lightmaptexture = NULL;
14125         rsurface.deluxemaptexture = NULL;
14126         rsurface.uselightmaptexture = false;
14127         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14128 }
14129
14130 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)
14131 {
14132         static msurface_t surface;
14133         const msurface_t *surfacelist = &surface;
14134
14135         // fake enough texture and surface state to render this geometry
14136         surface.texture = texture;
14137         surface.num_triangles = numtriangles;
14138         surface.num_firsttriangle = firsttriangle;
14139         surface.num_vertices = numvertices;
14140         surface.num_firstvertex = firstvertex;
14141
14142         // now render it
14143         rsurface.texture = R_GetCurrentTexture(surface.texture);
14144         rsurface.lightmaptexture = NULL;
14145         rsurface.deluxemaptexture = NULL;
14146         rsurface.uselightmaptexture = false;
14147         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
14148 }