]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
added r_shadow_bouncegrid 2 which disables rtlights and just renders the
[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_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
78 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)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 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"};
82 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"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 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"};
85 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"};
86 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"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 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)"};
95 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)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 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."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 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."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 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"};
118 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"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 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"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
127
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
136
137 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)"};
138 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"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
152
153 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)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 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)"};
162 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)"};
163 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)"};
164 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)"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169
170 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)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 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"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
177
178 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
179 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
180 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
181 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
182
183 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
184 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
185 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
186 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
187 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
188 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
189 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
190
191 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
192 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
193 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
194 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)"};
195 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
196 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
197 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
200 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
201
202 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"};
203
204 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"};
205
206 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
207
208 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
209
210 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
211 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"};
212
213 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
214
215 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)"};
216
217 extern cvar_t v_glslgamma;
218
219 extern qboolean v_flipped_state;
220
221 static struct r_bloomstate_s
222 {
223         qboolean enabled;
224         qboolean hdr;
225
226         int bloomwidth, bloomheight;
227
228         textype_t texturetype;
229         int viewfbo; // used to check if r_viewfbo cvar has changed
230
231         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
232         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
233         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
234
235         int screentexturewidth, screentextureheight;
236         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
237
238         int bloomtexturewidth, bloomtextureheight;
239         rtexture_t *texture_bloom;
240
241         // arrays for rendering the screen passes
242         float screentexcoord2f[8];
243         float bloomtexcoord2f[8];
244         float offsettexcoord2f[8];
245
246         r_viewport_t viewport;
247 }
248 r_bloomstate;
249
250 r_waterstate_t r_waterstate;
251
252 /// shadow volume bsp struct with automatically growing nodes buffer
253 svbsp_t r_svbsp;
254
255 rtexture_t *r_texture_blanknormalmap;
256 rtexture_t *r_texture_white;
257 rtexture_t *r_texture_grey128;
258 rtexture_t *r_texture_black;
259 rtexture_t *r_texture_notexture;
260 rtexture_t *r_texture_whitecube;
261 rtexture_t *r_texture_normalizationcube;
262 rtexture_t *r_texture_fogattenuation;
263 rtexture_t *r_texture_fogheighttexture;
264 rtexture_t *r_texture_gammaramps;
265 unsigned int r_texture_gammaramps_serial;
266 //rtexture_t *r_texture_fogintensity;
267 rtexture_t *r_texture_reflectcube;
268
269 // TODO: hash lookups?
270 typedef struct cubemapinfo_s
271 {
272         char basename[64];
273         rtexture_t *texture;
274 }
275 cubemapinfo_t;
276
277 int r_texture_numcubemaps;
278 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
279
280 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
281 unsigned int r_numqueries;
282 unsigned int r_maxqueries;
283
284 typedef struct r_qwskincache_s
285 {
286         char name[MAX_QPATH];
287         skinframe_t *skinframe;
288 }
289 r_qwskincache_t;
290
291 static r_qwskincache_t *r_qwskincache;
292 static int r_qwskincache_size;
293
294 /// vertex coordinates for a quad that covers the screen exactly
295 extern const float r_screenvertex3f[12];
296 extern const float r_d3dscreenvertex3f[12];
297 const float r_screenvertex3f[12] =
298 {
299         0, 0, 0,
300         1, 0, 0,
301         1, 1, 0,
302         0, 1, 0
303 };
304 const float r_d3dscreenvertex3f[12] =
305 {
306         0, 1, 0,
307         1, 1, 0,
308         1, 0, 0,
309         0, 0, 0
310 };
311
312 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
313 {
314         int i;
315         for (i = 0;i < verts;i++)
316         {
317                 out[0] = in[0] * r;
318                 out[1] = in[1] * g;
319                 out[2] = in[2] * b;
320                 out[3] = in[3];
321                 in += 4;
322                 out += 4;
323         }
324 }
325
326 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
327 {
328         int i;
329         for (i = 0;i < verts;i++)
330         {
331                 out[0] = r;
332                 out[1] = g;
333                 out[2] = b;
334                 out[3] = a;
335                 out += 4;
336         }
337 }
338
339 // FIXME: move this to client?
340 void FOG_clear(void)
341 {
342         if (gamemode == GAME_NEHAHRA)
343         {
344                 Cvar_Set("gl_fogenable", "0");
345                 Cvar_Set("gl_fogdensity", "0.2");
346                 Cvar_Set("gl_fogred", "0.3");
347                 Cvar_Set("gl_foggreen", "0.3");
348                 Cvar_Set("gl_fogblue", "0.3");
349         }
350         r_refdef.fog_density = 0;
351         r_refdef.fog_red = 0;
352         r_refdef.fog_green = 0;
353         r_refdef.fog_blue = 0;
354         r_refdef.fog_alpha = 1;
355         r_refdef.fog_start = 0;
356         r_refdef.fog_end = 16384;
357         r_refdef.fog_height = 1<<30;
358         r_refdef.fog_fadedepth = 128;
359         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
360 }
361
362 static void R_BuildBlankTextures(void)
363 {
364         unsigned char data[4];
365         data[2] = 128; // normal X
366         data[1] = 128; // normal Y
367         data[0] = 255; // normal Z
368         data[3] = 128; // height
369         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 255;
371         data[1] = 255;
372         data[2] = 255;
373         data[3] = 255;
374         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 128;
376         data[1] = 128;
377         data[2] = 128;
378         data[3] = 255;
379         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 0;
381         data[1] = 0;
382         data[2] = 0;
383         data[3] = 255;
384         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNoTexture(void)
388 {
389         int x, y;
390         unsigned char pix[16][16][4];
391         // this makes a light grey/dark grey checkerboard texture
392         for (y = 0;y < 16;y++)
393         {
394                 for (x = 0;x < 16;x++)
395                 {
396                         if ((y < 8) ^ (x < 8))
397                         {
398                                 pix[y][x][0] = 128;
399                                 pix[y][x][1] = 128;
400                                 pix[y][x][2] = 128;
401                                 pix[y][x][3] = 255;
402                         }
403                         else
404                         {
405                                 pix[y][x][0] = 64;
406                                 pix[y][x][1] = 64;
407                                 pix[y][x][2] = 64;
408                                 pix[y][x][3] = 255;
409                         }
410                 }
411         }
412         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
413 }
414
415 static void R_BuildWhiteCube(void)
416 {
417         unsigned char data[6*1*1*4];
418         memset(data, 255, sizeof(data));
419         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
420 }
421
422 static void R_BuildNormalizationCube(void)
423 {
424         int x, y, side;
425         vec3_t v;
426         vec_t s, t, intensity;
427 #define NORMSIZE 64
428         unsigned char *data;
429         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
430         for (side = 0;side < 6;side++)
431         {
432                 for (y = 0;y < NORMSIZE;y++)
433                 {
434                         for (x = 0;x < NORMSIZE;x++)
435                         {
436                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
438                                 switch(side)
439                                 {
440                                 default:
441                                 case 0:
442                                         v[0] = 1;
443                                         v[1] = -t;
444                                         v[2] = -s;
445                                         break;
446                                 case 1:
447                                         v[0] = -1;
448                                         v[1] = -t;
449                                         v[2] = s;
450                                         break;
451                                 case 2:
452                                         v[0] = s;
453                                         v[1] = 1;
454                                         v[2] = t;
455                                         break;
456                                 case 3:
457                                         v[0] = s;
458                                         v[1] = -1;
459                                         v[2] = -t;
460                                         break;
461                                 case 4:
462                                         v[0] = s;
463                                         v[1] = -t;
464                                         v[2] = 1;
465                                         break;
466                                 case 5:
467                                         v[0] = -s;
468                                         v[1] = -t;
469                                         v[2] = -1;
470                                         break;
471                                 }
472                                 intensity = 127.0f / sqrt(DotProduct(v, v));
473                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
474                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
475                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
476                                 data[((side*64+y)*64+x)*4+3] = 255;
477                         }
478                 }
479         }
480         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
481         Mem_Free(data);
482 }
483
484 static void R_BuildFogTexture(void)
485 {
486         int x, b;
487 #define FOGWIDTH 256
488         unsigned char data1[FOGWIDTH][4];
489         //unsigned char data2[FOGWIDTH][4];
490         double d, r, alpha;
491
492         r_refdef.fogmasktable_start = r_refdef.fog_start;
493         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
494         r_refdef.fogmasktable_range = r_refdef.fogrange;
495         r_refdef.fogmasktable_density = r_refdef.fog_density;
496
497         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
498         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
499         {
500                 d = (x * r - r_refdef.fogmasktable_start);
501                 if(developer_extra.integer)
502                         Con_DPrintf("%f ", d);
503                 d = max(0, d);
504                 if (r_fog_exp2.integer)
505                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
506                 else
507                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
508                 if(developer_extra.integer)
509                         Con_DPrintf(" : %f ", alpha);
510                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
511                 if(developer_extra.integer)
512                         Con_DPrintf(" = %f\n", alpha);
513                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
514         }
515
516         for (x = 0;x < FOGWIDTH;x++)
517         {
518                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
519                 data1[x][0] = b;
520                 data1[x][1] = b;
521                 data1[x][2] = b;
522                 data1[x][3] = 255;
523                 //data2[x][0] = 255 - b;
524                 //data2[x][1] = 255 - b;
525                 //data2[x][2] = 255 - b;
526                 //data2[x][3] = 255;
527         }
528         if (r_texture_fogattenuation)
529         {
530                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
531                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
532         }
533         else
534         {
535                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
536                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
537         }
538 }
539
540 static void R_BuildFogHeightTexture(void)
541 {
542         unsigned char *inpixels;
543         int size;
544         int x;
545         int y;
546         int j;
547         float c[4];
548         float f;
549         inpixels = NULL;
550         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
551         if (r_refdef.fogheighttexturename[0])
552                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
553         if (!inpixels)
554         {
555                 r_refdef.fog_height_tablesize = 0;
556                 if (r_texture_fogheighttexture)
557                         R_FreeTexture(r_texture_fogheighttexture);
558                 r_texture_fogheighttexture = NULL;
559                 if (r_refdef.fog_height_table2d)
560                         Mem_Free(r_refdef.fog_height_table2d);
561                 r_refdef.fog_height_table2d = NULL;
562                 if (r_refdef.fog_height_table1d)
563                         Mem_Free(r_refdef.fog_height_table1d);
564                 r_refdef.fog_height_table1d = NULL;
565                 return;
566         }
567         size = image_width;
568         r_refdef.fog_height_tablesize = size;
569         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
570         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
571         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
572         Mem_Free(inpixels);
573         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
574         // average fog color table accounting for every fog layer between a point
575         // and the camera.  (Note: attenuation is handled separately!)
576         for (y = 0;y < size;y++)
577         {
578                 for (x = 0;x < size;x++)
579                 {
580                         Vector4Clear(c);
581                         f = 0;
582                         if (x < y)
583                         {
584                                 for (j = x;j <= y;j++)
585                                 {
586                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
587                                         f++;
588                                 }
589                         }
590                         else
591                         {
592                                 for (j = x;j >= y;j--)
593                                 {
594                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
595                                         f++;
596                                 }
597                         }
598                         f = 1.0f / f;
599                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
600                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
601                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
602                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
603                 }
604         }
605         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
606 }
607
608 //=======================================================================================================================================================
609
610 static const char *builtinshaderstring =
611 #include "shader_glsl.h"
612 ;
613
614 const char *builtinhlslshaderstring =
615 #include "shader_hlsl.h"
616 ;
617
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
620
621 //=======================================================================================================================================================
622
623 typedef struct shaderpermutationinfo_s
624 {
625         const char *pretext;
626         const char *name;
627 }
628 shaderpermutationinfo_t;
629
630 typedef struct shadermodeinfo_s
631 {
632         const char *vertexfilename;
633         const char *geometryfilename;
634         const char *fragmentfilename;
635         const char *pretext;
636         const char *name;
637 }
638 shadermodeinfo_t;
639
640 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
641 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
642 {
643         {"#define USEDIFFUSE\n", " diffuse"},
644         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
645         {"#define USEVIEWTINT\n", " viewtint"},
646         {"#define USECOLORMAPPING\n", " colormapping"},
647         {"#define USESATURATION\n", " saturation"},
648         {"#define USEFOGINSIDE\n", " foginside"},
649         {"#define USEFOGOUTSIDE\n", " fogoutside"},
650         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
651         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
652         {"#define USEGAMMARAMPS\n", " gammaramps"},
653         {"#define USECUBEFILTER\n", " cubefilter"},
654         {"#define USEGLOW\n", " glow"},
655         {"#define USEBLOOM\n", " bloom"},
656         {"#define USESPECULAR\n", " specular"},
657         {"#define USEPOSTPROCESSING\n", " postprocessing"},
658         {"#define USEREFLECTION\n", " reflection"},
659         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
660         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
661         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
662         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
663         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
664         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
665         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
666         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668         {"#define USEALPHAKILL\n", " alphakill"},
669         {"#define USEREFLECTCUBE\n", " reflectcube"},
670         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671         {"#define USEBOUNCEGRID\n", " bouncegrid"},
672         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
673         {"#define USETRIPPY\n", " trippy"},
674 };
675
676 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
677 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
678 {
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
681         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
695 };
696
697 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
698 {
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
715 };
716
717 struct r_glsl_permutation_s;
718 typedef struct r_glsl_permutation_s
719 {
720         /// hash lookup data
721         struct r_glsl_permutation_s *hashnext;
722         unsigned int mode;
723         unsigned int permutation;
724
725         /// indicates if we have tried compiling this permutation already
726         qboolean compiled;
727         /// 0 if compilation failed
728         int program;
729         // texture units assigned to each detected uniform
730         int tex_Texture_First;
731         int tex_Texture_Second;
732         int tex_Texture_GammaRamps;
733         int tex_Texture_Normal;
734         int tex_Texture_Color;
735         int tex_Texture_Gloss;
736         int tex_Texture_Glow;
737         int tex_Texture_SecondaryNormal;
738         int tex_Texture_SecondaryColor;
739         int tex_Texture_SecondaryGloss;
740         int tex_Texture_SecondaryGlow;
741         int tex_Texture_Pants;
742         int tex_Texture_Shirt;
743         int tex_Texture_FogHeightTexture;
744         int tex_Texture_FogMask;
745         int tex_Texture_Lightmap;
746         int tex_Texture_Deluxemap;
747         int tex_Texture_Attenuation;
748         int tex_Texture_Cube;
749         int tex_Texture_Refraction;
750         int tex_Texture_Reflection;
751         int tex_Texture_ShadowMap2D;
752         int tex_Texture_CubeProjection;
753         int tex_Texture_ScreenDepth;
754         int tex_Texture_ScreenNormalMap;
755         int tex_Texture_ScreenDiffuse;
756         int tex_Texture_ScreenSpecular;
757         int tex_Texture_ReflectMask;
758         int tex_Texture_ReflectCube;
759         int tex_Texture_BounceGrid;
760         /// locations of detected uniforms in program object, or -1 if not found
761         int loc_Texture_First;
762         int loc_Texture_Second;
763         int loc_Texture_GammaRamps;
764         int loc_Texture_Normal;
765         int loc_Texture_Color;
766         int loc_Texture_Gloss;
767         int loc_Texture_Glow;
768         int loc_Texture_SecondaryNormal;
769         int loc_Texture_SecondaryColor;
770         int loc_Texture_SecondaryGloss;
771         int loc_Texture_SecondaryGlow;
772         int loc_Texture_Pants;
773         int loc_Texture_Shirt;
774         int loc_Texture_FogHeightTexture;
775         int loc_Texture_FogMask;
776         int loc_Texture_Lightmap;
777         int loc_Texture_Deluxemap;
778         int loc_Texture_Attenuation;
779         int loc_Texture_Cube;
780         int loc_Texture_Refraction;
781         int loc_Texture_Reflection;
782         int loc_Texture_ShadowMap2D;
783         int loc_Texture_CubeProjection;
784         int loc_Texture_ScreenDepth;
785         int loc_Texture_ScreenNormalMap;
786         int loc_Texture_ScreenDiffuse;
787         int loc_Texture_ScreenSpecular;
788         int loc_Texture_ReflectMask;
789         int loc_Texture_ReflectCube;
790         int loc_Texture_BounceGrid;
791         int loc_Alpha;
792         int loc_BloomBlur_Parameters;
793         int loc_ClientTime;
794         int loc_Color_Ambient;
795         int loc_Color_Diffuse;
796         int loc_Color_Specular;
797         int loc_Color_Glow;
798         int loc_Color_Pants;
799         int loc_Color_Shirt;
800         int loc_DeferredColor_Ambient;
801         int loc_DeferredColor_Diffuse;
802         int loc_DeferredColor_Specular;
803         int loc_DeferredMod_Diffuse;
804         int loc_DeferredMod_Specular;
805         int loc_DistortScaleRefractReflect;
806         int loc_EyePosition;
807         int loc_FogColor;
808         int loc_FogHeightFade;
809         int loc_FogPlane;
810         int loc_FogPlaneViewDist;
811         int loc_FogRangeRecip;
812         int loc_LightColor;
813         int loc_LightDir;
814         int loc_LightPosition;
815         int loc_OffsetMapping_ScaleSteps;
816         int loc_PixelSize;
817         int loc_ReflectColor;
818         int loc_ReflectFactor;
819         int loc_ReflectOffset;
820         int loc_RefractColor;
821         int loc_Saturation;
822         int loc_ScreenCenterRefractReflect;
823         int loc_ScreenScaleRefractReflect;
824         int loc_ScreenToDepth;
825         int loc_ShadowMap_Parameters;
826         int loc_ShadowMap_TextureScale;
827         int loc_SpecularPower;
828         int loc_UserVec1;
829         int loc_UserVec2;
830         int loc_UserVec3;
831         int loc_UserVec4;
832         int loc_ViewTintColor;
833         int loc_ViewToLight;
834         int loc_ModelToLight;
835         int loc_TexMatrix;
836         int loc_BackgroundTexMatrix;
837         int loc_ModelViewProjectionMatrix;
838         int loc_ModelViewMatrix;
839         int loc_PixelToScreenTexCoord;
840         int loc_ModelToReflectCube;
841         int loc_ShadowMapMatrix;
842         int loc_BloomColorSubtract;
843         int loc_NormalmapScrollBlend;
844         int loc_BounceGridMatrix;
845         int loc_BounceGridIntensity;
846 }
847 r_glsl_permutation_t;
848
849 #define SHADERPERMUTATION_HASHSIZE 256
850
851
852 // non-degradable "lightweight" shader parameters to keep the permutations simpler
853 // these can NOT degrade! only use for simple stuff
854 enum
855 {
856         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
857         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
858         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
861         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
862         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
863 };
864 #define SHADERSTATICPARMS_COUNT 7
865
866 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
867 static int shaderstaticparms_count = 0;
868
869 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
870 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
871 qboolean R_CompileShader_CheckStaticParms(void)
872 {
873         static int r_compileshader_staticparms_save[1];
874         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
875         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
876
877         // detect all
878         if (r_glsl_saturation_redcompensate.integer)
879                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
880         if (r_glsl_vertextextureblend_usebothalphas.integer)
881                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
882         if (r_shadow_glossexact.integer)
883                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
884         if (r_glsl_postprocess.integer)
885         {
886                 if (r_glsl_postprocess_uservec1_enable.integer)
887                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
888                 if (r_glsl_postprocess_uservec2_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
890                 if (r_glsl_postprocess_uservec3_enable.integer)
891                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
892                 if (r_glsl_postprocess_uservec4_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
894         }
895         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
896 }
897
898 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
899         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
900                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
901         else \
902                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
903 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
904 {
905         shaderstaticparms_count = 0;
906
907         // emit all
908         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
909         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
910         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
911         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
912         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
915 }
916
917 /// information about each possible shader permutation
918 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
919 /// currently selected permutation
920 r_glsl_permutation_t *r_glsl_permutation;
921 /// storage for permutations linked in the hash table
922 memexpandablearray_t r_glsl_permutationarray;
923
924 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
925 {
926         //unsigned int hashdepth = 0;
927         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
928         r_glsl_permutation_t *p;
929         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
930         {
931                 if (p->mode == mode && p->permutation == permutation)
932                 {
933                         //if (hashdepth > 10)
934                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
935                         return p;
936                 }
937                 //hashdepth++;
938         }
939         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
940         p->mode = mode;
941         p->permutation = permutation;
942         p->hashnext = r_glsl_permutationhash[mode][hashindex];
943         r_glsl_permutationhash[mode][hashindex] = p;
944         //if (hashdepth > 10)
945         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
946         return p;
947 }
948
949 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
950 {
951         char *shaderstring;
952         if (!filename || !filename[0])
953                 return NULL;
954         if (!strcmp(filename, "glsl/default.glsl"))
955         {
956                 if (!glslshaderstring)
957                 {
958                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
959                         if (glslshaderstring)
960                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
961                         else
962                                 glslshaderstring = (char *)builtinshaderstring;
963                 }
964                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
965                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
966                 return shaderstring;
967         }
968         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
969         if (shaderstring)
970         {
971                 if (printfromdisknotice)
972                         Con_DPrintf("from disk %s... ", filename);
973                 return shaderstring;
974         }
975         return shaderstring;
976 }
977
978 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
979 {
980         int i;
981         int sampler;
982         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
983         char *vertexstring, *geometrystring, *fragmentstring;
984         char permutationname[256];
985         int vertstrings_count = 0;
986         int geomstrings_count = 0;
987         int fragstrings_count = 0;
988         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
990         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
991
992         if (p->compiled)
993                 return;
994         p->compiled = true;
995         p->program = 0;
996
997         permutationname[0] = 0;
998         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
999         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1000         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1001
1002         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1003
1004         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1005         if(vid.support.gl20shaders130)
1006         {
1007                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1008                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1009                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1010                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1011                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1012                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1013         }
1014
1015         // the first pretext is which type of shader to compile as
1016         // (later these will all be bound together as a program object)
1017         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1018         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1019         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1020
1021         // the second pretext is the mode (for example a light source)
1022         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1023         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1024         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1025         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1026
1027         // now add all the permutation pretexts
1028         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1029         {
1030                 if (permutation & (1<<i))
1031                 {
1032                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1033                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1034                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1035                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1036                 }
1037                 else
1038                 {
1039                         // keep line numbers correct
1040                         vertstrings_list[vertstrings_count++] = "\n";
1041                         geomstrings_list[geomstrings_count++] = "\n";
1042                         fragstrings_list[fragstrings_count++] = "\n";
1043                 }
1044         }
1045
1046         // add static parms
1047         R_CompileShader_AddStaticParms(mode, permutation);
1048         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1049         vertstrings_count += shaderstaticparms_count;
1050         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1051         geomstrings_count += shaderstaticparms_count;
1052         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1053         fragstrings_count += shaderstaticparms_count;
1054
1055         // now append the shader text itself
1056         vertstrings_list[vertstrings_count++] = vertexstring;
1057         geomstrings_list[geomstrings_count++] = geometrystring;
1058         fragstrings_list[fragstrings_count++] = fragmentstring;
1059
1060         // if any sources were NULL, clear the respective list
1061         if (!vertexstring)
1062                 vertstrings_count = 0;
1063         if (!geometrystring)
1064                 geomstrings_count = 0;
1065         if (!fragmentstring)
1066                 fragstrings_count = 0;
1067
1068         // compile the shader program
1069         if (vertstrings_count + geomstrings_count + fragstrings_count)
1070                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1071         if (p->program)
1072         {
1073                 CHECKGLERROR
1074                 qglUseProgram(p->program);CHECKGLERROR
1075                 // look up all the uniform variable names we care about, so we don't
1076                 // have to look them up every time we set them
1077
1078                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1079                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1080                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1081                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1082                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1083                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1084                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1085                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1086                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1087                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1088                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1089                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1090                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1091                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1092                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1093                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1094                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1095                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1096                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1097                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1098                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1099                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1100                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1101                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1102                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1103                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1104                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1105                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1106                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1107                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1108                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1109                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1110                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1111                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1112                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1113                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1114                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1115                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1116                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1117                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1118                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1119                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1120                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1121                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1122                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1123                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1124                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1125                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1126                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1127                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1128                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1129                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1130                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1131                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1132                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1133                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1134                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1135                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1136                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1137                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1138                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1139                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1140                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1141                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1142                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1143                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1144                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1145                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1146                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1147                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1148                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1149                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1150                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1151                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1152                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1153                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1154                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1155                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1156                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1157                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1158                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1159                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1160                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1161                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1162                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1163                 // initialize the samplers to refer to the texture units we use
1164                 p->tex_Texture_First = -1;
1165                 p->tex_Texture_Second = -1;
1166                 p->tex_Texture_GammaRamps = -1;
1167                 p->tex_Texture_Normal = -1;
1168                 p->tex_Texture_Color = -1;
1169                 p->tex_Texture_Gloss = -1;
1170                 p->tex_Texture_Glow = -1;
1171                 p->tex_Texture_SecondaryNormal = -1;
1172                 p->tex_Texture_SecondaryColor = -1;
1173                 p->tex_Texture_SecondaryGloss = -1;
1174                 p->tex_Texture_SecondaryGlow = -1;
1175                 p->tex_Texture_Pants = -1;
1176                 p->tex_Texture_Shirt = -1;
1177                 p->tex_Texture_FogHeightTexture = -1;
1178                 p->tex_Texture_FogMask = -1;
1179                 p->tex_Texture_Lightmap = -1;
1180                 p->tex_Texture_Deluxemap = -1;
1181                 p->tex_Texture_Attenuation = -1;
1182                 p->tex_Texture_Cube = -1;
1183                 p->tex_Texture_Refraction = -1;
1184                 p->tex_Texture_Reflection = -1;
1185                 p->tex_Texture_ShadowMap2D = -1;
1186                 p->tex_Texture_CubeProjection = -1;
1187                 p->tex_Texture_ScreenDepth = -1;
1188                 p->tex_Texture_ScreenNormalMap = -1;
1189                 p->tex_Texture_ScreenDiffuse = -1;
1190                 p->tex_Texture_ScreenSpecular = -1;
1191                 p->tex_Texture_ReflectMask = -1;
1192                 p->tex_Texture_ReflectCube = -1;
1193                 p->tex_Texture_BounceGrid = -1;
1194                 sampler = 0;
1195                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1196                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1197                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1198                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1199                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1200                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1201                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1202                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1203                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1204                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1205                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1206                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1207                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1208                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1209                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1210                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1211                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1212                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1213                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1214                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1215                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1216                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1217                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1218                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1219                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1220                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1221                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1222                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1223                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1224                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1225                 CHECKGLERROR
1226                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1227         }
1228         else
1229                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1230
1231         // free the strings
1232         if (vertexstring)
1233                 Mem_Free(vertexstring);
1234         if (geometrystring)
1235                 Mem_Free(geometrystring);
1236         if (fragmentstring)
1237                 Mem_Free(fragmentstring);
1238 }
1239
1240 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1241 {
1242         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1243         if (r_glsl_permutation != perm)
1244         {
1245                 r_glsl_permutation = perm;
1246                 if (!r_glsl_permutation->program)
1247                 {
1248                         if (!r_glsl_permutation->compiled)
1249                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1250                         if (!r_glsl_permutation->program)
1251                         {
1252                                 // remove features until we find a valid permutation
1253                                 int i;
1254                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1255                                 {
1256                                         // reduce i more quickly whenever it would not remove any bits
1257                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1258                                         if (!(permutation & j))
1259                                                 continue;
1260                                         permutation -= j;
1261                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1262                                         if (!r_glsl_permutation->compiled)
1263                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1264                                         if (r_glsl_permutation->program)
1265                                                 break;
1266                                 }
1267                                 if (i >= SHADERPERMUTATION_COUNT)
1268                                 {
1269                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1270                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1271                                         qglUseProgram(0);CHECKGLERROR
1272                                         return; // no bit left to clear, entire mode is broken
1273                                 }
1274                         }
1275                 }
1276                 CHECKGLERROR
1277                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1278         }
1279         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1280         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1281         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1282 }
1283
1284 #ifdef SUPPORTD3D
1285
1286 #ifdef SUPPORTD3D
1287 #include <d3d9.h>
1288 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1289 extern D3DCAPS9 vid_d3d9caps;
1290 #endif
1291
1292 struct r_hlsl_permutation_s;
1293 typedef struct r_hlsl_permutation_s
1294 {
1295         /// hash lookup data
1296         struct r_hlsl_permutation_s *hashnext;
1297         unsigned int mode;
1298         unsigned int permutation;
1299
1300         /// indicates if we have tried compiling this permutation already
1301         qboolean compiled;
1302         /// NULL if compilation failed
1303         IDirect3DVertexShader9 *vertexshader;
1304         IDirect3DPixelShader9 *pixelshader;
1305 }
1306 r_hlsl_permutation_t;
1307
1308 typedef enum D3DVSREGISTER_e
1309 {
1310         D3DVSREGISTER_TexMatrix = 0, // float4x4
1311         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1312         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1313         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1314         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1315         D3DVSREGISTER_ModelToLight = 20, // float4x4
1316         D3DVSREGISTER_EyePosition = 24,
1317         D3DVSREGISTER_FogPlane = 25,
1318         D3DVSREGISTER_LightDir = 26,
1319         D3DVSREGISTER_LightPosition = 27,
1320 }
1321 D3DVSREGISTER_t;
1322
1323 typedef enum D3DPSREGISTER_e
1324 {
1325         D3DPSREGISTER_Alpha = 0,
1326         D3DPSREGISTER_BloomBlur_Parameters = 1,
1327         D3DPSREGISTER_ClientTime = 2,
1328         D3DPSREGISTER_Color_Ambient = 3,
1329         D3DPSREGISTER_Color_Diffuse = 4,
1330         D3DPSREGISTER_Color_Specular = 5,
1331         D3DPSREGISTER_Color_Glow = 6,
1332         D3DPSREGISTER_Color_Pants = 7,
1333         D3DPSREGISTER_Color_Shirt = 8,
1334         D3DPSREGISTER_DeferredColor_Ambient = 9,
1335         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1336         D3DPSREGISTER_DeferredColor_Specular = 11,
1337         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1338         D3DPSREGISTER_DeferredMod_Specular = 13,
1339         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1340         D3DPSREGISTER_EyePosition = 15, // unused
1341         D3DPSREGISTER_FogColor = 16,
1342         D3DPSREGISTER_FogHeightFade = 17,
1343         D3DPSREGISTER_FogPlane = 18,
1344         D3DPSREGISTER_FogPlaneViewDist = 19,
1345         D3DPSREGISTER_FogRangeRecip = 20,
1346         D3DPSREGISTER_LightColor = 21,
1347         D3DPSREGISTER_LightDir = 22, // unused
1348         D3DPSREGISTER_LightPosition = 23,
1349         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1350         D3DPSREGISTER_PixelSize = 25,
1351         D3DPSREGISTER_ReflectColor = 26,
1352         D3DPSREGISTER_ReflectFactor = 27,
1353         D3DPSREGISTER_ReflectOffset = 28,
1354         D3DPSREGISTER_RefractColor = 29,
1355         D3DPSREGISTER_Saturation = 30,
1356         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1357         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1358         D3DPSREGISTER_ScreenToDepth = 33,
1359         D3DPSREGISTER_ShadowMap_Parameters = 34,
1360         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1361         D3DPSREGISTER_SpecularPower = 36,
1362         D3DPSREGISTER_UserVec1 = 37,
1363         D3DPSREGISTER_UserVec2 = 38,
1364         D3DPSREGISTER_UserVec3 = 39,
1365         D3DPSREGISTER_UserVec4 = 40,
1366         D3DPSREGISTER_ViewTintColor = 41,
1367         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1368         D3DPSREGISTER_BloomColorSubtract = 43,
1369         D3DPSREGISTER_ViewToLight = 44, // float4x4
1370         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1371         D3DPSREGISTER_NormalmapScrollBlend = 52,
1372         // next at 53
1373 }
1374 D3DPSREGISTER_t;
1375
1376 /// information about each possible shader permutation
1377 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1378 /// currently selected permutation
1379 r_hlsl_permutation_t *r_hlsl_permutation;
1380 /// storage for permutations linked in the hash table
1381 memexpandablearray_t r_hlsl_permutationarray;
1382
1383 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1384 {
1385         //unsigned int hashdepth = 0;
1386         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1387         r_hlsl_permutation_t *p;
1388         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1389         {
1390                 if (p->mode == mode && p->permutation == permutation)
1391                 {
1392                         //if (hashdepth > 10)
1393                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1394                         return p;
1395                 }
1396                 //hashdepth++;
1397         }
1398         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1399         p->mode = mode;
1400         p->permutation = permutation;
1401         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1402         r_hlsl_permutationhash[mode][hashindex] = p;
1403         //if (hashdepth > 10)
1404         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1405         return p;
1406 }
1407
1408 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1409 {
1410         char *shaderstring;
1411         if (!filename || !filename[0])
1412                 return NULL;
1413         if (!strcmp(filename, "hlsl/default.hlsl"))
1414         {
1415                 if (!hlslshaderstring)
1416                 {
1417                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1418                         if (hlslshaderstring)
1419                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1420                         else
1421                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1422                 }
1423                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1424                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1425                 return shaderstring;
1426         }
1427         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1428         if (shaderstring)
1429         {
1430                 if (printfromdisknotice)
1431                         Con_DPrintf("from disk %s... ", filename);
1432                 return shaderstring;
1433         }
1434         return shaderstring;
1435 }
1436
1437 #include <d3dx9.h>
1438 //#include <d3dx9shader.h>
1439 //#include <d3dx9mesh.h>
1440
1441 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1442 {
1443         DWORD *vsbin = NULL;
1444         DWORD *psbin = NULL;
1445         fs_offset_t vsbinsize;
1446         fs_offset_t psbinsize;
1447 //      IDirect3DVertexShader9 *vs = NULL;
1448 //      IDirect3DPixelShader9 *ps = NULL;
1449         ID3DXBuffer *vslog = NULL;
1450         ID3DXBuffer *vsbuffer = NULL;
1451         ID3DXConstantTable *vsconstanttable = NULL;
1452         ID3DXBuffer *pslog = NULL;
1453         ID3DXBuffer *psbuffer = NULL;
1454         ID3DXConstantTable *psconstanttable = NULL;
1455         int vsresult = 0;
1456         int psresult = 0;
1457         char temp[MAX_INPUTLINE];
1458         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1459         qboolean debugshader = gl_paranoid.integer != 0;
1460         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1461         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1462         if (!debugshader)
1463         {
1464                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1465                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1466         }
1467         if ((!vsbin && vertstring) || (!psbin && fragstring))
1468         {
1469                 const char* dllnames_d3dx9 [] =
1470                 {
1471                         "d3dx9_43.dll",
1472                         "d3dx9_42.dll",
1473                         "d3dx9_41.dll",
1474                         "d3dx9_40.dll",
1475                         "d3dx9_39.dll",
1476                         "d3dx9_38.dll",
1477                         "d3dx9_37.dll",
1478                         "d3dx9_36.dll",
1479                         "d3dx9_35.dll",
1480                         "d3dx9_34.dll",
1481                         "d3dx9_33.dll",
1482                         "d3dx9_32.dll",
1483                         "d3dx9_31.dll",
1484                         "d3dx9_30.dll",
1485                         "d3dx9_29.dll",
1486                         "d3dx9_28.dll",
1487                         "d3dx9_27.dll",
1488                         "d3dx9_26.dll",
1489                         "d3dx9_25.dll",
1490                         "d3dx9_24.dll",
1491                         NULL
1492                 };
1493                 dllhandle_t d3dx9_dll = NULL;
1494                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1495                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1496                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1497                 dllfunction_t d3dx9_dllfuncs[] =
1498                 {
1499                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1500                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1501                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1502                         {NULL, NULL}
1503                 };
1504                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1505                 {
1506                         DWORD shaderflags = 0;
1507                         if (debugshader)
1508                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1509                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1510                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1511                         if (vertstring && vertstring[0])
1512                         {
1513                                 if (debugshader)
1514                                 {
1515 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1516 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1517                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1518                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1519                                 }
1520                                 else
1521                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1522                                 if (vsbuffer)
1523                                 {
1524                                         vsbinsize = vsbuffer->GetBufferSize();
1525                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1526                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1527                                         vsbuffer->Release();
1528                                 }
1529                                 if (vslog)
1530                                 {
1531                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1532                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1533                                         vslog->Release();
1534                                 }
1535                         }
1536                         if (fragstring && fragstring[0])
1537                         {
1538                                 if (debugshader)
1539                                 {
1540 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1541 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1542                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1543                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1544                                 }
1545                                 else
1546                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1547                                 if (psbuffer)
1548                                 {
1549                                         psbinsize = psbuffer->GetBufferSize();
1550                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1551                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1552                                         psbuffer->Release();
1553                                 }
1554                                 if (pslog)
1555                                 {
1556                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1557                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1558                                         pslog->Release();
1559                                 }
1560                         }
1561                         Sys_UnloadLibrary(&d3dx9_dll);
1562                 }
1563                 else
1564                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1565         }
1566         if (vsbin && psbin)
1567         {
1568                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1569                 if (FAILED(vsresult))
1570                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1571                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1572                 if (FAILED(psresult))
1573                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1574         }
1575         // free the shader data
1576         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1577         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1578 }
1579
1580 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1581 {
1582         int i;
1583         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1584         int vertstring_length = 0;
1585         int geomstring_length = 0;
1586         int fragstring_length = 0;
1587         char *t;
1588         char *vertexstring, *geometrystring, *fragmentstring;
1589         char *vertstring, *geomstring, *fragstring;
1590         char permutationname[256];
1591         char cachename[256];
1592         int vertstrings_count = 0;
1593         int geomstrings_count = 0;
1594         int fragstrings_count = 0;
1595         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1597         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1598
1599         if (p->compiled)
1600                 return;
1601         p->compiled = true;
1602         p->vertexshader = NULL;
1603         p->pixelshader = NULL;
1604
1605         permutationname[0] = 0;
1606         cachename[0] = 0;
1607         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1608         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1609         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1610
1611         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1612         strlcat(cachename, "hlsl/", sizeof(cachename));
1613
1614         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1615         vertstrings_count = 0;
1616         geomstrings_count = 0;
1617         fragstrings_count = 0;
1618         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1619         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1620         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1621
1622         // the first pretext is which type of shader to compile as
1623         // (later these will all be bound together as a program object)
1624         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1625         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1626         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1627
1628         // the second pretext is the mode (for example a light source)
1629         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1630         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1631         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1632         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1633         strlcat(cachename, modeinfo->name, sizeof(cachename));
1634
1635         // now add all the permutation pretexts
1636         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1637         {
1638                 if (permutation & (1<<i))
1639                 {
1640                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1641                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1642                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1643                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1644                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1645                 }
1646                 else
1647                 {
1648                         // keep line numbers correct
1649                         vertstrings_list[vertstrings_count++] = "\n";
1650                         geomstrings_list[geomstrings_count++] = "\n";
1651                         fragstrings_list[fragstrings_count++] = "\n";
1652                 }
1653         }
1654
1655         // add static parms
1656         R_CompileShader_AddStaticParms(mode, permutation);
1657         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1658         vertstrings_count += shaderstaticparms_count;
1659         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1660         geomstrings_count += shaderstaticparms_count;
1661         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1662         fragstrings_count += shaderstaticparms_count;
1663
1664         // replace spaces in the cachename with _ characters
1665         for (i = 0;cachename[i];i++)
1666                 if (cachename[i] == ' ')
1667                         cachename[i] = '_';
1668
1669         // now append the shader text itself
1670         vertstrings_list[vertstrings_count++] = vertexstring;
1671         geomstrings_list[geomstrings_count++] = geometrystring;
1672         fragstrings_list[fragstrings_count++] = fragmentstring;
1673
1674         // if any sources were NULL, clear the respective list
1675         if (!vertexstring)
1676                 vertstrings_count = 0;
1677         if (!geometrystring)
1678                 geomstrings_count = 0;
1679         if (!fragmentstring)
1680                 fragstrings_count = 0;
1681
1682         vertstring_length = 0;
1683         for (i = 0;i < vertstrings_count;i++)
1684                 vertstring_length += strlen(vertstrings_list[i]);
1685         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1686         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1687                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1688
1689         geomstring_length = 0;
1690         for (i = 0;i < geomstrings_count;i++)
1691                 geomstring_length += strlen(geomstrings_list[i]);
1692         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1693         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1694                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1695
1696         fragstring_length = 0;
1697         for (i = 0;i < fragstrings_count;i++)
1698                 fragstring_length += strlen(fragstrings_list[i]);
1699         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1700         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1701                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1702
1703         // try to load the cached shader, or generate one
1704         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1705
1706         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1707                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1708         else
1709                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1710
1711         // free the strings
1712         if (vertstring)
1713                 Mem_Free(vertstring);
1714         if (geomstring)
1715                 Mem_Free(geomstring);
1716         if (fragstring)
1717                 Mem_Free(fragstring);
1718         if (vertexstring)
1719                 Mem_Free(vertexstring);
1720         if (geometrystring)
1721                 Mem_Free(geometrystring);
1722         if (fragmentstring)
1723                 Mem_Free(fragmentstring);
1724 }
1725
1726 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1727 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1728 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);}
1729 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);}
1730 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);}
1731 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);}
1732
1733 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1734 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1735 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);}
1736 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);}
1737 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);}
1738 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);}
1739
1740 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1741 {
1742         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1743         if (r_hlsl_permutation != perm)
1744         {
1745                 r_hlsl_permutation = perm;
1746                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1747                 {
1748                         if (!r_hlsl_permutation->compiled)
1749                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1750                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1751                         {
1752                                 // remove features until we find a valid permutation
1753                                 int i;
1754                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1755                                 {
1756                                         // reduce i more quickly whenever it would not remove any bits
1757                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1758                                         if (!(permutation & j))
1759                                                 continue;
1760                                         permutation -= j;
1761                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1762                                         if (!r_hlsl_permutation->compiled)
1763                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1764                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1765                                                 break;
1766                                 }
1767                                 if (i >= SHADERPERMUTATION_COUNT)
1768                                 {
1769                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1770                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1771                                         return; // no bit left to clear, entire mode is broken
1772                                 }
1773                         }
1774                 }
1775                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1776                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1777         }
1778         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1779         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1780         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1781 }
1782 #endif
1783
1784 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1785 {
1786         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1787         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1788         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1789         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1790 }
1791
1792 void R_GLSL_Restart_f(void)
1793 {
1794         unsigned int i, limit;
1795         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1796                 Mem_Free(glslshaderstring);
1797         glslshaderstring = NULL;
1798         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1799                 Mem_Free(hlslshaderstring);
1800         hlslshaderstring = NULL;
1801         switch(vid.renderpath)
1802         {
1803         case RENDERPATH_D3D9:
1804 #ifdef SUPPORTD3D
1805                 {
1806                         r_hlsl_permutation_t *p;
1807                         r_hlsl_permutation = NULL;
1808                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1809                         for (i = 0;i < limit;i++)
1810                         {
1811                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1812                                 {
1813                                         if (p->vertexshader)
1814                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1815                                         if (p->pixelshader)
1816                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1817                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1818                                 }
1819                         }
1820                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1821                 }
1822 #endif
1823                 break;
1824         case RENDERPATH_D3D10:
1825                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1826                 break;
1827         case RENDERPATH_D3D11:
1828                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1829                 break;
1830         case RENDERPATH_GL20:
1831         case RENDERPATH_GLES2:
1832                 {
1833                         r_glsl_permutation_t *p;
1834                         r_glsl_permutation = NULL;
1835                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1836                         for (i = 0;i < limit;i++)
1837                         {
1838                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1839                                 {
1840                                         GL_Backend_FreeProgram(p->program);
1841                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1842                                 }
1843                         }
1844                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1845                 }
1846                 break;
1847         case RENDERPATH_GL11:
1848         case RENDERPATH_GL13:
1849         case RENDERPATH_GLES1:
1850                 break;
1851         case RENDERPATH_SOFT:
1852                 break;
1853         }
1854 }
1855
1856 void R_GLSL_DumpShader_f(void)
1857 {
1858         int i;
1859         qfile_t *file;
1860
1861         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1862         if (file)
1863         {
1864                 FS_Print(file, "/* The engine may define the following macros:\n");
1865                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1866                 for (i = 0;i < SHADERMODE_COUNT;i++)
1867                         FS_Print(file, glslshadermodeinfo[i].pretext);
1868                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1869                         FS_Print(file, shaderpermutationinfo[i].pretext);
1870                 FS_Print(file, "*/\n");
1871                 FS_Print(file, builtinshaderstring);
1872                 FS_Close(file);
1873                 Con_Printf("glsl/default.glsl written\n");
1874         }
1875         else
1876                 Con_Printf("failed to write to glsl/default.glsl\n");
1877
1878         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1879         if (file)
1880         {
1881                 FS_Print(file, "/* The engine may define the following macros:\n");
1882                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1883                 for (i = 0;i < SHADERMODE_COUNT;i++)
1884                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1885                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1886                         FS_Print(file, shaderpermutationinfo[i].pretext);
1887                 FS_Print(file, "*/\n");
1888                 FS_Print(file, builtinhlslshaderstring);
1889                 FS_Close(file);
1890                 Con_Printf("hlsl/default.hlsl written\n");
1891         }
1892         else
1893                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1894 }
1895
1896 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy)
1897 {
1898         unsigned int permutation = 0;
1899         if (r_trippy.integer && !notrippy)
1900                 permutation |= SHADERPERMUTATION_TRIPPY;
1901         permutation |= SHADERPERMUTATION_VIEWTINT;
1902         if (first)
1903                 permutation |= SHADERPERMUTATION_DIFFUSE;
1904         if (second)
1905                 permutation |= SHADERPERMUTATION_SPECULAR;
1906         if (texturemode == GL_MODULATE)
1907                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1908         else if (texturemode == GL_ADD)
1909                 permutation |= SHADERPERMUTATION_GLOW;
1910         else if (texturemode == GL_DECAL)
1911                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1912         if (!second)
1913                 texturemode = GL_MODULATE;
1914         if (vid.allowalphatocoverage)
1915                 GL_AlphaToCoverage(false);
1916         switch (vid.renderpath)
1917         {
1918         case RENDERPATH_D3D9:
1919 #ifdef SUPPORTD3D
1920                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1921                 R_Mesh_TexBind(GL20TU_FIRST , first );
1922                 R_Mesh_TexBind(GL20TU_SECOND, second);
1923 #endif
1924                 break;
1925         case RENDERPATH_D3D10:
1926                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1927                 break;
1928         case RENDERPATH_D3D11:
1929                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1930                 break;
1931         case RENDERPATH_GL20:
1932         case RENDERPATH_GLES2:
1933                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1934                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1935                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1936                 break;
1937         case RENDERPATH_GL13:
1938         case RENDERPATH_GLES1:
1939                 R_Mesh_TexBind(0, first );
1940                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1941                 R_Mesh_TexBind(1, second);
1942                 if (second)
1943                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1944                 break;
1945         case RENDERPATH_GL11:
1946                 R_Mesh_TexBind(0, first );
1947                 break;
1948         case RENDERPATH_SOFT:
1949                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1950                 R_Mesh_TexBind(GL20TU_FIRST , first );
1951                 R_Mesh_TexBind(GL20TU_SECOND, second);
1952                 break;
1953         }
1954 }
1955
1956 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1957 {
1958         unsigned int permutation = 0;
1959         if (r_trippy.integer && !notrippy)
1960                 permutation |= SHADERPERMUTATION_TRIPPY;
1961         if (vid.allowalphatocoverage)
1962                 GL_AlphaToCoverage(false);
1963         switch (vid.renderpath)
1964         {
1965         case RENDERPATH_D3D9:
1966 #ifdef SUPPORTD3D
1967                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1968 #endif
1969                 break;
1970         case RENDERPATH_D3D10:
1971                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1972                 break;
1973         case RENDERPATH_D3D11:
1974                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1975                 break;
1976         case RENDERPATH_GL20:
1977         case RENDERPATH_GLES2:
1978                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1979                 break;
1980         case RENDERPATH_GL13:
1981         case RENDERPATH_GLES1:
1982                 R_Mesh_TexBind(0, 0);
1983                 R_Mesh_TexBind(1, 0);
1984                 break;
1985         case RENDERPATH_GL11:
1986                 R_Mesh_TexBind(0, 0);
1987                 break;
1988         case RENDERPATH_SOFT:
1989                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1990                 break;
1991         }
1992 }
1993
1994 void R_SetupShader_ShowDepth(qboolean notrippy)
1995 {
1996         int permutation = 0;
1997         if (r_trippy.integer && !notrippy)
1998                 permutation |= SHADERPERMUTATION_TRIPPY;
1999         if (r_trippy.integer)
2000                 permutation |= SHADERPERMUTATION_TRIPPY;
2001         if (vid.allowalphatocoverage)
2002                 GL_AlphaToCoverage(false);
2003         switch (vid.renderpath)
2004         {
2005         case RENDERPATH_D3D9:
2006 #ifdef SUPPORTHLSL
2007                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2008 #endif
2009                 break;
2010         case RENDERPATH_D3D10:
2011                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2012                 break;
2013         case RENDERPATH_D3D11:
2014                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2015                 break;
2016         case RENDERPATH_GL20:
2017         case RENDERPATH_GLES2:
2018                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2019                 break;
2020         case RENDERPATH_GL13:
2021         case RENDERPATH_GLES1:
2022                 break;
2023         case RENDERPATH_GL11:
2024                 break;
2025         case RENDERPATH_SOFT:
2026                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2027                 break;
2028         }
2029 }
2030
2031 extern qboolean r_shadow_usingdeferredprepass;
2032 extern cvar_t r_shadow_deferred_8bitrange;
2033 extern rtexture_t *r_shadow_attenuationgradienttexture;
2034 extern rtexture_t *r_shadow_attenuation2dtexture;
2035 extern rtexture_t *r_shadow_attenuation3dtexture;
2036 extern qboolean r_shadow_usingshadowmap2d;
2037 extern qboolean r_shadow_usingshadowmaportho;
2038 extern float r_shadow_shadowmap_texturescale[2];
2039 extern float r_shadow_shadowmap_parameters[4];
2040 extern qboolean r_shadow_shadowmapvsdct;
2041 extern qboolean r_shadow_shadowmapsampler;
2042 extern int r_shadow_shadowmappcf;
2043 extern rtexture_t *r_shadow_shadowmap2dtexture;
2044 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2045 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2046 extern matrix4x4_t r_shadow_shadowmapmatrix;
2047 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2048 extern int r_shadow_prepass_width;
2049 extern int r_shadow_prepass_height;
2050 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2051 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2052 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2053 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2054 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2055
2056 #define BLENDFUNC_ALLOWS_COLORMOD      1
2057 #define BLENDFUNC_ALLOWS_FOG           2
2058 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2059 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2060 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2061 static int R_BlendFuncFlags(int src, int dst)
2062 {
2063         int r = 0;
2064
2065         // a blendfunc allows colormod if:
2066         // a) it can never keep the destination pixel invariant, or
2067         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2068         // this is to prevent unintended side effects from colormod
2069
2070         // a blendfunc allows fog if:
2071         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2072         // this is to prevent unintended side effects from fog
2073
2074         // these checks are the output of fogeval.pl
2075
2076         r |= BLENDFUNC_ALLOWS_COLORMOD;
2077         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2078         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2079         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2080         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2081         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2082         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2084         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2085         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2086         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2087         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2088         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2089         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2090         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2091         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2092         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2093         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2095         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098
2099         return r;
2100 }
2101
2102 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, qboolean notrippy)
2103 {
2104         // select a permutation of the lighting shader appropriate to this
2105         // combination of texture, entity, light source, and fogging, only use the
2106         // minimum features necessary to avoid wasting rendering time in the
2107         // fragment shader on features that are not being used
2108         unsigned int permutation = 0;
2109         unsigned int mode = 0;
2110         int blendfuncflags;
2111         static float dummy_colormod[3] = {1, 1, 1};
2112         float *colormod = rsurface.colormod;
2113         float m16f[16];
2114         matrix4x4_t tempmatrix;
2115         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2116         if (r_trippy.integer && !notrippy)
2117                 permutation |= SHADERPERMUTATION_TRIPPY;
2118         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2119                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2120         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2121                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2122         if (rsurfacepass == RSURFPASS_BACKGROUND)
2123         {
2124                 // distorted background
2125                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2126                 {
2127                         mode = SHADERMODE_WATER;
2128                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2129                         {
2130                                 // this is the right thing to do for wateralpha
2131                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2132                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2133                         }
2134                         else
2135                         {
2136                                 // this is the right thing to do for entity alpha
2137                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2138                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2139                         }
2140                 }
2141                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2142                 {
2143                         mode = SHADERMODE_REFRACTION;
2144                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2145                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                 }
2147                 else
2148                 {
2149                         mode = SHADERMODE_GENERIC;
2150                         permutation |= SHADERPERMUTATION_DIFFUSE;
2151                         GL_BlendFunc(GL_ONE, GL_ZERO);
2152                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2153                 }
2154                 if (vid.allowalphatocoverage)
2155                         GL_AlphaToCoverage(false);
2156         }
2157         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2158         {
2159                 if (r_glsl_offsetmapping.integer)
2160                 {
2161                         switch(rsurface.texture->offsetmapping)
2162                         {
2163                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2164                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2165                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2166                         case OFFSETMAPPING_OFF: break;
2167                         }
2168                 }
2169                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2171                 // normalmap (deferred prepass), may use alpha test on diffuse
2172                 mode = SHADERMODE_DEFERREDGEOMETRY;
2173                 GL_BlendFunc(GL_ONE, GL_ZERO);
2174                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2175                 if (vid.allowalphatocoverage)
2176                         GL_AlphaToCoverage(false);
2177         }
2178         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2179         {
2180                 if (r_glsl_offsetmapping.integer)
2181                 {
2182                         switch(rsurface.texture->offsetmapping)
2183                         {
2184                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2185                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2186                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2187                         case OFFSETMAPPING_OFF: break;
2188                         }
2189                 }
2190                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2191                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2192                 // light source
2193                 mode = SHADERMODE_LIGHTSOURCE;
2194                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2195                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2196                 if (diffusescale > 0)
2197                         permutation |= SHADERPERMUTATION_DIFFUSE;
2198                 if (specularscale > 0)
2199                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2200                 if (r_refdef.fogenabled)
2201                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2202                 if (rsurface.texture->colormapping)
2203                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2204                 if (r_shadow_usingshadowmap2d)
2205                 {
2206                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2207                         if(r_shadow_shadowmapvsdct)
2208                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2209
2210                         if (r_shadow_shadowmapsampler)
2211                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2212                         if (r_shadow_shadowmappcf > 1)
2213                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2214                         else if (r_shadow_shadowmappcf)
2215                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2216                 }
2217                 if (rsurface.texture->reflectmasktexture)
2218                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2219                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2220                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2221                 if (vid.allowalphatocoverage)
2222                         GL_AlphaToCoverage(false);
2223         }
2224         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2225         {
2226                 if (r_glsl_offsetmapping.integer)
2227                 {
2228                         switch(rsurface.texture->offsetmapping)
2229                         {
2230                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2231                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2232                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2233                         case OFFSETMAPPING_OFF: break;
2234                         }
2235                 }
2236                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2237                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2238                 // unshaded geometry (fullbright or ambient model lighting)
2239                 mode = SHADERMODE_FLATCOLOR;
2240                 ambientscale = diffusescale = specularscale = 0;
2241                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2242                         permutation |= SHADERPERMUTATION_GLOW;
2243                 if (r_refdef.fogenabled)
2244                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2245                 if (rsurface.texture->colormapping)
2246                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2247                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2248                 {
2249                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2250                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2251
2252                         if (r_shadow_shadowmapsampler)
2253                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2254                         if (r_shadow_shadowmappcf > 1)
2255                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2256                         else if (r_shadow_shadowmappcf)
2257                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2258                 }
2259                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2260                         permutation |= SHADERPERMUTATION_REFLECTION;
2261                 if (rsurface.texture->reflectmasktexture)
2262                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2263                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2264                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2265                 // when using alphatocoverage, we don't need alphakill
2266                 if (vid.allowalphatocoverage)
2267                 {
2268                         if (r_transparent_alphatocoverage.integer)
2269                         {
2270                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2271                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2272                         }
2273                         else
2274                                 GL_AlphaToCoverage(false);
2275                 }
2276         }
2277         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2278         {
2279                 if (r_glsl_offsetmapping.integer)
2280                 {
2281                         switch(rsurface.texture->offsetmapping)
2282                         {
2283                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2284                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_OFF: break;
2287                         }
2288                 }
2289                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2290                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2291                 // directional model lighting
2292                 mode = SHADERMODE_LIGHTDIRECTION;
2293                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2294                         permutation |= SHADERPERMUTATION_GLOW;
2295                 permutation |= SHADERPERMUTATION_DIFFUSE;
2296                 if (specularscale > 0)
2297                         permutation |= SHADERPERMUTATION_SPECULAR;
2298                 if (r_refdef.fogenabled)
2299                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2300                 if (rsurface.texture->colormapping)
2301                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2302                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2303                 {
2304                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2305                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2306
2307                         if (r_shadow_shadowmapsampler)
2308                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2309                         if (r_shadow_shadowmappcf > 1)
2310                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2311                         else if (r_shadow_shadowmappcf)
2312                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2313                 }
2314                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2315                         permutation |= SHADERPERMUTATION_REFLECTION;
2316                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2317                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2318                 if (rsurface.texture->reflectmasktexture)
2319                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2320                 if (r_shadow_bouncegridtexture)
2321                 {
2322                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2323                         if (r_shadow_bouncegriddirectional)
2324                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2325                 }
2326                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2327                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2328                 // when using alphatocoverage, we don't need alphakill
2329                 if (vid.allowalphatocoverage)
2330                 {
2331                         if (r_transparent_alphatocoverage.integer)
2332                         {
2333                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2334                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2335                         }
2336                         else
2337                                 GL_AlphaToCoverage(false);
2338                 }
2339         }
2340         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2341         {
2342                 if (r_glsl_offsetmapping.integer)
2343                 {
2344                         switch(rsurface.texture->offsetmapping)
2345                         {
2346                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2347                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2348                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_OFF: break;
2350                         }
2351                 }
2352                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2353                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2354                 // ambient model lighting
2355                 mode = SHADERMODE_LIGHTDIRECTION;
2356                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2357                         permutation |= SHADERPERMUTATION_GLOW;
2358                 if (r_refdef.fogenabled)
2359                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2360                 if (rsurface.texture->colormapping)
2361                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2362                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2363                 {
2364                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2365                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2366
2367                         if (r_shadow_shadowmapsampler)
2368                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2369                         if (r_shadow_shadowmappcf > 1)
2370                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2371                         else if (r_shadow_shadowmappcf)
2372                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2373                 }
2374                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2375                         permutation |= SHADERPERMUTATION_REFLECTION;
2376                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2377                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2378                 if (rsurface.texture->reflectmasktexture)
2379                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2380                 if (r_shadow_bouncegridtexture)
2381                 {
2382                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2383                         if (r_shadow_bouncegriddirectional)
2384                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2385                 }
2386                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2387                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2388                 // when using alphatocoverage, we don't need alphakill
2389                 if (vid.allowalphatocoverage)
2390                 {
2391                         if (r_transparent_alphatocoverage.integer)
2392                         {
2393                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2394                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2395                         }
2396                         else
2397                                 GL_AlphaToCoverage(false);
2398                 }
2399         }
2400         else
2401         {
2402                 if (r_glsl_offsetmapping.integer)
2403                 {
2404                         switch(rsurface.texture->offsetmapping)
2405                         {
2406                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2407                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2408                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409                         case OFFSETMAPPING_OFF: break;
2410                         }
2411                 }
2412                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2413                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2414                 // lightmapped wall
2415                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2416                         permutation |= SHADERPERMUTATION_GLOW;
2417                 if (r_refdef.fogenabled)
2418                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2419                 if (rsurface.texture->colormapping)
2420                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2421                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2422                 {
2423                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2424                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2425
2426                         if (r_shadow_shadowmapsampler)
2427                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2428                         if (r_shadow_shadowmappcf > 1)
2429                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2430                         else if (r_shadow_shadowmappcf)
2431                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2432                 }
2433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2434                         permutation |= SHADERPERMUTATION_REFLECTION;
2435                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2436                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2437                 if (rsurface.texture->reflectmasktexture)
2438                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2439                 if (FAKELIGHT_ENABLED)
2440                 {
2441                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2442                         mode = SHADERMODE_FAKELIGHT;
2443                         permutation |= SHADERPERMUTATION_DIFFUSE;
2444                         if (specularscale > 0)
2445                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2446                 }
2447                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2448                 {
2449                         // deluxemapping (light direction texture)
2450                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2451                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2452                         else
2453                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2454                         permutation |= SHADERPERMUTATION_DIFFUSE;
2455                         if (specularscale > 0)
2456                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2457                 }
2458                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2459                 {
2460                         // fake deluxemapping (uniform light direction in tangentspace)
2461                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2462                         permutation |= SHADERPERMUTATION_DIFFUSE;
2463                         if (specularscale > 0)
2464                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2465                 }
2466                 else if (rsurface.uselightmaptexture)
2467                 {
2468                         // ordinary lightmapping (q1bsp, q3bsp)
2469                         mode = SHADERMODE_LIGHTMAP;
2470                 }
2471                 else
2472                 {
2473                         // ordinary vertex coloring (q3bsp)
2474                         mode = SHADERMODE_VERTEXCOLOR;
2475                 }
2476                 if (r_shadow_bouncegridtexture)
2477                 {
2478                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2479                         if (r_shadow_bouncegriddirectional)
2480                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2481                 }
2482                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2483                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2484                 // when using alphatocoverage, we don't need alphakill
2485                 if (vid.allowalphatocoverage)
2486                 {
2487                         if (r_transparent_alphatocoverage.integer)
2488                         {
2489                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2490                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2491                         }
2492                         else
2493                                 GL_AlphaToCoverage(false);
2494                 }
2495         }
2496         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2497                 colormod = dummy_colormod;
2498         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2499                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2500         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2501                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2502         switch(vid.renderpath)
2503         {
2504         case RENDERPATH_D3D9:
2505 #ifdef SUPPORTD3D
2506                 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);
2507                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2508                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2509                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2510                 if (mode == SHADERMODE_LIGHTSOURCE)
2511                 {
2512                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2513                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2514                 }
2515                 else
2516                 {
2517                         if (mode == SHADERMODE_LIGHTDIRECTION)
2518                         {
2519                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2520                         }
2521                 }
2522                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2523                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2524                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2525                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2526                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2527
2528                 if (mode == SHADERMODE_LIGHTSOURCE)
2529                 {
2530                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2531                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2532                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2533                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2535
2536                         // additive passes are only darkened by fog, not tinted
2537                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2538                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2539                 }
2540                 else
2541                 {
2542                         if (mode == SHADERMODE_FLATCOLOR)
2543                         {
2544                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2545                         }
2546                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2547                         {
2548                                 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]);
2549                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2550                                 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);
2551                                 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);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2555                         }
2556                         else
2557                         {
2558                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2559                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2560                                 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);
2561                                 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);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2563                         }
2564                         // additive passes are only darkened by fog, not tinted
2565                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2567                         else
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2569                         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);
2570                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2571                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2572                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2574                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2575                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2576                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2577                         if (mode == SHADERMODE_WATER)
2578                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2579                 }
2580                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2581                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2582                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2583                 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));
2584                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2585                 if (rsurface.texture->pantstexture)
2586                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2587                 else
2588                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2589                 if (rsurface.texture->shirttexture)
2590                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2591                 else
2592                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2593                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2594                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2595                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2596                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2597                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2598                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2599                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2600                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2601                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2602                         );
2603                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2604                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2605
2606                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2607                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2608                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2609                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2610                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2611                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2612                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2613                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2614                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2615                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2616                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2617                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2618                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2619                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2620                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2621                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2622                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2623                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2624                 {
2625                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2626                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2627                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2628                 }
2629                 else
2630                 {
2631                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2632                 }
2633 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2634 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2635                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2636                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2637                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2638                 {
2639                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2640                         if (rsurface.rtlight)
2641                         {
2642                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2643                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2644                         }
2645                 }
2646 #endif
2647                 break;
2648         case RENDERPATH_D3D10:
2649                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2650                 break;
2651         case RENDERPATH_D3D11:
2652                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2653                 break;
2654         case RENDERPATH_GL20:
2655         case RENDERPATH_GLES2:
2656                 if (!vid.useinterleavedarrays)
2657                 {
2658                         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);
2659                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2660                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2661                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2662                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2663                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2664                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2665                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2666                 }
2667                 else
2668                 {
2669                         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);
2670                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2671                 }
2672                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2673                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2674                 if (mode == SHADERMODE_LIGHTSOURCE)
2675                 {
2676                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2677                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2678                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2679                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2680                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2681                         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);
2682         
2683                         // additive passes are only darkened by fog, not tinted
2684                         if (r_glsl_permutation->loc_FogColor >= 0)
2685                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2686                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2687                 }
2688                 else
2689                 {
2690                         if (mode == SHADERMODE_FLATCOLOR)
2691                         {
2692                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2693                         }
2694                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2695                         {
2696                                 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]);
2697                                 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]);
2698                                 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);
2699                                 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);
2700                                 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);
2701                                 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]);
2702                                 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]);
2703                         }
2704                         else
2705                         {
2706                                 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]);
2707                                 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]);
2708                                 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);
2709                                 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);
2710                                 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);
2711                         }
2712                         // additive passes are only darkened by fog, not tinted
2713                         if (r_glsl_permutation->loc_FogColor >= 0)
2714                         {
2715                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2716                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2717                                 else
2718                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2719                         }
2720                         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);
2721                         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]);
2722                         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]);
2723                         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]);
2724                         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]);
2725                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2726                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2727                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2728                         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]);
2729                 }
2730                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2731                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2732                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2733                 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]);
2734                 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]);
2735
2736                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2737                 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));
2738                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2739                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2740                 {
2741                         if (rsurface.texture->pantstexture)
2742                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2743                         else
2744                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2745                 }
2746                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2747                 {
2748                         if (rsurface.texture->shirttexture)
2749                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2750                         else
2751                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2752                 }
2753                 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]);
2754                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2755                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2756                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2757                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2758                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2759                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2760                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2761                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2762                         );
2763                 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]);
2764                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2765                 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);}
2766                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2767
2768                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2769                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2770                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2771                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2772                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2773                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2774                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2775                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2776                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2777                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2778                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2779                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2780                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2781                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2782                 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);
2783                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2784                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2785                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2786                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2787                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2788                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2789                 {
2790                         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);
2791                         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);
2792                         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);
2793                 }
2794                 else
2795                 {
2796                         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);
2797                 }
2798                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2799                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2800                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2801                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2802                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2803                 {
2804                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2805                         if (rsurface.rtlight)
2806                         {
2807                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2808                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2809                         }
2810                 }
2811                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2812                 CHECKGLERROR
2813                 break;
2814         case RENDERPATH_GL11:
2815         case RENDERPATH_GL13:
2816         case RENDERPATH_GLES1:
2817                 break;
2818         case RENDERPATH_SOFT:
2819                 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);
2820                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2821                 R_SetupShader_SetPermutationSoft(mode, permutation);
2822                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2823                 if (mode == SHADERMODE_LIGHTSOURCE)
2824                 {
2825                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2826                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2827                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2828                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2829                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2830                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2831         
2832                         // additive passes are only darkened by fog, not tinted
2833                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2834                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2835                 }
2836                 else
2837                 {
2838                         if (mode == SHADERMODE_FLATCOLOR)
2839                         {
2840                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2841                         }
2842                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2843                         {
2844                                 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]);
2845                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2846                                 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);
2847                                 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);
2848                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2849                                 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]);
2850                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2851                         }
2852                         else
2853                         {
2854                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2856                                 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);
2857                                 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);
2858                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2859                         }
2860                         // additive passes are only darkened by fog, not tinted
2861                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2863                         else
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2865                         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);
2866                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2867                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2868                         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]);
2869                         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]);
2870                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2871                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2872                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2873                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2874                 }
2875                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2876                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2877                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2878                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2879                 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]);
2880
2881                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2882                 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));
2883                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2884                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2885                 {
2886                         if (rsurface.texture->pantstexture)
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2888                         else
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2890                 }
2891                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2892                 {
2893                         if (rsurface.texture->shirttexture)
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2895                         else
2896                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2897                 }
2898                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2899                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2900                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2901                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2902                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2903                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2904                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2905                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2906                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2907                         );
2908                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2909                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2910
2911                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2912                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2913                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2914                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2915                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2916                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2917                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2918                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2919                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2920                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2921                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2922                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2923                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2924                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2925                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2926                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2927                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2928                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2929                 {
2930                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2931                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2932                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2933                 }
2934                 else
2935                 {
2936                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2937                 }
2938 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2939 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2940                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2941                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2942                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2943                 {
2944                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2945                         if (rsurface.rtlight)
2946                         {
2947                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2948                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2949                         }
2950                 }
2951                 break;
2952         }
2953 }
2954
2955 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2956 {
2957         // select a permutation of the lighting shader appropriate to this
2958         // combination of texture, entity, light source, and fogging, only use the
2959         // minimum features necessary to avoid wasting rendering time in the
2960         // fragment shader on features that are not being used
2961         unsigned int permutation = 0;
2962         unsigned int mode = 0;
2963         const float *lightcolorbase = rtlight->currentcolor;
2964         float ambientscale = rtlight->ambientscale;
2965         float diffusescale = rtlight->diffusescale;
2966         float specularscale = rtlight->specularscale;
2967         // this is the location of the light in view space
2968         vec3_t viewlightorigin;
2969         // this transforms from view space (camera) to light space (cubemap)
2970         matrix4x4_t viewtolight;
2971         matrix4x4_t lighttoview;
2972         float viewtolight16f[16];
2973         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2974         // light source
2975         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2976         if (rtlight->currentcubemap != r_texture_whitecube)
2977                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2978         if (diffusescale > 0)
2979                 permutation |= SHADERPERMUTATION_DIFFUSE;
2980         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2981                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2982         if (r_shadow_usingshadowmap2d)
2983         {
2984                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2985                 if (r_shadow_shadowmapvsdct)
2986                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2987
2988                 if (r_shadow_shadowmapsampler)
2989                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2990                 if (r_shadow_shadowmappcf > 1)
2991                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2992                 else if (r_shadow_shadowmappcf)
2993                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2994         }
2995         if (vid.allowalphatocoverage)
2996                 GL_AlphaToCoverage(false);
2997         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2998         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2999         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3000         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3001         switch(vid.renderpath)
3002         {
3003         case RENDERPATH_D3D9:
3004 #ifdef SUPPORTD3D
3005                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3006                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3007                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3008                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3009                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3010                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3011                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3012                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3013                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3014                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3015                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3016
3017                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3018                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3019                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3020                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3021                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3022                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3023 #endif
3024                 break;
3025         case RENDERPATH_D3D10:
3026                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3027                 break;
3028         case RENDERPATH_D3D11:
3029                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3030                 break;
3031         case RENDERPATH_GL20:
3032         case RENDERPATH_GLES2:
3033                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3034                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3035                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3036                 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);
3037                 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);
3038                 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);
3039                 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]);
3040                 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]);
3041                 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));
3042                 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]);
3043                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3044
3045                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3046                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3047                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3048                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3049                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3050                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3051                 break;
3052         case RENDERPATH_GL11:
3053         case RENDERPATH_GL13:
3054         case RENDERPATH_GLES1:
3055                 break;
3056         case RENDERPATH_SOFT:
3057                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3058                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3059                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3060                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3061                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3062                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3063                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3064                 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]);
3065                 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));
3066                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3067                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3068
3069                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3070                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3071                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3072                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3073                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3074                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3075                 break;
3076         }
3077 }
3078
3079 #define SKINFRAME_HASH 1024
3080
3081 typedef struct
3082 {
3083         int loadsequence; // incremented each level change
3084         memexpandablearray_t array;
3085         skinframe_t *hash[SKINFRAME_HASH];
3086 }
3087 r_skinframe_t;
3088 r_skinframe_t r_skinframe;
3089
3090 void R_SkinFrame_PrepareForPurge(void)
3091 {
3092         r_skinframe.loadsequence++;
3093         // wrap it without hitting zero
3094         if (r_skinframe.loadsequence >= 200)
3095                 r_skinframe.loadsequence = 1;
3096 }
3097
3098 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3099 {
3100         if (!skinframe)
3101                 return;
3102         // mark the skinframe as used for the purging code
3103         skinframe->loadsequence = r_skinframe.loadsequence;
3104 }
3105
3106 void R_SkinFrame_Purge(void)
3107 {
3108         int i;
3109         skinframe_t *s;
3110         for (i = 0;i < SKINFRAME_HASH;i++)
3111         {
3112                 for (s = r_skinframe.hash[i];s;s = s->next)
3113                 {
3114                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3115                         {
3116                                 if (s->merged == s->base)
3117                                         s->merged = NULL;
3118                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3119                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3120                                 R_PurgeTexture(s->merged);s->merged = NULL;
3121                                 R_PurgeTexture(s->base  );s->base   = NULL;
3122                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3123                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3124                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3125                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3126                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3127                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3128                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3129                                 s->loadsequence = 0;
3130                         }
3131                 }
3132         }
3133 }
3134
3135 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3136         skinframe_t *item;
3137         char basename[MAX_QPATH];
3138
3139         Image_StripImageExtension(name, basename, sizeof(basename));
3140
3141         if( last == NULL ) {
3142                 int hashindex;
3143                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3144                 item = r_skinframe.hash[hashindex];
3145         } else {
3146                 item = last->next;
3147         }
3148
3149         // linearly search through the hash bucket
3150         for( ; item ; item = item->next ) {
3151                 if( !strcmp( item->basename, basename ) ) {
3152                         return item;
3153                 }
3154         }
3155         return NULL;
3156 }
3157
3158 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3159 {
3160         skinframe_t *item;
3161         int hashindex;
3162         char basename[MAX_QPATH];
3163
3164         Image_StripImageExtension(name, basename, sizeof(basename));
3165
3166         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3167         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3168                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3169                         break;
3170
3171         if (!item) {
3172                 rtexture_t *dyntexture;
3173                 // check whether its a dynamic texture
3174                 dyntexture = CL_GetDynTexture( basename );
3175                 if (!add && !dyntexture)
3176                         return NULL;
3177                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3178                 memset(item, 0, sizeof(*item));
3179                 strlcpy(item->basename, basename, sizeof(item->basename));
3180                 item->base = dyntexture; // either NULL or dyntexture handle
3181                 item->textureflags = textureflags;
3182                 item->comparewidth = comparewidth;
3183                 item->compareheight = compareheight;
3184                 item->comparecrc = comparecrc;
3185                 item->next = r_skinframe.hash[hashindex];
3186                 r_skinframe.hash[hashindex] = item;
3187         }
3188         else if( item->base == NULL )
3189         {
3190                 rtexture_t *dyntexture;
3191                 // check whether its a dynamic texture
3192                 // 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]
3193                 dyntexture = CL_GetDynTexture( basename );
3194                 item->base = dyntexture; // either NULL or dyntexture handle
3195         }
3196
3197         R_SkinFrame_MarkUsed(item);
3198         return item;
3199 }
3200
3201 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3202         { \
3203                 unsigned long long avgcolor[5], wsum; \
3204                 int pix, comp, w; \
3205                 avgcolor[0] = 0; \
3206                 avgcolor[1] = 0; \
3207                 avgcolor[2] = 0; \
3208                 avgcolor[3] = 0; \
3209                 avgcolor[4] = 0; \
3210                 wsum = 0; \
3211                 for(pix = 0; pix < cnt; ++pix) \
3212                 { \
3213                         w = 0; \
3214                         for(comp = 0; comp < 3; ++comp) \
3215                                 w += getpixel; \
3216                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3217                         { \
3218                                 ++wsum; \
3219                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3220                                 w = getpixel; \
3221                                 for(comp = 0; comp < 3; ++comp) \
3222                                         avgcolor[comp] += getpixel * w; \
3223                                 avgcolor[3] += w; \
3224                         } \
3225                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3226                         avgcolor[4] += getpixel; \
3227                 } \
3228                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3229                         avgcolor[3] = 1; \
3230                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3231                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3232                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3233                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3234         }
3235
3236 extern cvar_t gl_picmip;
3237 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3238 {
3239         int j;
3240         unsigned char *pixels;
3241         unsigned char *bumppixels;
3242         unsigned char *basepixels = NULL;
3243         int basepixels_width = 0;
3244         int basepixels_height = 0;
3245         skinframe_t *skinframe;
3246         rtexture_t *ddsbase = NULL;
3247         qboolean ddshasalpha = false;
3248         float ddsavgcolor[4];
3249         char basename[MAX_QPATH];
3250         int miplevel = R_PicmipForFlags(textureflags);
3251         int savemiplevel = miplevel;
3252         int mymiplevel;
3253
3254         if (cls.state == ca_dedicated)
3255                 return NULL;
3256
3257         // return an existing skinframe if already loaded
3258         // if loading of the first image fails, don't make a new skinframe as it
3259         // would cause all future lookups of this to be missing
3260         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3261         if (skinframe && skinframe->base)
3262                 return skinframe;
3263
3264         Image_StripImageExtension(name, basename, sizeof(basename));
3265
3266         // check for DDS texture file first
3267         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3268         {
3269                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3270                 if (basepixels == NULL)
3271                         return NULL;
3272         }
3273
3274         // FIXME handle miplevel
3275
3276         if (developer_loading.integer)
3277                 Con_Printf("loading skin \"%s\"\n", name);
3278
3279         // we've got some pixels to store, so really allocate this new texture now
3280         if (!skinframe)
3281                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3282         skinframe->stain = NULL;
3283         skinframe->merged = NULL;
3284         skinframe->base = NULL;
3285         skinframe->pants = NULL;
3286         skinframe->shirt = NULL;
3287         skinframe->nmap = NULL;
3288         skinframe->gloss = NULL;
3289         skinframe->glow = NULL;
3290         skinframe->fog = NULL;
3291         skinframe->reflect = NULL;
3292         skinframe->hasalpha = false;
3293
3294         if (ddsbase)
3295         {
3296                 skinframe->base = ddsbase;
3297                 skinframe->hasalpha = ddshasalpha;
3298                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3299                 if (r_loadfog && skinframe->hasalpha)
3300                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3301                 //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]);
3302         }
3303         else
3304         {
3305                 basepixels_width = image_width;
3306                 basepixels_height = image_height;
3307                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3308                 if (textureflags & TEXF_ALPHA)
3309                 {
3310                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3311                         {
3312                                 if (basepixels[j] < 255)
3313                                 {
3314                                         skinframe->hasalpha = true;
3315                                         break;
3316                                 }
3317                         }
3318                         if (r_loadfog && skinframe->hasalpha)
3319                         {
3320                                 // has transparent pixels
3321                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3322                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3323                                 {
3324                                         pixels[j+0] = 255;
3325                                         pixels[j+1] = 255;
3326                                         pixels[j+2] = 255;
3327                                         pixels[j+3] = basepixels[j+3];
3328                                 }
3329                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3330                                 Mem_Free(pixels);
3331                         }
3332                 }
3333                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3334                 //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]);
3335                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3336                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3337                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3338                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3339         }
3340
3341         if (r_loaddds)
3342         {
3343                 mymiplevel = savemiplevel;
3344                 if (r_loadnormalmap)
3345                         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);
3346                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3347                 if (r_loadgloss)
3348                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3349                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3350                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3351                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3352         }
3353
3354         // _norm is the name used by tenebrae and has been adopted as standard
3355         if (r_loadnormalmap && skinframe->nmap == NULL)
3356         {
3357                 mymiplevel = savemiplevel;
3358                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3359                 {
3360                         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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3361                         Mem_Free(pixels);
3362                         pixels = NULL;
3363                 }
3364                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3365                 {
3366                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3367                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3368                         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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3369                         Mem_Free(pixels);
3370                         Mem_Free(bumppixels);
3371                 }
3372                 else if (r_shadow_bumpscale_basetexture.value > 0)
3373                 {
3374                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3375                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3376                         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 && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3377                         Mem_Free(pixels);
3378                 }
3379                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3380                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3381         }
3382
3383         // _luma is supported only for tenebrae compatibility
3384         // _glow is the preferred name
3385         mymiplevel = savemiplevel;
3386         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3387         {
3388                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3389                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3390                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3391                 Mem_Free(pixels);pixels = NULL;
3392         }
3393
3394         mymiplevel = savemiplevel;
3395         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3396         {
3397                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3398                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3399                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3400                 Mem_Free(pixels);
3401                 pixels = NULL;
3402         }
3403
3404         mymiplevel = savemiplevel;
3405         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3406         {
3407                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3408                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3409                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3410                 Mem_Free(pixels);
3411                 pixels = NULL;
3412         }
3413
3414         mymiplevel = savemiplevel;
3415         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3416         {
3417                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3418                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3419                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3420                 Mem_Free(pixels);
3421                 pixels = NULL;
3422         }
3423
3424         mymiplevel = savemiplevel;
3425         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3426         {
3427                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3428                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3429                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3430                 Mem_Free(pixels);
3431                 pixels = NULL;
3432         }
3433
3434         if (basepixels)
3435                 Mem_Free(basepixels);
3436
3437         return skinframe;
3438 }
3439
3440 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3441 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3442 {
3443         int i;
3444         unsigned char *temp1, *temp2;
3445         skinframe_t *skinframe;
3446
3447         if (cls.state == ca_dedicated)
3448                 return NULL;
3449
3450         // if already loaded just return it, otherwise make a new skinframe
3451         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3452         if (skinframe && skinframe->base)
3453                 return skinframe;
3454
3455         skinframe->stain = NULL;
3456         skinframe->merged = NULL;
3457         skinframe->base = NULL;
3458         skinframe->pants = NULL;
3459         skinframe->shirt = NULL;
3460         skinframe->nmap = NULL;
3461         skinframe->gloss = NULL;
3462         skinframe->glow = NULL;
3463         skinframe->fog = NULL;
3464         skinframe->reflect = NULL;
3465         skinframe->hasalpha = false;
3466
3467         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3468         if (!skindata)
3469                 return NULL;
3470
3471         if (developer_loading.integer)
3472                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3473
3474         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3475         {
3476                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3477                 temp2 = temp1 + width * height * 4;
3478                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3479                 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);
3480                 Mem_Free(temp1);
3481         }
3482         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3483         if (textureflags & TEXF_ALPHA)
3484         {
3485                 for (i = 3;i < width * height * 4;i += 4)
3486                 {
3487                         if (skindata[i] < 255)
3488                         {
3489                                 skinframe->hasalpha = true;
3490                                 break;
3491                         }
3492                 }
3493                 if (r_loadfog && skinframe->hasalpha)
3494                 {
3495                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3496                         memcpy(fogpixels, skindata, width * height * 4);
3497                         for (i = 0;i < width * height * 4;i += 4)
3498                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3499                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3500                         Mem_Free(fogpixels);
3501                 }
3502         }
3503
3504         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3505         //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]);
3506
3507         return skinframe;
3508 }
3509
3510 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3511 {
3512         int i;
3513         int featuresmask;
3514         skinframe_t *skinframe;
3515
3516         if (cls.state == ca_dedicated)
3517                 return NULL;
3518
3519         // if already loaded just return it, otherwise make a new skinframe
3520         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3521         if (skinframe && skinframe->base)
3522                 return skinframe;
3523
3524         skinframe->stain = NULL;
3525         skinframe->merged = NULL;
3526         skinframe->base = NULL;
3527         skinframe->pants = NULL;
3528         skinframe->shirt = NULL;
3529         skinframe->nmap = NULL;
3530         skinframe->gloss = NULL;
3531         skinframe->glow = NULL;
3532         skinframe->fog = NULL;
3533         skinframe->reflect = NULL;
3534         skinframe->hasalpha = false;
3535
3536         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3537         if (!skindata)
3538                 return NULL;
3539
3540         if (developer_loading.integer)
3541                 Con_Printf("loading quake skin \"%s\"\n", name);
3542
3543         // 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)
3544         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3545         memcpy(skinframe->qpixels, skindata, width*height);
3546         skinframe->qwidth = width;
3547         skinframe->qheight = height;
3548
3549         featuresmask = 0;
3550         for (i = 0;i < width * height;i++)
3551                 featuresmask |= palette_featureflags[skindata[i]];
3552
3553         skinframe->hasalpha = false;
3554         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3555         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3556         skinframe->qgeneratemerged = true;
3557         skinframe->qgeneratebase = skinframe->qhascolormapping;
3558         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3559
3560         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3561         //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]);
3562
3563         return skinframe;
3564 }
3565
3566 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3567 {
3568         int width;
3569         int height;
3570         unsigned char *skindata;
3571
3572         if (!skinframe->qpixels)
3573                 return;
3574
3575         if (!skinframe->qhascolormapping)
3576                 colormapped = false;
3577
3578         if (colormapped)
3579         {
3580                 if (!skinframe->qgeneratebase)
3581                         return;
3582         }
3583         else
3584         {
3585                 if (!skinframe->qgeneratemerged)
3586                         return;
3587         }
3588
3589         width = skinframe->qwidth;
3590         height = skinframe->qheight;
3591         skindata = skinframe->qpixels;
3592
3593         if (skinframe->qgeneratenmap)
3594         {
3595                 unsigned char *temp1, *temp2;
3596                 skinframe->qgeneratenmap = false;
3597                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3598                 temp2 = temp1 + width * height * 4;
3599                 // use either a custom palette or the quake palette
3600                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3601                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3602                 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);
3603                 Mem_Free(temp1);
3604         }
3605
3606         if (skinframe->qgenerateglow)
3607         {
3608                 skinframe->qgenerateglow = false;
3609                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3610         }
3611
3612         if (colormapped)
3613         {
3614                 skinframe->qgeneratebase = false;
3615                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3616                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3617                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3618         }
3619         else
3620         {
3621                 skinframe->qgeneratemerged = false;
3622                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3623         }
3624
3625         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3626         {
3627                 Mem_Free(skinframe->qpixels);
3628                 skinframe->qpixels = NULL;
3629         }
3630 }
3631
3632 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)
3633 {
3634         int i;
3635         skinframe_t *skinframe;
3636
3637         if (cls.state == ca_dedicated)
3638                 return NULL;
3639
3640         // if already loaded just return it, otherwise make a new skinframe
3641         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3642         if (skinframe && skinframe->base)
3643                 return skinframe;
3644
3645         skinframe->stain = NULL;
3646         skinframe->merged = NULL;
3647         skinframe->base = NULL;
3648         skinframe->pants = NULL;
3649         skinframe->shirt = NULL;
3650         skinframe->nmap = NULL;
3651         skinframe->gloss = NULL;
3652         skinframe->glow = NULL;
3653         skinframe->fog = NULL;
3654         skinframe->reflect = NULL;
3655         skinframe->hasalpha = false;
3656
3657         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3658         if (!skindata)
3659                 return NULL;
3660
3661         if (developer_loading.integer)
3662                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3663
3664         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3665         if (textureflags & TEXF_ALPHA)
3666         {
3667                 for (i = 0;i < width * height;i++)
3668                 {
3669                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3670                         {
3671                                 skinframe->hasalpha = true;
3672                                 break;
3673                         }
3674                 }
3675                 if (r_loadfog && skinframe->hasalpha)
3676                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3677         }
3678
3679         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3680         //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]);
3681
3682         return skinframe;
3683 }
3684
3685 skinframe_t *R_SkinFrame_LoadMissing(void)
3686 {
3687         skinframe_t *skinframe;
3688
3689         if (cls.state == ca_dedicated)
3690                 return NULL;
3691
3692         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3693         skinframe->stain = NULL;
3694         skinframe->merged = NULL;
3695         skinframe->base = NULL;
3696         skinframe->pants = NULL;
3697         skinframe->shirt = NULL;
3698         skinframe->nmap = NULL;
3699         skinframe->gloss = NULL;
3700         skinframe->glow = NULL;
3701         skinframe->fog = NULL;
3702         skinframe->reflect = NULL;
3703         skinframe->hasalpha = false;
3704
3705         skinframe->avgcolor[0] = rand() / RAND_MAX;
3706         skinframe->avgcolor[1] = rand() / RAND_MAX;
3707         skinframe->avgcolor[2] = rand() / RAND_MAX;
3708         skinframe->avgcolor[3] = 1;
3709
3710         return skinframe;
3711 }
3712
3713 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3714 typedef struct suffixinfo_s
3715 {
3716         const char *suffix;
3717         qboolean flipx, flipy, flipdiagonal;
3718 }
3719 suffixinfo_t;
3720 static suffixinfo_t suffix[3][6] =
3721 {
3722         {
3723                 {"px",   false, false, false},
3724                 {"nx",   false, false, false},
3725                 {"py",   false, false, false},
3726                 {"ny",   false, false, false},
3727                 {"pz",   false, false, false},
3728                 {"nz",   false, false, false}
3729         },
3730         {
3731                 {"posx", false, false, false},
3732                 {"negx", false, false, false},
3733                 {"posy", false, false, false},
3734                 {"negy", false, false, false},
3735                 {"posz", false, false, false},
3736                 {"negz", false, false, false}
3737         },
3738         {
3739                 {"rt",    true, false,  true},
3740                 {"lf",   false,  true,  true},
3741                 {"ft",    true,  true, false},
3742                 {"bk",   false, false, false},
3743                 {"up",    true, false,  true},
3744                 {"dn",    true, false,  true}
3745         }
3746 };
3747
3748 static int componentorder[4] = {0, 1, 2, 3};
3749
3750 rtexture_t *R_LoadCubemap(const char *basename)
3751 {
3752         int i, j, cubemapsize;
3753         unsigned char *cubemappixels, *image_buffer;
3754         rtexture_t *cubemaptexture;
3755         char name[256];
3756         // must start 0 so the first loadimagepixels has no requested width/height
3757         cubemapsize = 0;
3758         cubemappixels = NULL;
3759         cubemaptexture = NULL;
3760         // keep trying different suffix groups (posx, px, rt) until one loads
3761         for (j = 0;j < 3 && !cubemappixels;j++)
3762         {
3763                 // load the 6 images in the suffix group
3764                 for (i = 0;i < 6;i++)
3765                 {
3766                         // generate an image name based on the base and and suffix
3767                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3768                         // load it
3769                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3770                         {
3771                                 // an image loaded, make sure width and height are equal
3772                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3773                                 {
3774                                         // if this is the first image to load successfully, allocate the cubemap memory
3775                                         if (!cubemappixels && image_width >= 1)
3776                                         {
3777                                                 cubemapsize = image_width;
3778                                                 // note this clears to black, so unavailable sides are black
3779                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3780                                         }
3781                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3782                                         if (cubemappixels)
3783                                                 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);
3784                                 }
3785                                 else
3786                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3787                                 // free the image
3788                                 Mem_Free(image_buffer);
3789                         }
3790                 }
3791         }
3792         // if a cubemap loaded, upload it
3793         if (cubemappixels)
3794         {
3795                 if (developer_loading.integer)
3796                         Con_Printf("loading cubemap \"%s\"\n", basename);
3797
3798                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3799                 Mem_Free(cubemappixels);
3800         }
3801         else
3802         {
3803                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3804                 if (developer_loading.integer)
3805                 {
3806                         Con_Printf("(tried tried images ");
3807                         for (j = 0;j < 3;j++)
3808                                 for (i = 0;i < 6;i++)
3809                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3810                         Con_Print(" and was unable to find any of them).\n");
3811                 }
3812         }
3813         return cubemaptexture;
3814 }
3815
3816 rtexture_t *R_GetCubemap(const char *basename)
3817 {
3818         int i;
3819         for (i = 0;i < r_texture_numcubemaps;i++)
3820                 if (r_texture_cubemaps[i] != NULL)
3821                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3822                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3823         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3824                 return r_texture_whitecube;
3825         r_texture_numcubemaps++;
3826         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3827         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3828         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3829         return r_texture_cubemaps[i]->texture;
3830 }
3831
3832 void R_FreeCubemap(const char *basename)
3833 {
3834         int i;
3835
3836         for (i = 0;i < r_texture_numcubemaps;i++)
3837         {
3838                 if (r_texture_cubemaps[i] != NULL)
3839                 {
3840                         if (r_texture_cubemaps[i]->texture)
3841                         {
3842                                 if (developer_loading.integer)
3843                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3844                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3845                                 Mem_Free(r_texture_cubemaps[i]);
3846                                 r_texture_cubemaps[i] = NULL;
3847                         }
3848                 }
3849         }
3850 }
3851
3852 void R_FreeCubemaps(void)
3853 {
3854         int i;
3855         for (i = 0;i < r_texture_numcubemaps;i++)
3856         {
3857                 if (developer_loading.integer)
3858                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3859                 if (r_texture_cubemaps[i] != NULL)
3860                 {
3861                         if (r_texture_cubemaps[i]->texture)
3862                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3863                         Mem_Free(r_texture_cubemaps[i]);
3864                 }
3865         }
3866         r_texture_numcubemaps = 0;
3867 }
3868
3869 void R_Main_FreeViewCache(void)
3870 {
3871         if (r_refdef.viewcache.entityvisible)
3872                 Mem_Free(r_refdef.viewcache.entityvisible);
3873         if (r_refdef.viewcache.world_pvsbits)
3874                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3875         if (r_refdef.viewcache.world_leafvisible)
3876                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3877         if (r_refdef.viewcache.world_surfacevisible)
3878                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3879         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3880 }
3881
3882 void R_Main_ResizeViewCache(void)
3883 {
3884         int numentities = r_refdef.scene.numentities;
3885         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3886         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3887         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3888         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3889         if (r_refdef.viewcache.maxentities < numentities)
3890         {
3891                 r_refdef.viewcache.maxentities = numentities;
3892                 if (r_refdef.viewcache.entityvisible)
3893                         Mem_Free(r_refdef.viewcache.entityvisible);
3894                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3895         }
3896         if (r_refdef.viewcache.world_numclusters != numclusters)
3897         {
3898                 r_refdef.viewcache.world_numclusters = numclusters;
3899                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3900                 if (r_refdef.viewcache.world_pvsbits)
3901                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3902                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3903         }
3904         if (r_refdef.viewcache.world_numleafs != numleafs)
3905         {
3906                 r_refdef.viewcache.world_numleafs = numleafs;
3907                 if (r_refdef.viewcache.world_leafvisible)
3908                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3909                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3910         }
3911         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3912         {
3913                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3914                 if (r_refdef.viewcache.world_surfacevisible)
3915                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3916                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3917         }
3918 }
3919
3920 extern rtexture_t *loadingscreentexture;
3921 void gl_main_start(void)
3922 {
3923         loadingscreentexture = NULL;
3924         r_texture_blanknormalmap = NULL;
3925         r_texture_white = NULL;
3926         r_texture_grey128 = NULL;
3927         r_texture_black = NULL;
3928         r_texture_whitecube = NULL;
3929         r_texture_normalizationcube = NULL;
3930         r_texture_fogattenuation = NULL;
3931         r_texture_fogheighttexture = NULL;
3932         r_texture_gammaramps = NULL;
3933         r_texture_numcubemaps = 0;
3934
3935         r_loaddds = r_texture_dds_load.integer != 0;
3936         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3937
3938         switch(vid.renderpath)
3939         {
3940         case RENDERPATH_GL20:
3941         case RENDERPATH_D3D9:
3942         case RENDERPATH_D3D10:
3943         case RENDERPATH_D3D11:
3944         case RENDERPATH_SOFT:
3945         case RENDERPATH_GLES2:
3946                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3947                 Cvar_SetValueQuick(&gl_combine, 1);
3948                 Cvar_SetValueQuick(&r_glsl, 1);
3949                 r_loadnormalmap = true;
3950                 r_loadgloss = true;
3951                 r_loadfog = false;
3952                 break;
3953         case RENDERPATH_GL13:
3954         case RENDERPATH_GLES1:
3955                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3956                 Cvar_SetValueQuick(&gl_combine, 1);
3957                 Cvar_SetValueQuick(&r_glsl, 0);
3958                 r_loadnormalmap = false;
3959                 r_loadgloss = false;
3960                 r_loadfog = true;
3961                 break;
3962         case RENDERPATH_GL11:
3963                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3964                 Cvar_SetValueQuick(&gl_combine, 0);
3965                 Cvar_SetValueQuick(&r_glsl, 0);
3966                 r_loadnormalmap = false;
3967                 r_loadgloss = false;
3968                 r_loadfog = true;
3969                 break;
3970         }
3971
3972         R_AnimCache_Free();
3973         R_FrameData_Reset();
3974
3975         r_numqueries = 0;
3976         r_maxqueries = 0;
3977         memset(r_queries, 0, sizeof(r_queries));
3978
3979         r_qwskincache = NULL;
3980         r_qwskincache_size = 0;
3981
3982         // due to caching of texture_t references, the collision cache must be reset
3983         Collision_Cache_Reset(true);
3984
3985         // set up r_skinframe loading system for textures
3986         memset(&r_skinframe, 0, sizeof(r_skinframe));
3987         r_skinframe.loadsequence = 1;
3988         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3989
3990         r_main_texturepool = R_AllocTexturePool();
3991         R_BuildBlankTextures();
3992         R_BuildNoTexture();
3993         if (vid.support.arb_texture_cube_map)
3994         {
3995                 R_BuildWhiteCube();
3996                 R_BuildNormalizationCube();
3997         }
3998         r_texture_fogattenuation = NULL;
3999         r_texture_fogheighttexture = NULL;
4000         r_texture_gammaramps = NULL;
4001         //r_texture_fogintensity = NULL;
4002         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4003         memset(&r_waterstate, 0, sizeof(r_waterstate));
4004         r_glsl_permutation = NULL;
4005         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4006         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4007         glslshaderstring = NULL;
4008 #ifdef SUPPORTD3D
4009         r_hlsl_permutation = NULL;
4010         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4011         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4012 #endif
4013         hlslshaderstring = NULL;
4014         memset(&r_svbsp, 0, sizeof (r_svbsp));
4015
4016         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4017         r_texture_numcubemaps = 0;
4018
4019         r_refdef.fogmasktable_density = 0;
4020 }
4021
4022 void gl_main_shutdown(void)
4023 {
4024         R_AnimCache_Free();
4025         R_FrameData_Reset();
4026
4027         R_Main_FreeViewCache();
4028
4029         switch(vid.renderpath)
4030         {
4031         case RENDERPATH_GL11:
4032         case RENDERPATH_GL13:
4033         case RENDERPATH_GL20:
4034         case RENDERPATH_GLES1:
4035         case RENDERPATH_GLES2:
4036                 if (r_maxqueries)
4037                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4038                 break;
4039         case RENDERPATH_D3D9:
4040                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4041                 break;
4042         case RENDERPATH_D3D10:
4043                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4044                 break;
4045         case RENDERPATH_D3D11:
4046                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4047                 break;
4048         case RENDERPATH_SOFT:
4049                 break;
4050         }
4051
4052         r_numqueries = 0;
4053         r_maxqueries = 0;
4054         memset(r_queries, 0, sizeof(r_queries));
4055
4056         r_qwskincache = NULL;
4057         r_qwskincache_size = 0;
4058
4059         // clear out the r_skinframe state
4060         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4061         memset(&r_skinframe, 0, sizeof(r_skinframe));
4062
4063         if (r_svbsp.nodes)
4064                 Mem_Free(r_svbsp.nodes);
4065         memset(&r_svbsp, 0, sizeof (r_svbsp));
4066         R_FreeTexturePool(&r_main_texturepool);
4067         loadingscreentexture = NULL;
4068         r_texture_blanknormalmap = NULL;
4069         r_texture_white = NULL;
4070         r_texture_grey128 = NULL;
4071         r_texture_black = NULL;
4072         r_texture_whitecube = NULL;
4073         r_texture_normalizationcube = NULL;
4074         r_texture_fogattenuation = NULL;
4075         r_texture_fogheighttexture = NULL;
4076         r_texture_gammaramps = NULL;
4077         r_texture_numcubemaps = 0;
4078         //r_texture_fogintensity = NULL;
4079         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4080         memset(&r_waterstate, 0, sizeof(r_waterstate));
4081         R_GLSL_Restart_f();
4082
4083         r_glsl_permutation = NULL;
4084         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4085         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4086         glslshaderstring = NULL;
4087 #ifdef SUPPORTD3D
4088         r_hlsl_permutation = NULL;
4089         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4090         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4091 #endif
4092         hlslshaderstring = NULL;
4093 }
4094
4095 extern void CL_ParseEntityLump(char *entitystring);
4096 void gl_main_newmap(void)
4097 {
4098         // FIXME: move this code to client
4099         char *entities, entname[MAX_QPATH];
4100         if (r_qwskincache)
4101                 Mem_Free(r_qwskincache);
4102         r_qwskincache = NULL;
4103         r_qwskincache_size = 0;
4104         if (cl.worldmodel)
4105         {
4106                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4107                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4108                 {
4109                         CL_ParseEntityLump(entities);
4110                         Mem_Free(entities);
4111                         return;
4112                 }
4113                 if (cl.worldmodel->brush.entities)
4114                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4115         }
4116         R_Main_FreeViewCache();
4117
4118         R_FrameData_Reset();
4119 }
4120
4121 void GL_Main_Init(void)
4122 {
4123         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4124
4125         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4126         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4127         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4128         if (gamemode == GAME_NEHAHRA)
4129         {
4130                 Cvar_RegisterVariable (&gl_fogenable);
4131                 Cvar_RegisterVariable (&gl_fogdensity);
4132                 Cvar_RegisterVariable (&gl_fogred);
4133                 Cvar_RegisterVariable (&gl_foggreen);
4134                 Cvar_RegisterVariable (&gl_fogblue);
4135                 Cvar_RegisterVariable (&gl_fogstart);
4136                 Cvar_RegisterVariable (&gl_fogend);
4137                 Cvar_RegisterVariable (&gl_skyclip);
4138         }
4139         Cvar_RegisterVariable(&r_motionblur);
4140         Cvar_RegisterVariable(&r_motionblur_maxblur);
4141         Cvar_RegisterVariable(&r_motionblur_bmin);
4142         Cvar_RegisterVariable(&r_motionblur_vmin);
4143         Cvar_RegisterVariable(&r_motionblur_vmax);
4144         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4145         Cvar_RegisterVariable(&r_motionblur_randomize);
4146         Cvar_RegisterVariable(&r_damageblur);
4147         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4148         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4149         Cvar_RegisterVariable(&r_equalize_entities_by);
4150         Cvar_RegisterVariable(&r_equalize_entities_to);
4151         Cvar_RegisterVariable(&r_depthfirst);
4152         Cvar_RegisterVariable(&r_useinfinitefarclip);
4153         Cvar_RegisterVariable(&r_farclip_base);
4154         Cvar_RegisterVariable(&r_farclip_world);
4155         Cvar_RegisterVariable(&r_nearclip);
4156         Cvar_RegisterVariable(&r_deformvertexes);
4157         Cvar_RegisterVariable(&r_transparent);
4158         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4159         Cvar_RegisterVariable(&r_showoverdraw);
4160         Cvar_RegisterVariable(&r_showbboxes);
4161         Cvar_RegisterVariable(&r_showsurfaces);
4162         Cvar_RegisterVariable(&r_showtris);
4163         Cvar_RegisterVariable(&r_shownormals);
4164         Cvar_RegisterVariable(&r_showlighting);
4165         Cvar_RegisterVariable(&r_showshadowvolumes);
4166         Cvar_RegisterVariable(&r_showcollisionbrushes);
4167         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4168         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4169         Cvar_RegisterVariable(&r_showdisabledepthtest);
4170         Cvar_RegisterVariable(&r_drawportals);
4171         Cvar_RegisterVariable(&r_drawentities);
4172         Cvar_RegisterVariable(&r_draw2d);
4173         Cvar_RegisterVariable(&r_drawworld);
4174         Cvar_RegisterVariable(&r_cullentities_trace);
4175         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4176         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4177         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4178         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4179         Cvar_RegisterVariable(&r_drawviewmodel);
4180         Cvar_RegisterVariable(&r_drawexteriormodel);
4181         Cvar_RegisterVariable(&r_speeds);
4182         Cvar_RegisterVariable(&r_fullbrights);
4183         Cvar_RegisterVariable(&r_wateralpha);
4184         Cvar_RegisterVariable(&r_dynamic);
4185         Cvar_RegisterVariable(&r_fakelight);
4186         Cvar_RegisterVariable(&r_fakelight_intensity);
4187         Cvar_RegisterVariable(&r_fullbright);
4188         Cvar_RegisterVariable(&r_shadows);
4189         Cvar_RegisterVariable(&r_shadows_darken);
4190         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4191         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4192         Cvar_RegisterVariable(&r_shadows_throwdistance);
4193         Cvar_RegisterVariable(&r_shadows_throwdirection);
4194         Cvar_RegisterVariable(&r_shadows_focus);
4195         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4196         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4197         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4198         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4199         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4200         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4201         Cvar_RegisterVariable(&r_fog_exp2);
4202         Cvar_RegisterVariable(&r_fog_clear);
4203         Cvar_RegisterVariable(&r_drawfog);
4204         Cvar_RegisterVariable(&r_transparentdepthmasking);
4205         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4206         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4207         Cvar_RegisterVariable(&r_texture_dds_load);
4208         Cvar_RegisterVariable(&r_texture_dds_save);
4209         Cvar_RegisterVariable(&r_textureunits);
4210         Cvar_RegisterVariable(&gl_combine);
4211         Cvar_RegisterVariable(&r_viewfbo);
4212         Cvar_RegisterVariable(&r_viewscale);
4213         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4214         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4215         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4216         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4217         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4218         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4219         Cvar_RegisterVariable(&r_glsl);
4220         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4221         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4222         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4223         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4224         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4225         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4226         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4227         Cvar_RegisterVariable(&r_glsl_postprocess);
4228         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4229         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4230         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4231         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4232         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4233         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4234         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4235         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4236
4237         Cvar_RegisterVariable(&r_water);
4238         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4239         Cvar_RegisterVariable(&r_water_clippingplanebias);
4240         Cvar_RegisterVariable(&r_water_refractdistort);
4241         Cvar_RegisterVariable(&r_water_reflectdistort);
4242         Cvar_RegisterVariable(&r_water_scissormode);
4243         Cvar_RegisterVariable(&r_water_lowquality);
4244
4245         Cvar_RegisterVariable(&r_lerpsprites);
4246         Cvar_RegisterVariable(&r_lerpmodels);
4247         Cvar_RegisterVariable(&r_lerplightstyles);
4248         Cvar_RegisterVariable(&r_waterscroll);
4249         Cvar_RegisterVariable(&r_bloom);
4250         Cvar_RegisterVariable(&r_bloom_colorscale);
4251         Cvar_RegisterVariable(&r_bloom_brighten);
4252         Cvar_RegisterVariable(&r_bloom_blur);
4253         Cvar_RegisterVariable(&r_bloom_resolution);
4254         Cvar_RegisterVariable(&r_bloom_colorexponent);
4255         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4256         Cvar_RegisterVariable(&r_hdr);
4257         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4258         Cvar_RegisterVariable(&r_hdr_glowintensity);
4259         Cvar_RegisterVariable(&r_hdr_range);
4260         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4261         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4262         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4263         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4264         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4265         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4266         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4267         Cvar_RegisterVariable(&developer_texturelogging);
4268         Cvar_RegisterVariable(&gl_lightmaps);
4269         Cvar_RegisterVariable(&r_test);
4270         Cvar_RegisterVariable(&r_glsl_saturation);
4271         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4272         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4273         Cvar_RegisterVariable(&r_framedatasize);
4274         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4275                 Cvar_SetValue("r_fullbrights", 0);
4276         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4277 }
4278
4279 extern void R_Textures_Init(void);
4280 extern void GL_Draw_Init(void);
4281 extern void GL_Main_Init(void);
4282 extern void R_Shadow_Init(void);
4283 extern void R_Sky_Init(void);
4284 extern void GL_Surf_Init(void);
4285 extern void R_Particles_Init(void);
4286 extern void R_Explosion_Init(void);
4287 extern void gl_backend_init(void);
4288 extern void Sbar_Init(void);
4289 extern void R_LightningBeams_Init(void);
4290 extern void Mod_RenderInit(void);
4291 extern void Font_Init(void);
4292
4293 void Render_Init(void)
4294 {
4295         gl_backend_init();
4296         R_Textures_Init();
4297         GL_Main_Init();
4298         Font_Init();
4299         GL_Draw_Init();
4300         R_Shadow_Init();
4301         R_Sky_Init();
4302         GL_Surf_Init();
4303         Sbar_Init();
4304         R_Particles_Init();
4305         R_Explosion_Init();
4306         R_LightningBeams_Init();
4307         Mod_RenderInit();
4308 }
4309
4310 /*
4311 ===============
4312 GL_Init
4313 ===============
4314 */
4315 extern char *ENGINE_EXTENSIONS;
4316 void GL_Init (void)
4317 {
4318         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4319         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4320         gl_version = (const char *)qglGetString(GL_VERSION);
4321         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4322
4323         if (!gl_extensions)
4324                 gl_extensions = "";
4325         if (!gl_platformextensions)
4326                 gl_platformextensions = "";
4327
4328         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4329         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4330         Con_Printf("GL_VERSION: %s\n", gl_version);
4331         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4332         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4333
4334         VID_CheckExtensions();
4335
4336         // LordHavoc: report supported extensions
4337         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4338
4339         // clear to black (loading plaque will be seen over this)
4340         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4341 }
4342
4343 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4344 {
4345         int i;
4346         mplane_t *p;
4347         if (r_trippy.integer)
4348                 return false;
4349         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4350         {
4351                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4352                 if (i == 4)
4353                         continue;
4354                 p = r_refdef.view.frustum + i;
4355                 switch(p->signbits)
4356                 {
4357                 default:
4358                 case 0:
4359                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4360                                 return true;
4361                         break;
4362                 case 1:
4363                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4364                                 return true;
4365                         break;
4366                 case 2:
4367                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4368                                 return true;
4369                         break;
4370                 case 3:
4371                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4372                                 return true;
4373                         break;
4374                 case 4:
4375                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4376                                 return true;
4377                         break;
4378                 case 5:
4379                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4380                                 return true;
4381                         break;
4382                 case 6:
4383                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4384                                 return true;
4385                         break;
4386                 case 7:
4387                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4388                                 return true;
4389                         break;
4390                 }
4391         }
4392         return false;
4393 }
4394
4395 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4396 {
4397         int i;
4398         const mplane_t *p;
4399         if (r_trippy.integer)
4400                 return false;
4401         for (i = 0;i < numplanes;i++)
4402         {
4403                 p = planes + i;
4404                 switch(p->signbits)
4405                 {
4406                 default:
4407                 case 0:
4408                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4409                                 return true;
4410                         break;
4411                 case 1:
4412                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4413                                 return true;
4414                         break;
4415                 case 2:
4416                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4417                                 return true;
4418                         break;
4419                 case 3:
4420                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4421                                 return true;
4422                         break;
4423                 case 4:
4424                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4425                                 return true;
4426                         break;
4427                 case 5:
4428                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 6:
4432                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 7:
4436                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 }
4440         }
4441         return false;
4442 }
4443
4444 //==================================================================================
4445
4446 // LordHavoc: this stores temporary data used within the same frame
4447
4448 typedef struct r_framedata_mem_s
4449 {
4450         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4451         size_t size; // how much usable space
4452         size_t current; // how much space in use
4453         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4454         size_t wantedsize; // how much space was allocated
4455         unsigned char *data; // start of real data (16byte aligned)
4456 }
4457 r_framedata_mem_t;
4458
4459 static r_framedata_mem_t *r_framedata_mem;
4460
4461 void R_FrameData_Reset(void)
4462 {
4463         while (r_framedata_mem)
4464         {
4465                 r_framedata_mem_t *next = r_framedata_mem->purge;
4466                 Mem_Free(r_framedata_mem);
4467                 r_framedata_mem = next;
4468         }
4469 }
4470
4471 void R_FrameData_Resize(void)
4472 {
4473         size_t wantedsize;
4474         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4475         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4476         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4477         {
4478                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4479                 newmem->wantedsize = wantedsize;
4480                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4481                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4482                 newmem->current = 0;
4483                 newmem->mark = 0;
4484                 newmem->purge = r_framedata_mem;
4485                 r_framedata_mem = newmem;
4486         }
4487 }
4488
4489 void R_FrameData_NewFrame(void)
4490 {
4491         R_FrameData_Resize();
4492         if (!r_framedata_mem)
4493                 return;
4494         // if we ran out of space on the last frame, free the old memory now
4495         while (r_framedata_mem->purge)
4496         {
4497                 // repeatedly remove the second item in the list, leaving only head
4498                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4499                 Mem_Free(r_framedata_mem->purge);
4500                 r_framedata_mem->purge = next;
4501         }
4502         // reset the current mem pointer
4503         r_framedata_mem->current = 0;
4504         r_framedata_mem->mark = 0;
4505 }
4506
4507 void *R_FrameData_Alloc(size_t size)
4508 {
4509         void *data;
4510
4511         // align to 16 byte boundary - the data pointer is already aligned, so we
4512         // only need to ensure the size of every allocation is also aligned
4513         size = (size + 15) & ~15;
4514
4515         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4516         {
4517                 // emergency - we ran out of space, allocate more memory
4518                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4519                 R_FrameData_Resize();
4520         }
4521
4522         data = r_framedata_mem->data + r_framedata_mem->current;
4523         r_framedata_mem->current += size;
4524
4525         // count the usage for stats
4526         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4527         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4528
4529         return (void *)data;
4530 }
4531
4532 void *R_FrameData_Store(size_t size, void *data)
4533 {
4534         void *d = R_FrameData_Alloc(size);
4535         if (d && data)
4536                 memcpy(d, data, size);
4537         return d;
4538 }
4539
4540 void R_FrameData_SetMark(void)
4541 {
4542         if (!r_framedata_mem)
4543                 return;
4544         r_framedata_mem->mark = r_framedata_mem->current;
4545 }
4546
4547 void R_FrameData_ReturnToMark(void)
4548 {
4549         if (!r_framedata_mem)
4550                 return;
4551         r_framedata_mem->current = r_framedata_mem->mark;
4552 }
4553
4554 //==================================================================================
4555
4556 // LordHavoc: animcache originally written by Echon, rewritten since then
4557
4558 /**
4559  * Animation cache prevents re-generating mesh data for an animated model
4560  * multiple times in one frame for lighting, shadowing, reflections, etc.
4561  */
4562
4563 void R_AnimCache_Free(void)
4564 {
4565 }
4566
4567 void R_AnimCache_ClearCache(void)
4568 {
4569         int i;
4570         entity_render_t *ent;
4571
4572         for (i = 0;i < r_refdef.scene.numentities;i++)
4573         {
4574                 ent = r_refdef.scene.entities[i];
4575                 ent->animcache_vertex3f = NULL;
4576                 ent->animcache_normal3f = NULL;
4577                 ent->animcache_svector3f = NULL;
4578                 ent->animcache_tvector3f = NULL;
4579                 ent->animcache_vertexmesh = NULL;
4580                 ent->animcache_vertex3fbuffer = NULL;
4581                 ent->animcache_vertexmeshbuffer = NULL;
4582         }
4583 }
4584
4585 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4586 {
4587         int i;
4588
4589         // check if we need the meshbuffers
4590         if (!vid.useinterleavedarrays)
4591                 return;
4592
4593         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4594                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4595         // TODO: upload vertex3f buffer?
4596         if (ent->animcache_vertexmesh)
4597         {
4598                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4599                 for (i = 0;i < numvertices;i++)
4600                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4601                 if (ent->animcache_svector3f)
4602                         for (i = 0;i < numvertices;i++)
4603                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4604                 if (ent->animcache_tvector3f)
4605                         for (i = 0;i < numvertices;i++)
4606                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4607                 if (ent->animcache_normal3f)
4608                         for (i = 0;i < numvertices;i++)
4609                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4610                 // TODO: upload vertexmeshbuffer?
4611         }
4612 }
4613
4614 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4615 {
4616         dp_model_t *model = ent->model;
4617         int numvertices;
4618         // see if it's already cached this frame
4619         if (ent->animcache_vertex3f)
4620         {
4621                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4622                 if (wantnormals || wanttangents)
4623                 {
4624                         if (ent->animcache_normal3f)
4625                                 wantnormals = false;
4626                         if (ent->animcache_svector3f)
4627                                 wanttangents = false;
4628                         if (wantnormals || wanttangents)
4629                         {
4630                                 numvertices = model->surfmesh.num_vertices;
4631                                 if (wantnormals)
4632                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4633                                 if (wanttangents)
4634                                 {
4635                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4636                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4637                                 }
4638                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4639                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4640                         }
4641                 }
4642         }
4643         else
4644         {
4645                 // see if this ent is worth caching
4646                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4647                         return false;
4648                 // get some memory for this entity and generate mesh data
4649                 numvertices = model->surfmesh.num_vertices;
4650                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4651                 if (wantnormals)
4652                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4653                 if (wanttangents)
4654                 {
4655                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4656                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4657                 }
4658                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4659                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4660         }
4661         return true;
4662 }
4663
4664 void R_AnimCache_CacheVisibleEntities(void)
4665 {
4666         int i;
4667         qboolean wantnormals = true;
4668         qboolean wanttangents = !r_showsurfaces.integer;
4669
4670         switch(vid.renderpath)
4671         {
4672         case RENDERPATH_GL20:
4673         case RENDERPATH_D3D9:
4674         case RENDERPATH_D3D10:
4675         case RENDERPATH_D3D11:
4676         case RENDERPATH_GLES2:
4677                 break;
4678         case RENDERPATH_GL11:
4679         case RENDERPATH_GL13:
4680         case RENDERPATH_GLES1:
4681                 wanttangents = false;
4682                 break;
4683         case RENDERPATH_SOFT:
4684                 break;
4685         }
4686
4687         if (r_shownormals.integer)
4688                 wanttangents = wantnormals = true;
4689
4690         // TODO: thread this
4691         // NOTE: R_PrepareRTLights() also caches entities
4692
4693         for (i = 0;i < r_refdef.scene.numentities;i++)
4694                 if (r_refdef.viewcache.entityvisible[i])
4695                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4696 }
4697
4698 //==================================================================================
4699
4700 extern cvar_t r_overheadsprites_pushback;
4701
4702 static void R_View_UpdateEntityLighting (void)
4703 {
4704         int i;
4705         entity_render_t *ent;
4706         vec3_t tempdiffusenormal, avg;
4707         vec_t f, fa, fd, fdd;
4708         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4709
4710         for (i = 0;i < r_refdef.scene.numentities;i++)
4711         {
4712                 ent = r_refdef.scene.entities[i];
4713
4714                 // skip unseen models
4715                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4716                         continue;
4717
4718                 // skip bsp models
4719                 if (ent->model && ent->model->brush.num_leafs)
4720                 {
4721                         // TODO: use modellight for r_ambient settings on world?
4722                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4723                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4724                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4725                         continue;
4726                 }
4727
4728                 // fetch the lighting from the worldmodel data
4729                 VectorClear(ent->modellight_ambient);
4730                 VectorClear(ent->modellight_diffuse);
4731                 VectorClear(tempdiffusenormal);
4732                 if (ent->flags & RENDER_LIGHT)
4733                 {
4734                         vec3_t org;
4735                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4736
4737                         // complete lightning for lit sprites
4738                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4739                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4740                         {
4741                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4742                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4743                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4744                         }
4745                         else
4746                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4747
4748                         if(ent->flags & RENDER_EQUALIZE)
4749                         {
4750                                 // first fix up ambient lighting...
4751                                 if(r_equalize_entities_minambient.value > 0)
4752                                 {
4753                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4754                                         if(fd > 0)
4755                                         {
4756                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4757                                                 if(fa < r_equalize_entities_minambient.value * fd)
4758                                                 {
4759                                                         // solve:
4760                                                         //   fa'/fd' = minambient
4761                                                         //   fa'+0.25*fd' = fa+0.25*fd
4762                                                         //   ...
4763                                                         //   fa' = fd' * minambient
4764                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4765                                                         //   ...
4766                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4767                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4768                                                         //   ...
4769                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4770                                                         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
4771                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4772                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4773                                                 }
4774                                         }
4775                                 }
4776
4777                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4778                                 {
4779                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4780                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4781                                         f = fa + 0.25 * fd;
4782                                         if(f > 0)
4783                                         {
4784                                                 // adjust brightness and saturation to target
4785                                                 avg[0] = avg[1] = avg[2] = fa / f;
4786                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4787                                                 avg[0] = avg[1] = avg[2] = fd / f;
4788                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4789                                         }
4790                                 }
4791                         }
4792                 }
4793                 else // highly rare
4794                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4795
4796                 // move the light direction into modelspace coordinates for lighting code
4797                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4798                 if(VectorLength2(ent->modellight_lightdir) == 0)
4799                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4800                 VectorNormalize(ent->modellight_lightdir);
4801         }
4802 }
4803
4804 #define MAX_LINEOFSIGHTTRACES 64
4805
4806 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4807 {
4808         int i;
4809         vec3_t boxmins, boxmaxs;
4810         vec3_t start;
4811         vec3_t end;
4812         dp_model_t *model = r_refdef.scene.worldmodel;
4813
4814         if (!model || !model->brush.TraceLineOfSight)
4815                 return true;
4816
4817         // expand the box a little
4818         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4819         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4820         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4821         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4822         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4823         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4824
4825         // return true if eye is inside enlarged box
4826         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4827                 return true;
4828
4829         // try center
4830         VectorCopy(eye, start);
4831         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4832         if (model->brush.TraceLineOfSight(model, start, end))
4833                 return true;
4834
4835         // try various random positions
4836         for (i = 0;i < numsamples;i++)
4837         {
4838                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4839                 if (model->brush.TraceLineOfSight(model, start, end))
4840                         return true;
4841         }
4842
4843         return false;
4844 }
4845
4846
4847 static void R_View_UpdateEntityVisible (void)
4848 {
4849         int i;
4850         int renderimask;
4851         int samples;
4852         entity_render_t *ent;
4853
4854         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4855                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4856                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4857                 :                                                          RENDER_EXTERIORMODEL;
4858         if (!r_drawviewmodel.integer)
4859                 renderimask |= RENDER_VIEWMODEL;
4860         if (!r_drawexteriormodel.integer)
4861                 renderimask |= RENDER_EXTERIORMODEL;
4862         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4863         {
4864                 // worldmodel can check visibility
4865                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4866                 for (i = 0;i < r_refdef.scene.numentities;i++)
4867                 {
4868                         ent = r_refdef.scene.entities[i];
4869                         if (!(ent->flags & renderimask))
4870                         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)))
4871                         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))
4872                                 r_refdef.viewcache.entityvisible[i] = true;
4873                 }
4874         }
4875         else
4876         {
4877                 // no worldmodel or it can't check visibility
4878                 for (i = 0;i < r_refdef.scene.numentities;i++)
4879                 {
4880                         ent = r_refdef.scene.entities[i];
4881                         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));
4882                 }
4883         }
4884         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4885                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4886         {
4887                 for (i = 0;i < r_refdef.scene.numentities;i++)
4888                 {
4889                         if (!r_refdef.viewcache.entityvisible[i])
4890                                 continue;
4891                         ent = r_refdef.scene.entities[i];
4892                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4893                         {
4894                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4895                                 if (samples < 0)
4896                                         continue; // temp entities do pvs only
4897                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4898                                         ent->last_trace_visibility = realtime;
4899                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4900                                         r_refdef.viewcache.entityvisible[i] = 0;
4901                         }
4902                 }
4903         }
4904 }
4905
4906 /// only used if skyrendermasked, and normally returns false
4907 int R_DrawBrushModelsSky (void)
4908 {
4909         int i, sky;
4910         entity_render_t *ent;
4911
4912         sky = false;
4913         for (i = 0;i < r_refdef.scene.numentities;i++)
4914         {
4915                 if (!r_refdef.viewcache.entityvisible[i])
4916                         continue;
4917                 ent = r_refdef.scene.entities[i];
4918                 if (!ent->model || !ent->model->DrawSky)
4919                         continue;
4920                 ent->model->DrawSky(ent);
4921                 sky = true;
4922         }
4923         return sky;
4924 }
4925
4926 static void R_DrawNoModel(entity_render_t *ent);
4927 static void R_DrawModels(void)
4928 {
4929         int i;
4930         entity_render_t *ent;
4931
4932         for (i = 0;i < r_refdef.scene.numentities;i++)
4933         {
4934                 if (!r_refdef.viewcache.entityvisible[i])
4935                         continue;
4936                 ent = r_refdef.scene.entities[i];
4937                 r_refdef.stats.entities++;
4938                 /*
4939                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4940                 {
4941                         vec3_t f, l, u, o;
4942                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4943                         Con_Printf("R_DrawModels\n");
4944                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
4945                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
4946                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
4947                 }
4948                 */
4949                 if (ent->model && ent->model->Draw != NULL)
4950                         ent->model->Draw(ent);
4951                 else
4952                         R_DrawNoModel(ent);
4953         }
4954 }
4955
4956 static void R_DrawModelsDepth(void)
4957 {
4958         int i;
4959         entity_render_t *ent;
4960
4961         for (i = 0;i < r_refdef.scene.numentities;i++)
4962         {
4963                 if (!r_refdef.viewcache.entityvisible[i])
4964                         continue;
4965                 ent = r_refdef.scene.entities[i];
4966                 if (ent->model && ent->model->DrawDepth != NULL)
4967                         ent->model->DrawDepth(ent);
4968         }
4969 }
4970
4971 static void R_DrawModelsDebug(void)
4972 {
4973         int i;
4974         entity_render_t *ent;
4975
4976         for (i = 0;i < r_refdef.scene.numentities;i++)
4977         {
4978                 if (!r_refdef.viewcache.entityvisible[i])
4979                         continue;
4980                 ent = r_refdef.scene.entities[i];
4981                 if (ent->model && ent->model->DrawDebug != NULL)
4982                         ent->model->DrawDebug(ent);
4983         }
4984 }
4985
4986 static void R_DrawModelsAddWaterPlanes(void)
4987 {
4988         int i;
4989         entity_render_t *ent;
4990
4991         for (i = 0;i < r_refdef.scene.numentities;i++)
4992         {
4993                 if (!r_refdef.viewcache.entityvisible[i])
4994                         continue;
4995                 ent = r_refdef.scene.entities[i];
4996                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4997                         ent->model->DrawAddWaterPlanes(ent);
4998         }
4999 }
5000
5001 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5002 {
5003         if (r_hdr_irisadaptation.integer)
5004         {
5005                 vec3_t ambient;
5006                 vec3_t diffuse;
5007                 vec3_t diffusenormal;
5008                 vec_t brightness;
5009                 vec_t goal;
5010                 vec_t adjust;
5011                 vec_t current;
5012                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5013                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5014                 brightness = max(0.0000001f, brightness);
5015                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5016                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5017                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
5018                 current = r_hdr_irisadaptation_value.value;
5019                 if (current < goal)
5020                         current = min(current + adjust, goal);
5021                 else if (current > goal)
5022                         current = max(current - adjust, goal);
5023                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5024                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5025         }
5026         else if (r_hdr_irisadaptation_value.value != 1.0f)
5027                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5028 }
5029
5030 static void R_View_SetFrustum(const int *scissor)
5031 {
5032         int i;
5033         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5034         vec3_t forward, left, up, origin, v;
5035
5036         if(scissor)
5037         {
5038                 // flipped x coordinates (because x points left here)
5039                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5040                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5041
5042                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5043                 switch(vid.renderpath)
5044                 {
5045                         case RENDERPATH_D3D9:
5046                         case RENDERPATH_D3D10:
5047                         case RENDERPATH_D3D11:
5048                                 // non-flipped y coordinates
5049                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5050                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5051                                 break;
5052                         case RENDERPATH_SOFT:
5053                         case RENDERPATH_GL11:
5054                         case RENDERPATH_GL13:
5055                         case RENDERPATH_GL20:
5056                         case RENDERPATH_GLES1:
5057                         case RENDERPATH_GLES2:
5058                                 // non-flipped y coordinates
5059                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5060                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5061                                 break;
5062                 }
5063         }
5064
5065         // we can't trust r_refdef.view.forward and friends in reflected scenes
5066         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5067
5068 #if 0
5069         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5070         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5071         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5072         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5073         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5074         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5075         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5076         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5077         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5078         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5079         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5080         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5081 #endif
5082
5083 #if 0
5084         zNear = r_refdef.nearclip;
5085         nudge = 1.0 - 1.0 / (1<<23);
5086         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5087         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5088         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5089         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5090         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5091         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5092         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5093         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5094 #endif
5095
5096
5097
5098 #if 0
5099         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5100         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5101         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5102         r_refdef.view.frustum[0].dist = m[15] - m[12];
5103
5104         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5105         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5106         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5107         r_refdef.view.frustum[1].dist = m[15] + m[12];
5108
5109         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5110         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5111         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5112         r_refdef.view.frustum[2].dist = m[15] - m[13];
5113
5114         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5115         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5116         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5117         r_refdef.view.frustum[3].dist = m[15] + m[13];
5118
5119         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5120         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5121         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5122         r_refdef.view.frustum[4].dist = m[15] - m[14];
5123
5124         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5125         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5126         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5127         r_refdef.view.frustum[5].dist = m[15] + m[14];
5128 #endif
5129
5130         if (r_refdef.view.useperspective)
5131         {
5132                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5133                 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]);
5134                 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]);
5135                 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]);
5136                 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]);
5137
5138                 // then the normals from the corners relative to origin
5139                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5140                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5141                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5142                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5143
5144                 // in a NORMAL view, forward cross left == up
5145                 // in a REFLECTED view, forward cross left == down
5146                 // so our cross products above need to be adjusted for a left handed coordinate system
5147                 CrossProduct(forward, left, v);
5148                 if(DotProduct(v, up) < 0)
5149                 {
5150                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5151                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5152                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5153                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5154                 }
5155
5156                 // Leaving those out was a mistake, those were in the old code, and they
5157                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5158                 // I couldn't reproduce it after adding those normalizations. --blub
5159                 VectorNormalize(r_refdef.view.frustum[0].normal);
5160                 VectorNormalize(r_refdef.view.frustum[1].normal);
5161                 VectorNormalize(r_refdef.view.frustum[2].normal);
5162                 VectorNormalize(r_refdef.view.frustum[3].normal);
5163
5164                 // make the corners absolute
5165                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5166                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5167                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5168                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5169
5170                 // one more normal
5171                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5172
5173                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5174                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5175                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5176                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5177                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5178         }
5179         else
5180         {
5181                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5182                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5183                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5184                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5185                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5186                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5187                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5188                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5189                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5190                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5191         }
5192         r_refdef.view.numfrustumplanes = 5;
5193
5194         if (r_refdef.view.useclipplane)
5195         {
5196                 r_refdef.view.numfrustumplanes = 6;
5197                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5198         }
5199
5200         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5201                 PlaneClassify(r_refdef.view.frustum + i);
5202
5203         // LordHavoc: note to all quake engine coders, Quake had a special case
5204         // for 90 degrees which assumed a square view (wrong), so I removed it,
5205         // Quake2 has it disabled as well.
5206
5207         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5208         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5209         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5210         //PlaneClassify(&frustum[0]);
5211
5212         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5213         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5214         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5215         //PlaneClassify(&frustum[1]);
5216
5217         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5218         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5219         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5220         //PlaneClassify(&frustum[2]);
5221
5222         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5223         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5224         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5225         //PlaneClassify(&frustum[3]);
5226
5227         // nearclip plane
5228         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5229         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5230         //PlaneClassify(&frustum[4]);
5231 }
5232
5233 void R_View_UpdateWithScissor(const int *myscissor)
5234 {
5235         R_Main_ResizeViewCache();
5236         R_View_SetFrustum(myscissor);
5237         R_View_WorldVisibility(r_refdef.view.useclipplane);
5238         R_View_UpdateEntityVisible();
5239         R_View_UpdateEntityLighting();
5240 }
5241
5242 void R_View_Update(void)
5243 {
5244         R_Main_ResizeViewCache();
5245         R_View_SetFrustum(NULL);
5246         R_View_WorldVisibility(r_refdef.view.useclipplane);
5247         R_View_UpdateEntityVisible();
5248         R_View_UpdateEntityLighting();
5249 }
5250
5251 float viewscalefpsadjusted = 1.0f;
5252
5253 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5254 {
5255         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5256         scale = bound(0.03125f, scale, 1.0f);
5257         *outwidth = (int)ceil(width * scale);
5258         *outheight = (int)ceil(height * scale);
5259 }
5260
5261 void R_Mesh_SetMainRenderTargets(void)
5262 {
5263         if (r_bloomstate.fbo_framebuffer)
5264                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5265         else
5266                 R_Mesh_ResetRenderTargets();
5267 }
5268
5269 void R_SetupView(qboolean allowwaterclippingplane)
5270 {
5271         const float *customclipplane = NULL;
5272         float plane[4];
5273         int scaledwidth, scaledheight;
5274         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5275         {
5276                 // LordHavoc: couldn't figure out how to make this approach the
5277                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5278                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5279                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5280                         dist = r_refdef.view.clipplane.dist;
5281                 plane[0] = r_refdef.view.clipplane.normal[0];
5282                 plane[1] = r_refdef.view.clipplane.normal[1];
5283                 plane[2] = r_refdef.view.clipplane.normal[2];
5284                 plane[3] = -dist;
5285                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5286         }
5287
5288         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5289         if (!r_refdef.view.useperspective)
5290                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -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);
5291         else if (vid.stencil && r_useinfinitefarclip.integer)
5292                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5293         else
5294                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5295         R_Mesh_SetMainRenderTargets();
5296         R_SetViewport(&r_refdef.view.viewport);
5297         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5298         {
5299                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5300                 float screenplane[4];
5301                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5302                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5303                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5304                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5305                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5306         }
5307 }
5308
5309 void R_EntityMatrix(const matrix4x4_t *matrix)
5310 {
5311         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5312         {
5313                 gl_modelmatrixchanged = false;
5314                 gl_modelmatrix = *matrix;
5315                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5316                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5317                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5318                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5319                 CHECKGLERROR
5320                 switch(vid.renderpath)
5321                 {
5322                 case RENDERPATH_D3D9:
5323 #ifdef SUPPORTD3D
5324                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5325                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5326 #endif
5327                         break;
5328                 case RENDERPATH_D3D10:
5329                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5330                         break;
5331                 case RENDERPATH_D3D11:
5332                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5333                         break;
5334                 case RENDERPATH_GL11:
5335                 case RENDERPATH_GL13:
5336                 case RENDERPATH_GLES1:
5337                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5338                         break;
5339                 case RENDERPATH_SOFT:
5340                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5341                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5342                         break;
5343                 case RENDERPATH_GL20:
5344                 case RENDERPATH_GLES2:
5345                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5346                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5347                         break;
5348                 }
5349         }
5350 }
5351
5352 void R_ResetViewRendering2D(void)
5353 {
5354         r_viewport_t viewport;
5355         DrawQ_Finish();
5356
5357         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5358         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);
5359         R_Mesh_ResetRenderTargets();
5360         R_SetViewport(&viewport);
5361         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5362         GL_Color(1, 1, 1, 1);
5363         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5364         GL_BlendFunc(GL_ONE, GL_ZERO);
5365         GL_ScissorTest(false);
5366         GL_DepthMask(false);
5367         GL_DepthRange(0, 1);
5368         GL_DepthTest(false);
5369         GL_DepthFunc(GL_LEQUAL);
5370         R_EntityMatrix(&identitymatrix);
5371         R_Mesh_ResetTextureState();
5372         GL_PolygonOffset(0, 0);
5373         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5374         switch(vid.renderpath)
5375         {
5376         case RENDERPATH_GL11:
5377         case RENDERPATH_GL13:
5378         case RENDERPATH_GL20:
5379         case RENDERPATH_GLES1:
5380         case RENDERPATH_GLES2:
5381                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5382                 break;
5383         case RENDERPATH_D3D9:
5384         case RENDERPATH_D3D10:
5385         case RENDERPATH_D3D11:
5386         case RENDERPATH_SOFT:
5387                 break;
5388         }
5389         GL_CullFace(GL_NONE);
5390 }
5391
5392 void R_ResetViewRendering3D(void)
5393 {
5394         DrawQ_Finish();
5395
5396         R_SetupView(true);
5397         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5398         GL_Color(1, 1, 1, 1);
5399         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5400         GL_BlendFunc(GL_ONE, GL_ZERO);
5401         GL_ScissorTest(true);
5402         GL_DepthMask(true);
5403         GL_DepthRange(0, 1);
5404         GL_DepthTest(true);
5405         GL_DepthFunc(GL_LEQUAL);
5406         R_EntityMatrix(&identitymatrix);
5407         R_Mesh_ResetTextureState();
5408         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5409         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5410         switch(vid.renderpath)
5411         {
5412         case RENDERPATH_GL11:
5413         case RENDERPATH_GL13:
5414         case RENDERPATH_GL20:
5415         case RENDERPATH_GLES1:
5416         case RENDERPATH_GLES2:
5417                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5418                 break;
5419         case RENDERPATH_D3D9:
5420         case RENDERPATH_D3D10:
5421         case RENDERPATH_D3D11:
5422         case RENDERPATH_SOFT:
5423                 break;
5424         }
5425         GL_CullFace(r_refdef.view.cullface_back);
5426 }
5427
5428 /*
5429 ================
5430 R_RenderView_UpdateViewVectors
5431 ================
5432 */
5433 static void R_RenderView_UpdateViewVectors(void)
5434 {
5435         // break apart the view matrix into vectors for various purposes
5436         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5437         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5438         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5439         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5440         // make an inverted copy of the view matrix for tracking sprites
5441         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5442 }
5443
5444 void R_RenderScene(void);
5445 void R_RenderWaterPlanes(void);
5446
5447 static void R_Water_StartFrame(void)
5448 {
5449         int i;
5450         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5451         r_waterstate_waterplane_t *p;
5452
5453         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5454                 return;
5455
5456         switch(vid.renderpath)
5457         {
5458         case RENDERPATH_GL20:
5459         case RENDERPATH_D3D9:
5460         case RENDERPATH_D3D10:
5461         case RENDERPATH_D3D11:
5462         case RENDERPATH_SOFT:
5463         case RENDERPATH_GLES2:
5464                 break;
5465         case RENDERPATH_GL11:
5466         case RENDERPATH_GL13:
5467         case RENDERPATH_GLES1:
5468                 return;
5469         }
5470
5471         // set waterwidth and waterheight to the water resolution that will be
5472         // used (often less than the screen resolution for faster rendering)
5473         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5474
5475         // calculate desired texture sizes
5476         // can't use water if the card does not support the texture size
5477         if (!r_water.integer || r_showsurfaces.integer)
5478                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5479         else if (vid.support.arb_texture_non_power_of_two)
5480         {
5481                 texturewidth = waterwidth;
5482                 textureheight = waterheight;
5483                 camerawidth = waterwidth;
5484                 cameraheight = waterheight;
5485         }
5486         else
5487         {
5488                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5489                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5490                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5491                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5492         }
5493
5494         // allocate textures as needed
5495         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5496         {
5497                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5498                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5499                 {
5500                         if (p->texture_refraction)
5501                                 R_FreeTexture(p->texture_refraction);
5502                         p->texture_refraction = NULL;
5503                         if (p->texture_reflection)
5504                                 R_FreeTexture(p->texture_reflection);
5505                         p->texture_reflection = NULL;
5506                         if (p->texture_camera)
5507                                 R_FreeTexture(p->texture_camera);
5508                         p->texture_camera = NULL;
5509                 }
5510                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5511                 r_waterstate.texturewidth = texturewidth;
5512                 r_waterstate.textureheight = textureheight;
5513                 r_waterstate.camerawidth = camerawidth;
5514                 r_waterstate.cameraheight = cameraheight;
5515         }
5516
5517         if (r_waterstate.texturewidth)
5518         {
5519                 int scaledwidth, scaledheight;
5520
5521                 r_waterstate.enabled = true;
5522
5523                 // when doing a reduced render (HDR) we want to use a smaller area
5524                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5525                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5526                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5527
5528                 // set up variables that will be used in shader setup
5529                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5530                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5531                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5532                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5533         }
5534
5535         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5536         r_waterstate.numwaterplanes = 0;
5537 }
5538
5539 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5540 {
5541         int triangleindex, planeindex;
5542         const int *e;
5543         vec3_t vert[3];
5544         vec3_t normal;
5545         vec3_t center;
5546         mplane_t plane;
5547         r_waterstate_waterplane_t *p;
5548         texture_t *t = R_GetCurrentTexture(surface->texture);
5549
5550         // just use the first triangle with a valid normal for any decisions
5551         VectorClear(normal);
5552         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5553         {
5554                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5555                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5556                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5557                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5558                 if (VectorLength2(normal) >= 0.001)
5559                         break;
5560         }
5561
5562         VectorCopy(normal, plane.normal);
5563         VectorNormalize(plane.normal);
5564         plane.dist = DotProduct(vert[0], plane.normal);
5565         PlaneClassify(&plane);
5566         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5567         {
5568                 // skip backfaces (except if nocullface is set)
5569                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5570                         return;
5571                 VectorNegate(plane.normal, plane.normal);
5572                 plane.dist *= -1;
5573                 PlaneClassify(&plane);
5574         }
5575
5576
5577         // find a matching plane if there is one
5578         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5579                 if(p->camera_entity == t->camera_entity)
5580                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5581                                 break;
5582         if (planeindex >= r_waterstate.maxwaterplanes)
5583                 return; // nothing we can do, out of planes
5584
5585         // if this triangle does not fit any known plane rendered this frame, add one
5586         if (planeindex >= r_waterstate.numwaterplanes)
5587         {
5588                 // store the new plane
5589                 r_waterstate.numwaterplanes++;
5590                 p->plane = plane;
5591                 // clear materialflags and pvs
5592                 p->materialflags = 0;
5593                 p->pvsvalid = false;
5594                 p->camera_entity = t->camera_entity;
5595                 VectorCopy(surface->mins, p->mins);
5596                 VectorCopy(surface->maxs, p->maxs);
5597         }
5598         else
5599         {
5600                 // merge mins/maxs
5601                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5602                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5603                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5604                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5605                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5606                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5607         }
5608         // merge this surface's materialflags into the waterplane
5609         p->materialflags |= t->currentmaterialflags;
5610         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5611         {
5612                 // merge this surface's PVS into the waterplane
5613                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5614                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5615                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5616                 {
5617                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5618                         p->pvsvalid = true;
5619                 }
5620         }
5621 }
5622
5623 extern cvar_t r_drawparticles;
5624 extern cvar_t r_drawdecals;
5625
5626 static void R_Water_ProcessPlanes(void)
5627 {
5628         int myscissor[4];
5629         r_refdef_view_t originalview;
5630         r_refdef_view_t myview;
5631         int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5632         r_waterstate_waterplane_t *p;
5633         vec3_t visorigin;
5634
5635         originalview = r_refdef.view;
5636
5637         // lowquality hack, temporarily shut down some cvars and restore afterwards
5638         qualityreduction = r_water_lowquality.integer;
5639         if (qualityreduction > 0)
5640         {
5641                 if (qualityreduction >= 1)
5642                 {
5643                         old_r_shadows = r_shadows.integer;
5644                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5645                         old_r_dlight = r_shadow_realtime_dlight.integer;
5646                         Cvar_SetValueQuick(&r_shadows, 0);
5647                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5648                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5649                 }
5650                 if (qualityreduction >= 2)
5651                 {
5652                         old_r_dynamic = r_dynamic.integer;
5653                         old_r_particles = r_drawparticles.integer;
5654                         old_r_decals = r_drawdecals.integer;
5655                         Cvar_SetValueQuick(&r_dynamic, 0);
5656                         Cvar_SetValueQuick(&r_drawparticles, 0);
5657                         Cvar_SetValueQuick(&r_drawdecals, 0);
5658                 }
5659         }
5660
5661         // make sure enough textures are allocated
5662         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5663         {
5664                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5665                 {
5666                         if (!p->texture_refraction)
5667                                 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);
5668                         if (!p->texture_refraction)
5669                                 goto error;
5670                 }
5671                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5672                 {
5673                         if (!p->texture_camera)
5674                                 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);
5675                         if (!p->texture_camera)
5676                                 goto error;
5677                 }
5678
5679                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5680                 {
5681                         if (!p->texture_reflection)
5682                                 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);
5683                         if (!p->texture_reflection)
5684                                 goto error;
5685                 }
5686         }
5687
5688         // render views
5689         r_refdef.view = originalview;
5690         r_refdef.view.showdebug = false;
5691         r_refdef.view.width = r_waterstate.waterwidth;
5692         r_refdef.view.height = r_waterstate.waterheight;
5693         r_refdef.view.useclipplane = true;
5694         myview = r_refdef.view;
5695         r_waterstate.renderingscene = true;
5696         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5697         {
5698                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5699                 {
5700                         r_refdef.view = myview;
5701                         if(r_water_scissormode.integer)
5702                         {
5703                                 R_SetupView(true);
5704                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5705                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5706                         }
5707
5708                         // render reflected scene and copy into texture
5709                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5710                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5711                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5712                         r_refdef.view.clipplane = p->plane;
5713                         // reverse the cullface settings for this render
5714                         r_refdef.view.cullface_front = GL_FRONT;
5715                         r_refdef.view.cullface_back = GL_BACK;
5716                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5717                         {
5718                                 r_refdef.view.usecustompvs = true;
5719                                 if (p->pvsvalid)
5720                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5721                                 else
5722                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5723                         }
5724
5725                         R_ResetViewRendering3D();
5726                         R_ClearScreen(r_refdef.fogenabled);
5727                         if(r_water_scissormode.integer & 2)
5728                                 R_View_UpdateWithScissor(myscissor);
5729                         else
5730                                 R_View_Update();
5731                         if(r_water_scissormode.integer & 1)
5732                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5733                         R_RenderScene();
5734
5735                         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);
5736                 }
5737
5738                 // render the normal view scene and copy into texture
5739                 // (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)
5740                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5741                 {
5742                         r_refdef.view = myview;
5743                         if(r_water_scissormode.integer)
5744                         {
5745                                 R_SetupView(true);
5746                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5747                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5748                         }
5749
5750                         r_waterstate.renderingrefraction = true;
5751
5752                         r_refdef.view.clipplane = p->plane;
5753                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5754                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5755
5756                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5757                         {
5758                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5759                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5760                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5761                                 R_RenderView_UpdateViewVectors();
5762                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5763                                 {
5764                                         r_refdef.view.usecustompvs = true;
5765                                         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);
5766                                 }
5767                         }
5768
5769                         PlaneClassify(&r_refdef.view.clipplane);
5770
5771                         R_ResetViewRendering3D();
5772                         R_ClearScreen(r_refdef.fogenabled);
5773                         if(r_water_scissormode.integer & 2)
5774                                 R_View_UpdateWithScissor(myscissor);
5775                         else
5776                                 R_View_Update();
5777                         if(r_water_scissormode.integer & 1)
5778                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5779                         R_RenderScene();
5780
5781                         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);
5782                         r_waterstate.renderingrefraction = false;
5783                 }
5784                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5785                 {
5786                         r_refdef.view = myview;
5787
5788                         r_refdef.view.clipplane = p->plane;
5789                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5790                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5791
5792                         r_refdef.view.width = r_waterstate.camerawidth;
5793                         r_refdef.view.height = r_waterstate.cameraheight;
5794                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5795                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5796
5797                         if(p->camera_entity)
5798                         {
5799                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5800                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5801                         }
5802
5803                         // note: all of the view is used for displaying... so
5804                         // there is no use in scissoring
5805
5806                         // reverse the cullface settings for this render
5807                         r_refdef.view.cullface_front = GL_FRONT;
5808                         r_refdef.view.cullface_back = GL_BACK;
5809                         // also reverse the view matrix
5810                         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
5811                         R_RenderView_UpdateViewVectors();
5812                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5813                         {
5814                                 r_refdef.view.usecustompvs = true;
5815                                 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);
5816                         }
5817                         
5818                         // camera needs no clipplane
5819                         r_refdef.view.useclipplane = false;
5820
5821                         PlaneClassify(&r_refdef.view.clipplane);
5822
5823                         R_ResetViewRendering3D();
5824                         R_ClearScreen(r_refdef.fogenabled);
5825                         R_View_Update();
5826                         R_RenderScene();
5827
5828                         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);
5829                         r_waterstate.renderingrefraction = false;
5830                 }
5831
5832         }
5833         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5834         r_waterstate.renderingscene = false;
5835         r_refdef.view = originalview;
5836         R_ResetViewRendering3D();
5837         R_ClearScreen(r_refdef.fogenabled);
5838         R_View_Update();
5839         goto finish;
5840 error:
5841         r_refdef.view = originalview;
5842         r_waterstate.renderingscene = false;
5843         Cvar_SetValueQuick(&r_water, 0);
5844         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5845 finish:
5846         // lowquality hack, restore cvars
5847         if (qualityreduction > 0)
5848         {
5849                 if (qualityreduction >= 1)
5850                 {
5851                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5852                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5853                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5854                 }
5855                 if (qualityreduction >= 2)
5856                 {
5857                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5858                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5859                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5860                 }
5861         }
5862 }
5863
5864 void R_Bloom_StartFrame(void)
5865 {
5866         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5867         int viewwidth, viewheight;
5868         textype_t textype;
5869
5870         if (r_viewscale_fpsscaling.integer)
5871         {
5872                 double actualframetime;
5873                 double targetframetime;
5874                 double adjust;
5875                 actualframetime = r_refdef.lastdrawscreentime;
5876                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5877                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5878                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5879                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5880                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5881                 viewscalefpsadjusted += adjust;
5882                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5883         }
5884         else
5885                 viewscalefpsadjusted = 1.0f;
5886
5887         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5888
5889         switch(vid.renderpath)
5890         {
5891         case RENDERPATH_GL20:
5892         case RENDERPATH_D3D9:
5893         case RENDERPATH_D3D10:
5894         case RENDERPATH_D3D11:
5895         case RENDERPATH_SOFT:
5896         case RENDERPATH_GLES2:
5897                 break;
5898         case RENDERPATH_GL11:
5899         case RENDERPATH_GL13:
5900         case RENDERPATH_GLES1:
5901                 return;
5902         }
5903
5904         // set bloomwidth and bloomheight to the bloom resolution that will be
5905         // used (often less than the screen resolution for faster rendering)
5906         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5907         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5908         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5909         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5910         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5911
5912         // calculate desired texture sizes
5913         if (vid.support.arb_texture_non_power_of_two)
5914         {
5915                 screentexturewidth = vid.width;
5916                 screentextureheight = vid.height;
5917                 bloomtexturewidth = r_bloomstate.bloomwidth;
5918                 bloomtextureheight = r_bloomstate.bloomheight;
5919         }
5920         else
5921         {
5922                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5923                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5924                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5925                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5926         }
5927
5928         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))
5929         {
5930                 Cvar_SetValueQuick(&r_hdr, 0);
5931                 Cvar_SetValueQuick(&r_bloom, 0);
5932                 Cvar_SetValueQuick(&r_motionblur, 0);
5933                 Cvar_SetValueQuick(&r_damageblur, 0);
5934         }
5935
5936         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)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5937                 screentexturewidth = screentextureheight = 0;
5938         if (!r_hdr.integer && !r_bloom.integer)
5939                 bloomtexturewidth = bloomtextureheight = 0;
5940
5941         textype = TEXTYPE_COLORBUFFER;
5942         switch (vid.renderpath)
5943         {
5944         case RENDERPATH_GL20:
5945         case RENDERPATH_GLES2:
5946                 if (vid.support.ext_framebuffer_object)
5947                 {
5948                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5949                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5950                 }
5951                 break;
5952         case RENDERPATH_GL11:
5953         case RENDERPATH_GL13:
5954         case RENDERPATH_GLES1:
5955         case RENDERPATH_D3D9:
5956         case RENDERPATH_D3D10:
5957         case RENDERPATH_D3D11:
5958         case RENDERPATH_SOFT:
5959                 break;
5960         }
5961
5962         // allocate textures as needed
5963         if (r_bloomstate.screentexturewidth != screentexturewidth
5964          || r_bloomstate.screentextureheight != screentextureheight
5965          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5966          || r_bloomstate.bloomtextureheight != bloomtextureheight
5967          || r_bloomstate.texturetype != textype
5968          || r_bloomstate.viewfbo != r_viewfbo.integer)
5969         {
5970                 if (r_bloomstate.texture_bloom)
5971                         R_FreeTexture(r_bloomstate.texture_bloom);
5972                 r_bloomstate.texture_bloom = NULL;
5973                 if (r_bloomstate.texture_screen)
5974                         R_FreeTexture(r_bloomstate.texture_screen);
5975                 r_bloomstate.texture_screen = NULL;
5976                 if (r_bloomstate.fbo_framebuffer)
5977                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5978                 r_bloomstate.fbo_framebuffer = 0;
5979                 if (r_bloomstate.texture_framebuffercolor)
5980                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5981                 r_bloomstate.texture_framebuffercolor = NULL;
5982                 if (r_bloomstate.texture_framebufferdepth)
5983                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5984                 r_bloomstate.texture_framebufferdepth = NULL;
5985                 r_bloomstate.screentexturewidth = screentexturewidth;
5986                 r_bloomstate.screentextureheight = screentextureheight;
5987                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5988                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5989                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5990                 {
5991                         // FIXME: choose depth bits based on a cvar
5992                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5993                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5994                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5995                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5996                         // render depth into one texture and normalmap into the other
5997                         if (qglDrawBuffer)
5998                         {
5999                                 int status;
6000                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6001                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6002                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
6003                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
6004                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6005                         }
6006                 }
6007                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6008                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6009                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6010                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6011                 r_bloomstate.viewfbo = r_viewfbo.integer;
6012                 r_bloomstate.texturetype = textype;
6013         }
6014
6015         // when doing a reduced render (HDR) we want to use a smaller area
6016         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6017         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6018         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6019         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6020         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6021
6022         // set up a texcoord array for the full resolution screen image
6023         // (we have to keep this around to copy back during final render)
6024         r_bloomstate.screentexcoord2f[0] = 0;
6025         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6026         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6027         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6028         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6029         r_bloomstate.screentexcoord2f[5] = 0;
6030         r_bloomstate.screentexcoord2f[6] = 0;
6031         r_bloomstate.screentexcoord2f[7] = 0;
6032
6033         // set up a texcoord array for the reduced resolution bloom image
6034         // (which will be additive blended over the screen image)
6035         r_bloomstate.bloomtexcoord2f[0] = 0;
6036         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6037         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6038         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6039         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6040         r_bloomstate.bloomtexcoord2f[5] = 0;
6041         r_bloomstate.bloomtexcoord2f[6] = 0;
6042         r_bloomstate.bloomtexcoord2f[7] = 0;
6043
6044         switch(vid.renderpath)
6045         {
6046         case RENDERPATH_GL11:
6047         case RENDERPATH_GL13:
6048         case RENDERPATH_GL20:
6049         case RENDERPATH_SOFT:
6050         case RENDERPATH_GLES1:
6051         case RENDERPATH_GLES2:
6052                 break;
6053         case RENDERPATH_D3D9:
6054         case RENDERPATH_D3D10:
6055         case RENDERPATH_D3D11:
6056                 {
6057                         int i;
6058                         for (i = 0;i < 4;i++)
6059                         {
6060                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6061                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6062                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6063                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6064                         }
6065                 }
6066                 break;
6067         }
6068
6069         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6070         {
6071                 r_bloomstate.enabled = true;
6072                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6073         }
6074
6075         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);
6076
6077         if (r_bloomstate.fbo_framebuffer)
6078                 r_refdef.view.clear = true;
6079 }
6080
6081 void R_Bloom_CopyBloomTexture(float colorscale)
6082 {
6083         r_refdef.stats.bloom++;
6084
6085         // scale down screen texture to the bloom texture size
6086         CHECKGLERROR
6087         R_Mesh_SetMainRenderTargets();
6088         R_SetViewport(&r_bloomstate.viewport);
6089         GL_BlendFunc(GL_ONE, GL_ZERO);
6090         GL_Color(colorscale, colorscale, colorscale, 1);
6091         // 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...
6092         switch(vid.renderpath)
6093         {
6094         case RENDERPATH_GL11:
6095         case RENDERPATH_GL13:
6096         case RENDERPATH_GL20:
6097         case RENDERPATH_GLES1:
6098         case RENDERPATH_GLES2:
6099         case RENDERPATH_SOFT:
6100                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6101                 break;
6102         case RENDERPATH_D3D9:
6103         case RENDERPATH_D3D10:
6104         case RENDERPATH_D3D11:
6105                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6106                 break;
6107         }
6108         // TODO: do boxfilter scale-down in shader?
6109         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6110         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6111         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6112
6113         // we now have a bloom image in the framebuffer
6114         // copy it into the bloom image texture for later processing
6115         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);
6116         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6117 }
6118
6119 void R_Bloom_CopyHDRTexture(void)
6120 {
6121         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);
6122         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6123 }
6124
6125 void R_Bloom_MakeTexture(void)
6126 {
6127         int x, range, dir;
6128         float xoffset, yoffset, r, brighten;
6129
6130         r_refdef.stats.bloom++;
6131
6132         R_ResetViewRendering2D();
6133
6134         // we have a bloom image in the framebuffer
6135         CHECKGLERROR
6136         R_SetViewport(&r_bloomstate.viewport);
6137
6138         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6139         {
6140                 x *= 2;
6141                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6142                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6143                 GL_Color(r,r,r,1);
6144                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6145                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6146                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6147                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6148
6149                 // copy the vertically blurred bloom view to a texture
6150                 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);
6151                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6152         }
6153
6154         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6155         brighten = r_bloom_brighten.value;
6156         if (r_bloomstate.hdr)
6157                 brighten *= r_hdr_range.value;
6158         brighten = sqrt(brighten);
6159         if(range >= 1)
6160                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6161         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6162
6163         for (dir = 0;dir < 2;dir++)
6164         {
6165                 // blend on at multiple vertical offsets to achieve a vertical blur
6166                 // TODO: do offset blends using GLSL
6167                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6168                 GL_BlendFunc(GL_ONE, GL_ZERO);
6169                 for (x = -range;x <= range;x++)
6170                 {
6171                         if (!dir){xoffset = 0;yoffset = x;}
6172                         else {xoffset = x;yoffset = 0;}
6173                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6174                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6175                         // compute a texcoord array with the specified x and y offset
6176                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6177                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6178                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6179                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6180                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6181                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6182                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6183                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6184                         // this r value looks like a 'dot' particle, fading sharply to
6185                         // black at the edges
6186                         // (probably not realistic but looks good enough)
6187                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6188                         //r = brighten/(range*2+1);
6189                         r = brighten / (range * 2 + 1);
6190                         if(range >= 1)
6191                                 r *= (1 - x*x/(float)(range*range));
6192                         GL_Color(r, r, r, 1);
6193                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6194                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6195                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6196                         GL_BlendFunc(GL_ONE, GL_ONE);
6197                 }
6198
6199                 // copy the vertically blurred bloom view to a texture
6200                 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);
6201                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6202         }
6203 }
6204
6205 void R_HDR_RenderBloomTexture(void)
6206 {
6207         int oldwidth, oldheight;
6208         float oldcolorscale;
6209         qboolean oldwaterstate;
6210
6211         oldwaterstate = r_waterstate.enabled;
6212         oldcolorscale = r_refdef.view.colorscale;
6213         oldwidth = r_refdef.view.width;
6214         oldheight = r_refdef.view.height;
6215         r_refdef.view.width = r_bloomstate.bloomwidth;
6216         r_refdef.view.height = r_bloomstate.bloomheight;
6217
6218         if(r_hdr.integer < 2)
6219                 r_waterstate.enabled = false;
6220
6221         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6222         // TODO: add exposure compensation features
6223         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6224
6225         r_refdef.view.showdebug = false;
6226         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6227
6228         R_ResetViewRendering3D();
6229
6230         R_ClearScreen(r_refdef.fogenabled);
6231         if (r_timereport_active)
6232                 R_TimeReport("HDRclear");
6233
6234         R_View_Update();
6235         if (r_timereport_active)
6236                 R_TimeReport("visibility");
6237
6238         // only do secondary renders with HDR if r_hdr is 2 or higher
6239         r_waterstate.numwaterplanes = 0;
6240         if (r_waterstate.enabled)
6241                 R_RenderWaterPlanes();
6242
6243         r_refdef.view.showdebug = true;
6244         R_RenderScene();
6245         r_waterstate.numwaterplanes = 0;
6246
6247         R_ResetViewRendering2D();
6248
6249         R_Bloom_CopyHDRTexture();
6250         R_Bloom_MakeTexture();
6251
6252         // restore the view settings
6253         r_waterstate.enabled = oldwaterstate;
6254         r_refdef.view.width = oldwidth;
6255         r_refdef.view.height = oldheight;
6256         r_refdef.view.colorscale = oldcolorscale;
6257
6258         R_ResetViewRendering3D();
6259
6260         R_ClearScreen(r_refdef.fogenabled);
6261         if (r_timereport_active)
6262                 R_TimeReport("viewclear");
6263 }
6264
6265 static void R_BlendView(void)
6266 {
6267         unsigned int permutation;
6268         float uservecs[4][4];
6269
6270         switch (vid.renderpath)
6271         {
6272         case RENDERPATH_GL20:
6273         case RENDERPATH_D3D9:
6274         case RENDERPATH_D3D10:
6275         case RENDERPATH_D3D11:
6276         case RENDERPATH_SOFT:
6277         case RENDERPATH_GLES2:
6278                 permutation =
6279                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6280                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6281                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6282                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6283                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6284
6285                 if (r_bloomstate.texture_screen)
6286                 {
6287                         // make sure the buffer is available
6288                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6289
6290                         R_ResetViewRendering2D();
6291                         R_Mesh_SetMainRenderTargets();
6292
6293                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6294                         {
6295                                 // declare variables
6296                                 float speed;
6297                                 static float avgspeed;
6298
6299                                 speed = VectorLength(cl.movement_velocity);
6300
6301                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6302                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6303
6304                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6305                                 speed = bound(0, speed, 1);
6306                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6307
6308                                 // calculate values into a standard alpha
6309                                 cl.motionbluralpha = 1 - exp(-
6310                                                 (
6311                                                  (r_motionblur.value * speed / 80)
6312                                                  +
6313                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6314                                                 )
6315                                                 /
6316                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6317                                            );
6318
6319                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6320                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6321                                 // apply the blur
6322                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6323                                 {
6324                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6325                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6326                                         switch(vid.renderpath)
6327                                         {
6328                                         case RENDERPATH_GL11:
6329                                         case RENDERPATH_GL13:
6330                                         case RENDERPATH_GL20:
6331                                         case RENDERPATH_GLES1:
6332                                         case RENDERPATH_GLES2:
6333                                         case RENDERPATH_SOFT:
6334                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6335                                                 break;
6336                                         case RENDERPATH_D3D9:
6337                                         case RENDERPATH_D3D10:
6338                                         case RENDERPATH_D3D11:
6339                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6340                                                 break;
6341                                         }
6342                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6343                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6344                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6345                                 }
6346                         }
6347
6348                         // copy view into the screen texture
6349                         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);
6350                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6351                 }
6352                 else if (!r_bloomstate.texture_bloom)
6353                 {
6354                         // we may still have to do view tint...
6355                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6356                         {
6357                                 // apply a color tint to the whole view
6358                                 R_ResetViewRendering2D();
6359                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6360                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6361                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6362                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6363                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6364                         }
6365                         break; // no screen processing, no bloom, skip it
6366                 }
6367
6368                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6369                 {
6370                         // render simple bloom effect
6371                         // copy the screen and shrink it and darken it for the bloom process
6372                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6373                         // make the bloom texture
6374                         R_Bloom_MakeTexture();
6375                 }
6376
6377 #if _MSC_VER >= 1400
6378 #define sscanf sscanf_s
6379 #endif
6380                 memset(uservecs, 0, sizeof(uservecs));
6381                 if (r_glsl_postprocess_uservec1_enable.integer)
6382                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6383                 if (r_glsl_postprocess_uservec2_enable.integer)
6384                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6385                 if (r_glsl_postprocess_uservec3_enable.integer)
6386                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6387                 if (r_glsl_postprocess_uservec4_enable.integer)
6388                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6389
6390                 R_ResetViewRendering2D();
6391                 GL_Color(1, 1, 1, 1);
6392                 GL_BlendFunc(GL_ONE, GL_ZERO);
6393
6394                 switch(vid.renderpath)
6395                 {
6396                 case RENDERPATH_GL20:
6397                 case RENDERPATH_GLES2:
6398                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6399                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6400                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6401                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6402                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6403                         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]);
6404                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6405                         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]);
6406                         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]);
6407                         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]);
6408                         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]);
6409                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6410                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6411                         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);
6412                         break;
6413                 case RENDERPATH_D3D9:
6414 #ifdef SUPPORTD3D
6415                         // 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...
6416                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6417                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6418                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6419                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6420                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6421                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6422                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6423                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6424                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6425                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6426                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6427                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6428                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6429                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6430 #endif
6431                         break;
6432                 case RENDERPATH_D3D10:
6433                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6434                         break;
6435                 case RENDERPATH_D3D11:
6436                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6437                         break;
6438                 case RENDERPATH_SOFT:
6439                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6440                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6441                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6442                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6443                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6444                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6445                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6446                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6447                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6448                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6449                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6450                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6451                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6452                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6453                         break;
6454                 default:
6455                         break;
6456                 }
6457                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6458                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6459                 break;
6460         case RENDERPATH_GL11:
6461         case RENDERPATH_GL13:
6462         case RENDERPATH_GLES1:
6463                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6464                 {
6465                         // apply a color tint to the whole view
6466                         R_ResetViewRendering2D();
6467                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6468                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6469                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6470                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6471                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6472                 }
6473                 break;
6474         }
6475 }
6476
6477 matrix4x4_t r_waterscrollmatrix;
6478
6479 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6480 {
6481         if (r_refdef.fog_density)
6482         {
6483                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6484                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6485                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6486
6487                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6488                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6489                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6490                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6491
6492                 {
6493                         vec3_t fogvec;
6494                         VectorCopy(r_refdef.fogcolor, fogvec);
6495                         //   color.rgb *= ContrastBoost * SceneBrightness;
6496                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6497                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6498                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6499                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6500                 }
6501         }
6502 }
6503
6504 void R_UpdateVariables(void)
6505 {
6506         R_Textures_Frame();
6507
6508         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6509
6510         r_refdef.farclip = r_farclip_base.value;
6511         if (r_refdef.scene.worldmodel)
6512                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6513         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6514
6515         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6516                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6517         r_refdef.polygonfactor = 0;
6518         r_refdef.polygonoffset = 0;
6519         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6520         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6521
6522         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6523         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6524         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6525         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6526         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6527         if (FAKELIGHT_ENABLED)
6528         {
6529                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6530         }
6531         if (r_showsurfaces.integer)
6532         {
6533                 r_refdef.scene.rtworld = false;
6534                 r_refdef.scene.rtworldshadows = false;
6535                 r_refdef.scene.rtdlight = false;
6536                 r_refdef.scene.rtdlightshadows = false;
6537                 r_refdef.lightmapintensity = 0;
6538         }
6539
6540         if (gamemode == GAME_NEHAHRA)
6541         {
6542                 if (gl_fogenable.integer)
6543                 {
6544                         r_refdef.oldgl_fogenable = true;
6545                         r_refdef.fog_density = gl_fogdensity.value;
6546                         r_refdef.fog_red = gl_fogred.value;
6547                         r_refdef.fog_green = gl_foggreen.value;
6548                         r_refdef.fog_blue = gl_fogblue.value;
6549                         r_refdef.fog_alpha = 1;
6550                         r_refdef.fog_start = 0;
6551                         r_refdef.fog_end = gl_skyclip.value;
6552                         r_refdef.fog_height = 1<<30;
6553                         r_refdef.fog_fadedepth = 128;
6554                 }
6555                 else if (r_refdef.oldgl_fogenable)
6556                 {
6557                         r_refdef.oldgl_fogenable = false;
6558                         r_refdef.fog_density = 0;
6559                         r_refdef.fog_red = 0;
6560                         r_refdef.fog_green = 0;
6561                         r_refdef.fog_blue = 0;
6562                         r_refdef.fog_alpha = 0;
6563                         r_refdef.fog_start = 0;
6564                         r_refdef.fog_end = 0;
6565                         r_refdef.fog_height = 1<<30;
6566                         r_refdef.fog_fadedepth = 128;
6567                 }
6568         }
6569
6570         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6571         r_refdef.fog_start = max(0, r_refdef.fog_start);
6572         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6573
6574         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6575
6576         if (r_refdef.fog_density && r_drawfog.integer)
6577         {
6578                 r_refdef.fogenabled = true;
6579                 // this is the point where the fog reaches 0.9986 alpha, which we
6580                 // consider a good enough cutoff point for the texture
6581                 // (0.9986 * 256 == 255.6)
6582                 if (r_fog_exp2.integer)
6583                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6584                 else
6585                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6586                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6587                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6588                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6589                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6590                         R_BuildFogHeightTexture();
6591                 // fog color was already set
6592                 // update the fog texture
6593                 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)
6594                         R_BuildFogTexture();
6595                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6596                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6597         }
6598         else
6599                 r_refdef.fogenabled = false;
6600
6601         switch(vid.renderpath)
6602         {
6603         case RENDERPATH_GL20:
6604         case RENDERPATH_D3D9:
6605         case RENDERPATH_D3D10:
6606         case RENDERPATH_D3D11:
6607         case RENDERPATH_SOFT:
6608         case RENDERPATH_GLES2:
6609                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6610                 {
6611                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6612                         {
6613                                 // build GLSL gamma texture
6614 #define RAMPWIDTH 256
6615                                 unsigned short ramp[RAMPWIDTH * 3];
6616                                 unsigned char rampbgr[RAMPWIDTH][4];
6617                                 int i;
6618
6619                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6620
6621                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6622                                 for(i = 0; i < RAMPWIDTH; ++i)
6623                                 {
6624                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6625                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6626                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6627                                         rampbgr[i][3] = 0;
6628                                 }
6629                                 if (r_texture_gammaramps)
6630                                 {
6631                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6632                                 }
6633                                 else
6634                                 {
6635                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6636                                 }
6637                         }
6638                 }
6639                 else
6640                 {
6641                         // remove GLSL gamma texture
6642                 }
6643                 break;
6644         case RENDERPATH_GL11:
6645         case RENDERPATH_GL13:
6646         case RENDERPATH_GLES1:
6647                 break;
6648         }
6649 }
6650
6651 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6652 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6653 /*
6654 ================
6655 R_SelectScene
6656 ================
6657 */
6658 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6659         if( scenetype != r_currentscenetype ) {
6660                 // store the old scenetype
6661                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6662                 r_currentscenetype = scenetype;
6663                 // move in the new scene
6664                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6665         }
6666 }
6667
6668 /*
6669 ================
6670 R_GetScenePointer
6671 ================
6672 */
6673 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6674 {
6675         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6676         if( scenetype == r_currentscenetype ) {
6677                 return &r_refdef.scene;
6678         } else {
6679                 return &r_scenes_store[ scenetype ];
6680         }
6681 }
6682
6683 /*
6684 ================
6685 R_RenderView
6686 ================
6687 */
6688 int dpsoftrast_test;
6689 extern void R_Shadow_UpdateBounceGridTexture(void);
6690 extern cvar_t r_shadow_bouncegrid;
6691 void R_RenderView(void)
6692 {
6693         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6694
6695         dpsoftrast_test = r_test.integer;
6696
6697         if (r_timereport_active)
6698                 R_TimeReport("start");
6699         r_textureframe++; // used only by R_GetCurrentTexture
6700         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6701
6702         if(R_CompileShader_CheckStaticParms())
6703                 R_GLSL_Restart_f();
6704
6705         if (!r_drawentities.integer)
6706                 r_refdef.scene.numentities = 0;
6707
6708         R_AnimCache_ClearCache();
6709         R_FrameData_NewFrame();
6710
6711         /* adjust for stereo display */
6712         if(R_Stereo_Active())
6713         {
6714                 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);
6715                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6716         }
6717
6718         if (r_refdef.view.isoverlay)
6719         {
6720                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6721                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6722                 R_TimeReport("depthclear");
6723
6724                 r_refdef.view.showdebug = false;
6725
6726                 r_waterstate.enabled = false;
6727                 r_waterstate.numwaterplanes = 0;
6728
6729                 R_RenderScene();
6730
6731                 r_refdef.view.matrix = originalmatrix;
6732
6733                 CHECKGLERROR
6734                 return;
6735         }
6736
6737         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6738         {
6739                 r_refdef.view.matrix = originalmatrix;
6740                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6741         }
6742
6743         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6744
6745         R_RenderView_UpdateViewVectors();
6746
6747         R_Shadow_UpdateWorldLightSelection();
6748
6749         R_Bloom_StartFrame();
6750         R_Water_StartFrame();
6751
6752         CHECKGLERROR
6753         if (r_timereport_active)
6754                 R_TimeReport("viewsetup");
6755
6756         R_ResetViewRendering3D();
6757
6758         if (r_refdef.view.clear || r_refdef.fogenabled)
6759         {
6760                 R_ClearScreen(r_refdef.fogenabled);
6761                 if (r_timereport_active)
6762                         R_TimeReport("viewclear");
6763         }
6764         r_refdef.view.clear = true;
6765
6766         R_Shadow_UpdateBounceGridTexture();
6767         if (r_timereport_active && r_shadow_bouncegrid.integer)
6768                 R_TimeReport("bouncegrid");
6769
6770         // this produces a bloom texture to be used in R_BlendView() later
6771         if (r_bloomstate.hdr)
6772         {
6773                 R_HDR_RenderBloomTexture();
6774                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6775                 r_textureframe++; // used only by R_GetCurrentTexture
6776         }
6777
6778         r_refdef.view.showdebug = true;
6779
6780         R_View_Update();
6781         if (r_timereport_active)
6782                 R_TimeReport("visibility");
6783
6784         r_waterstate.numwaterplanes = 0;
6785         if (r_waterstate.enabled)
6786                 R_RenderWaterPlanes();
6787
6788         R_RenderScene();
6789         r_waterstate.numwaterplanes = 0;
6790
6791         R_BlendView();
6792         if (r_timereport_active)
6793                 R_TimeReport("blendview");
6794
6795         GL_Scissor(0, 0, vid.width, vid.height);
6796         GL_ScissorTest(false);
6797
6798         r_refdef.view.matrix = originalmatrix;
6799
6800         CHECKGLERROR
6801 }
6802
6803 void R_RenderWaterPlanes(void)
6804 {
6805         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6806         {
6807                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6808                 if (r_timereport_active)
6809                         R_TimeReport("waterworld");
6810         }
6811
6812         // don't let sound skip if going slow
6813         if (r_refdef.scene.extraupdate)
6814                 S_ExtraUpdate ();
6815
6816         R_DrawModelsAddWaterPlanes();
6817         if (r_timereport_active)
6818                 R_TimeReport("watermodels");
6819
6820         if (r_waterstate.numwaterplanes)
6821         {
6822                 R_Water_ProcessPlanes();
6823                 if (r_timereport_active)
6824                         R_TimeReport("waterscenes");
6825         }
6826 }
6827
6828 extern void R_DrawLightningBeams (void);
6829 extern void VM_CL_AddPolygonsToMeshQueue (void);
6830 extern void R_DrawPortals (void);
6831 extern cvar_t cl_locs_show;
6832 static void R_DrawLocs(void);
6833 static void R_DrawEntityBBoxes(void);
6834 static void R_DrawModelDecals(void);
6835 extern void R_DrawModelShadows(void);
6836 extern void R_DrawModelShadowMaps(void);
6837 extern cvar_t cl_decals_newsystem;
6838 extern qboolean r_shadow_usingdeferredprepass;
6839 void R_RenderScene(void)
6840 {
6841         qboolean shadowmapping = false;
6842
6843         if (r_timereport_active)
6844                 R_TimeReport("beginscene");
6845
6846         r_refdef.stats.renders++;
6847
6848         R_UpdateFogColor();
6849
6850         // don't let sound skip if going slow
6851         if (r_refdef.scene.extraupdate)
6852                 S_ExtraUpdate ();
6853
6854         R_MeshQueue_BeginScene();
6855
6856         R_SkyStartFrame();
6857
6858         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);
6859
6860         if (r_timereport_active)
6861                 R_TimeReport("skystartframe");
6862
6863         if (cl.csqc_vidvars.drawworld)
6864         {
6865                 // don't let sound skip if going slow
6866                 if (r_refdef.scene.extraupdate)
6867                         S_ExtraUpdate ();
6868
6869                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6870                 {
6871                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6872                         if (r_timereport_active)
6873                                 R_TimeReport("worldsky");
6874                 }
6875
6876                 if (R_DrawBrushModelsSky() && r_timereport_active)
6877                         R_TimeReport("bmodelsky");
6878
6879                 if (skyrendermasked && skyrenderlater)
6880                 {
6881                         // we have to force off the water clipping plane while rendering sky
6882                         R_SetupView(false);
6883                         R_Sky();
6884                         R_SetupView(true);
6885                         if (r_timereport_active)
6886                                 R_TimeReport("sky");
6887                 }
6888         }
6889
6890         R_AnimCache_CacheVisibleEntities();
6891         if (r_timereport_active)
6892                 R_TimeReport("animation");
6893
6894         R_Shadow_PrepareLights();
6895         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6896                 R_Shadow_PrepareModelShadows();
6897         if (r_timereport_active)
6898                 R_TimeReport("preparelights");
6899
6900         if (R_Shadow_ShadowMappingEnabled())
6901                 shadowmapping = true;
6902
6903         if (r_shadow_usingdeferredprepass)
6904                 R_Shadow_DrawPrepass();
6905
6906         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6907         {
6908                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6909                 if (r_timereport_active)
6910                         R_TimeReport("worlddepth");
6911         }
6912         if (r_depthfirst.integer >= 2)
6913         {
6914                 R_DrawModelsDepth();
6915                 if (r_timereport_active)
6916                         R_TimeReport("modeldepth");
6917         }
6918
6919         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6920         {
6921                 R_DrawModelShadowMaps();
6922                 R_ResetViewRendering3D();
6923                 // don't let sound skip if going slow
6924                 if (r_refdef.scene.extraupdate)
6925                         S_ExtraUpdate ();
6926         }
6927
6928         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6929         {
6930                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6931                 if (r_timereport_active)
6932                         R_TimeReport("world");
6933         }
6934
6935         // don't let sound skip if going slow
6936         if (r_refdef.scene.extraupdate)
6937                 S_ExtraUpdate ();
6938
6939         R_DrawModels();
6940         if (r_timereport_active)
6941                 R_TimeReport("models");
6942
6943         // don't let sound skip if going slow
6944         if (r_refdef.scene.extraupdate)
6945                 S_ExtraUpdate ();
6946
6947         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6948         {
6949                 R_DrawModelShadows();
6950                 R_ResetViewRendering3D();
6951                 // don't let sound skip if going slow
6952                 if (r_refdef.scene.extraupdate)
6953                         S_ExtraUpdate ();
6954         }
6955
6956         if (!r_shadow_usingdeferredprepass)
6957         {
6958                 R_Shadow_DrawLights();
6959                 if (r_timereport_active)
6960                         R_TimeReport("rtlights");
6961         }
6962
6963         // don't let sound skip if going slow
6964         if (r_refdef.scene.extraupdate)
6965                 S_ExtraUpdate ();
6966
6967         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6968         {
6969                 R_DrawModelShadows();
6970                 R_ResetViewRendering3D();
6971                 // don't let sound skip if going slow
6972                 if (r_refdef.scene.extraupdate)
6973                         S_ExtraUpdate ();
6974         }
6975
6976         if (cl.csqc_vidvars.drawworld)
6977         {
6978                 if (cl_decals_newsystem.integer)
6979                 {
6980                         R_DrawModelDecals();
6981                         if (r_timereport_active)
6982                                 R_TimeReport("modeldecals");
6983                 }
6984                 else
6985                 {
6986                         R_DrawDecals();
6987                         if (r_timereport_active)
6988                                 R_TimeReport("decals");
6989                 }
6990
6991                 R_DrawParticles();
6992                 if (r_timereport_active)
6993                         R_TimeReport("particles");
6994
6995                 R_DrawExplosions();
6996                 if (r_timereport_active)
6997                         R_TimeReport("explosions");
6998
6999                 R_DrawLightningBeams();
7000                 if (r_timereport_active)
7001                         R_TimeReport("lightning");
7002         }
7003
7004         VM_CL_AddPolygonsToMeshQueue();
7005
7006         if (r_refdef.view.showdebug)
7007         {
7008                 if (cl_locs_show.integer)
7009                 {
7010                         R_DrawLocs();
7011                         if (r_timereport_active)
7012                                 R_TimeReport("showlocs");
7013                 }
7014
7015                 if (r_drawportals.integer)
7016                 {
7017                         R_DrawPortals();
7018                         if (r_timereport_active)
7019                                 R_TimeReport("portals");
7020                 }
7021
7022                 if (r_showbboxes.value > 0)
7023                 {
7024                         R_DrawEntityBBoxes();
7025                         if (r_timereport_active)
7026                                 R_TimeReport("bboxes");
7027                 }
7028         }
7029
7030         if (r_transparent.integer)
7031         {
7032                 R_MeshQueue_RenderTransparent();
7033                 if (r_timereport_active)
7034                         R_TimeReport("drawtrans");
7035         }
7036
7037         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 || r_showoverdraw.value > 0))
7038         {
7039                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7040                 if (r_timereport_active)
7041                         R_TimeReport("worlddebug");
7042                 R_DrawModelsDebug();
7043                 if (r_timereport_active)
7044                         R_TimeReport("modeldebug");
7045         }
7046
7047         if (cl.csqc_vidvars.drawworld)
7048         {
7049                 R_Shadow_DrawCoronas();
7050                 if (r_timereport_active)
7051                         R_TimeReport("coronas");
7052         }
7053
7054 #if 0
7055         {
7056                 GL_DepthTest(false);
7057                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7058                 GL_Color(1, 1, 1, 1);
7059                 qglBegin(GL_POLYGON);
7060                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7061                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7062                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7063                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7064                 qglEnd();
7065                 qglBegin(GL_POLYGON);
7066                 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]);
7067                 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]);
7068                 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]);
7069                 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]);
7070                 qglEnd();
7071                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7072         }
7073 #endif
7074
7075         // don't let sound skip if going slow
7076         if (r_refdef.scene.extraupdate)
7077                 S_ExtraUpdate ();
7078
7079         R_ResetViewRendering2D();
7080 }
7081
7082 static const unsigned short bboxelements[36] =
7083 {
7084         5, 1, 3, 5, 3, 7,
7085         6, 2, 0, 6, 0, 4,
7086         7, 3, 2, 7, 2, 6,
7087         4, 0, 1, 4, 1, 5,
7088         4, 5, 7, 4, 7, 6,
7089         1, 0, 2, 1, 2, 3,
7090 };
7091
7092 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7093 {
7094         int i;
7095         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7096
7097         RSurf_ActiveWorldEntity();
7098
7099         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7100         GL_DepthMask(false);
7101         GL_DepthRange(0, 1);
7102         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7103 //      R_Mesh_ResetTextureState();
7104
7105         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7106         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7107         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7108         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7109         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7110         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7111         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7112         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7113         R_FillColors(color4f, 8, cr, cg, cb, ca);
7114         if (r_refdef.fogenabled)
7115         {
7116                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7117                 {
7118                         f1 = RSurf_FogVertex(v);
7119                         f2 = 1 - f1;
7120                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7121                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7122                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7123                 }
7124         }
7125         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7126         R_Mesh_ResetTextureState();
7127         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7128         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7129 }
7130
7131 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7132 {
7133         int i;
7134         float color[4];
7135         prvm_edict_t *edict;
7136         prvm_prog_t *prog_save = prog;
7137
7138         // this function draws bounding boxes of server entities
7139         if (!sv.active)
7140                 return;
7141
7142         GL_CullFace(GL_NONE);
7143         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7144
7145         prog = 0;
7146         SV_VM_Begin();
7147         for (i = 0;i < numsurfaces;i++)
7148         {
7149                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7150                 switch ((int)PRVM_serveredictfloat(edict, solid))
7151                 {
7152                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7153                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7154                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7155                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7156                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7157                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7158                 }
7159                 color[3] *= r_showbboxes.value;
7160                 color[3] = bound(0, color[3], 1);
7161                 GL_DepthTest(!r_showdisabledepthtest.integer);
7162                 GL_CullFace(r_refdef.view.cullface_front);
7163                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7164         }
7165         SV_VM_End();
7166         prog = prog_save;
7167 }
7168
7169 static void R_DrawEntityBBoxes(void)
7170 {
7171         int i;
7172         prvm_edict_t *edict;
7173         vec3_t center;
7174         prvm_prog_t *prog_save = prog;
7175
7176         // this function draws bounding boxes of server entities
7177         if (!sv.active)
7178                 return;
7179
7180         prog = 0;
7181         SV_VM_Begin();
7182         for (i = 0;i < prog->num_edicts;i++)
7183         {
7184                 edict = PRVM_EDICT_NUM(i);
7185                 if (edict->priv.server->free)
7186                         continue;
7187                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7188                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7189                         continue;
7190                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7191                         continue;
7192                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7193                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7194         }
7195         SV_VM_End();
7196         prog = prog_save;
7197 }
7198
7199 static const int nomodelelement3i[24] =
7200 {
7201         5, 2, 0,
7202         5, 1, 2,
7203         5, 0, 3,
7204         5, 3, 1,
7205         0, 2, 4,
7206         2, 1, 4,
7207         3, 0, 4,
7208         1, 3, 4
7209 };
7210
7211 static const unsigned short nomodelelement3s[24] =
7212 {
7213         5, 2, 0,
7214         5, 1, 2,
7215         5, 0, 3,
7216         5, 3, 1,
7217         0, 2, 4,
7218         2, 1, 4,
7219         3, 0, 4,
7220         1, 3, 4
7221 };
7222
7223 static const float nomodelvertex3f[6*3] =
7224 {
7225         -16,   0,   0,
7226          16,   0,   0,
7227           0, -16,   0,
7228           0,  16,   0,
7229           0,   0, -16,
7230           0,   0,  16
7231 };
7232
7233 static const float nomodelcolor4f[6*4] =
7234 {
7235         0.0f, 0.0f, 0.5f, 1.0f,
7236         0.0f, 0.0f, 0.5f, 1.0f,
7237         0.0f, 0.5f, 0.0f, 1.0f,
7238         0.0f, 0.5f, 0.0f, 1.0f,
7239         0.5f, 0.0f, 0.0f, 1.0f,
7240         0.5f, 0.0f, 0.0f, 1.0f
7241 };
7242
7243 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7244 {
7245         int i;
7246         float f1, f2, *c;
7247         float color4f[6*4];
7248
7249         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);
7250
7251         // this is only called once per entity so numsurfaces is always 1, and
7252         // surfacelist is always {0}, so this code does not handle batches
7253
7254         if (rsurface.ent_flags & RENDER_ADDITIVE)
7255         {
7256                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7257                 GL_DepthMask(false);
7258         }
7259         else if (rsurface.colormod[3] < 1)
7260         {
7261                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7262                 GL_DepthMask(false);
7263         }
7264         else
7265         {
7266                 GL_BlendFunc(GL_ONE, GL_ZERO);
7267                 GL_DepthMask(true);
7268         }
7269         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7270         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7271         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7272         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7273         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7274         for (i = 0, c = color4f;i < 6;i++, c += 4)
7275         {
7276                 c[0] *= rsurface.colormod[0];
7277                 c[1] *= rsurface.colormod[1];
7278                 c[2] *= rsurface.colormod[2];
7279                 c[3] *= rsurface.colormod[3];
7280         }
7281         if (r_refdef.fogenabled)
7282         {
7283                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7284                 {
7285                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7286                         f2 = 1 - f1;
7287                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7288                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7289                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7290                 }
7291         }
7292 //      R_Mesh_ResetTextureState();
7293         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7294         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7295         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7296 }
7297
7298 void R_DrawNoModel(entity_render_t *ent)
7299 {
7300         vec3_t org;
7301         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7302         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7303                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7304         else
7305                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7306 }
7307
7308 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7309 {
7310         vec3_t right1, right2, diff, normal;
7311
7312         VectorSubtract (org2, org1, normal);
7313
7314         // calculate 'right' vector for start
7315         VectorSubtract (r_refdef.view.origin, org1, diff);
7316         CrossProduct (normal, diff, right1);
7317         VectorNormalize (right1);
7318
7319         // calculate 'right' vector for end
7320         VectorSubtract (r_refdef.view.origin, org2, diff);
7321         CrossProduct (normal, diff, right2);
7322         VectorNormalize (right2);
7323
7324         vert[ 0] = org1[0] + width * right1[0];
7325         vert[ 1] = org1[1] + width * right1[1];
7326         vert[ 2] = org1[2] + width * right1[2];
7327         vert[ 3] = org1[0] - width * right1[0];
7328         vert[ 4] = org1[1] - width * right1[1];
7329         vert[ 5] = org1[2] - width * right1[2];
7330         vert[ 6] = org2[0] - width * right2[0];
7331         vert[ 7] = org2[1] - width * right2[1];
7332         vert[ 8] = org2[2] - width * right2[2];
7333         vert[ 9] = org2[0] + width * right2[0];
7334         vert[10] = org2[1] + width * right2[1];
7335         vert[11] = org2[2] + width * right2[2];
7336 }
7337
7338 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)
7339 {
7340         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7341         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7342         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7343         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7344         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7345         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7346         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7347         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7348         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7349         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7350         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7351         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7352 }
7353
7354 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7355 {
7356         int i;
7357         float *vertex3f;
7358         float v[3];
7359         VectorSet(v, x, y, z);
7360         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7361                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7362                         break;
7363         if (i == mesh->numvertices)
7364         {
7365                 if (mesh->numvertices < mesh->maxvertices)
7366                 {
7367                         VectorCopy(v, vertex3f);
7368                         mesh->numvertices++;
7369                 }
7370                 return mesh->numvertices;
7371         }
7372         else
7373                 return i;
7374 }
7375
7376 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7377 {
7378         int i;
7379         int *e, element[3];
7380         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7381         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7382         e = mesh->element3i + mesh->numtriangles * 3;
7383         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7384         {
7385                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7386                 if (mesh->numtriangles < mesh->maxtriangles)
7387                 {
7388                         *e++ = element[0];
7389                         *e++ = element[1];
7390                         *e++ = element[2];
7391                         mesh->numtriangles++;
7392                 }
7393                 element[1] = element[2];
7394         }
7395 }
7396
7397 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7398 {
7399         int i;
7400         int *e, element[3];
7401         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7402         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7403         e = mesh->element3i + mesh->numtriangles * 3;
7404         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7405         {
7406                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7407                 if (mesh->numtriangles < mesh->maxtriangles)
7408                 {
7409                         *e++ = element[0];
7410                         *e++ = element[1];
7411                         *e++ = element[2];
7412                         mesh->numtriangles++;
7413                 }
7414                 element[1] = element[2];
7415         }
7416 }
7417
7418 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7419 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7420 {
7421         int planenum, planenum2;
7422         int w;
7423         int tempnumpoints;
7424         mplane_t *plane, *plane2;
7425         double maxdist;
7426         double temppoints[2][256*3];
7427         // figure out how large a bounding box we need to properly compute this brush
7428         maxdist = 0;
7429         for (w = 0;w < numplanes;w++)
7430                 maxdist = max(maxdist, fabs(planes[w].dist));
7431         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7432         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7433         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7434         {
7435                 w = 0;
7436                 tempnumpoints = 4;
7437                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7438                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7439                 {
7440                         if (planenum2 == planenum)
7441                                 continue;
7442                         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);
7443                         w = !w;
7444                 }
7445                 if (tempnumpoints < 3)
7446                         continue;
7447                 // generate elements forming a triangle fan for this polygon
7448                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7449         }
7450 }
7451
7452 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)
7453 {
7454         texturelayer_t *layer;
7455         layer = t->currentlayers + t->currentnumlayers++;
7456         layer->type = type;
7457         layer->depthmask = depthmask;
7458         layer->blendfunc1 = blendfunc1;
7459         layer->blendfunc2 = blendfunc2;
7460         layer->texture = texture;
7461         layer->texmatrix = *matrix;
7462         layer->color[0] = r;
7463         layer->color[1] = g;
7464         layer->color[2] = b;
7465         layer->color[3] = a;
7466 }
7467
7468 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7469 {
7470         if(parms[0] == 0 && parms[1] == 0)
7471                 return false;
7472         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7473                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7474                         return false;
7475         return true;
7476 }
7477
7478 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7479 {
7480         double index, f;
7481         index = parms[2] + rsurface.shadertime * parms[3];
7482         index -= floor(index);
7483         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7484         {
7485         default:
7486         case Q3WAVEFUNC_NONE:
7487         case Q3WAVEFUNC_NOISE:
7488         case Q3WAVEFUNC_COUNT:
7489                 f = 0;
7490                 break;
7491         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7492         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7493         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7494         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7495         case Q3WAVEFUNC_TRIANGLE:
7496                 index *= 4;
7497                 f = index - floor(index);
7498                 if (index < 1)
7499                 {
7500                         // f = f;
7501                 }
7502                 else if (index < 2)
7503                         f = 1 - f;
7504                 else if (index < 3)
7505                         f = -f;
7506                 else
7507                         f = -(1 - f);
7508                 break;
7509         }
7510         f = parms[0] + parms[1] * f;
7511         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7512                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7513         return (float) f;
7514 }
7515
7516 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7517 {
7518         int w, h, idx;
7519         double f;
7520         double offsetd[2];
7521         float tcmat[12];
7522         matrix4x4_t matrix, temp;
7523         switch(tcmod->tcmod)
7524         {
7525                 case Q3TCMOD_COUNT:
7526                 case Q3TCMOD_NONE:
7527                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7528                                 matrix = r_waterscrollmatrix;
7529                         else
7530                                 matrix = identitymatrix;
7531                         break;
7532                 case Q3TCMOD_ENTITYTRANSLATE:
7533                         // this is used in Q3 to allow the gamecode to control texcoord
7534                         // scrolling on the entity, which is not supported in darkplaces yet.
7535                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7536                         break;
7537                 case Q3TCMOD_ROTATE:
7538                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7539                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7540                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7541                         break;
7542                 case Q3TCMOD_SCALE:
7543                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7544                         break;
7545                 case Q3TCMOD_SCROLL:
7546                         // extra care is needed because of precision breakdown with large values of time
7547                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7548                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7549                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7550                         break;
7551                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7552                         w = (int) tcmod->parms[0];
7553                         h = (int) tcmod->parms[1];
7554                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7555                         f = f - floor(f);
7556                         idx = (int) floor(f * w * h);
7557                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7558                         break;
7559                 case Q3TCMOD_STRETCH:
7560                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7561                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7562                         break;
7563                 case Q3TCMOD_TRANSFORM:
7564                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7565                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7566                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7567                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7568                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7569                         break;
7570                 case Q3TCMOD_TURBULENT:
7571                         // this is handled in the RSurf_PrepareVertices function
7572                         matrix = identitymatrix;
7573                         break;
7574         }
7575         temp = *texmatrix;
7576         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7577 }
7578
7579 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7580 {
7581         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7582         char name[MAX_QPATH];
7583         skinframe_t *skinframe;
7584         unsigned char pixels[296*194];
7585         strlcpy(cache->name, skinname, sizeof(cache->name));
7586         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7587         if (developer_loading.integer)
7588                 Con_Printf("loading %s\n", name);
7589         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7590         if (!skinframe || !skinframe->base)
7591         {
7592                 unsigned char *f;
7593                 fs_offset_t filesize;
7594                 skinframe = NULL;
7595                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7596                 if (f)
7597                 {
7598                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7599                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7600                         Mem_Free(f);
7601                 }
7602         }
7603         cache->skinframe = skinframe;
7604 }
7605
7606 texture_t *R_GetCurrentTexture(texture_t *t)
7607 {
7608         int i;
7609         const entity_render_t *ent = rsurface.entity;
7610         dp_model_t *model = ent->model;
7611         q3shaderinfo_layer_tcmod_t *tcmod;
7612
7613         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7614                 return t->currentframe;
7615         t->update_lastrenderframe = r_textureframe;
7616         t->update_lastrenderentity = (void *)ent;
7617
7618         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7619                 t->camera_entity = ent->entitynumber;
7620         else
7621                 t->camera_entity = 0;
7622
7623         // switch to an alternate material if this is a q1bsp animated material
7624         {
7625                 texture_t *texture = t;
7626                 int s = rsurface.ent_skinnum;
7627                 if ((unsigned int)s >= (unsigned int)model->numskins)
7628                         s = 0;
7629                 if (model->skinscenes)
7630                 {
7631                         if (model->skinscenes[s].framecount > 1)
7632                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7633                         else
7634                                 s = model->skinscenes[s].firstframe;
7635                 }
7636                 if (s > 0)
7637                         t = t + s * model->num_surfaces;
7638                 if (t->animated)
7639                 {
7640                         // use an alternate animation if the entity's frame is not 0,
7641                         // and only if the texture has an alternate animation
7642                         if (rsurface.ent_alttextures && t->anim_total[1])
7643                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7644                         else
7645                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7646                 }
7647                 texture->currentframe = t;
7648         }
7649
7650         // update currentskinframe to be a qw skin or animation frame
7651         if (rsurface.ent_qwskin >= 0)
7652         {
7653                 i = rsurface.ent_qwskin;
7654                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7655                 {
7656                         r_qwskincache_size = cl.maxclients;
7657                         if (r_qwskincache)
7658                                 Mem_Free(r_qwskincache);
7659                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7660                 }
7661                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7662                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7663                 t->currentskinframe = r_qwskincache[i].skinframe;
7664                 if (t->currentskinframe == NULL)
7665                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7666         }
7667         else if (t->numskinframes >= 2)
7668                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7669         if (t->backgroundnumskinframes >= 2)
7670                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7671
7672         t->currentmaterialflags = t->basematerialflags;
7673         t->currentalpha = rsurface.colormod[3];
7674         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7675                 t->currentalpha *= r_wateralpha.value;
7676         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7677                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7678         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7679                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7680         if (!(rsurface.ent_flags & RENDER_LIGHT))
7681                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7682         else if (FAKELIGHT_ENABLED)
7683         {
7684                 // no modellight if using fakelight for the map
7685         }
7686         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7687         {
7688                 // pick a model lighting mode
7689                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7690                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7691                 else
7692                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7693         }
7694         if (rsurface.ent_flags & RENDER_ADDITIVE)
7695                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7696         else if (t->currentalpha < 1)
7697                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7698         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7699                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7700         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7701                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7702         if (t->backgroundnumskinframes)
7703                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7704         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7705         {
7706                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7707                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7708         }
7709         else
7710                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7711         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7712         {
7713                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7714                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7715         }
7716         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7717                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7718
7719         // there is no tcmod
7720         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7721         {
7722                 t->currenttexmatrix = r_waterscrollmatrix;
7723                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7724         }
7725         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7726         {
7727                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7728                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7729         }
7730
7731         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7732                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7733         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7734                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7735
7736         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7737         if (t->currentskinframe->qpixels)
7738                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7739         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7740         if (!t->basetexture)
7741                 t->basetexture = r_texture_notexture;
7742         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7743         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7744         t->nmaptexture = t->currentskinframe->nmap;
7745         if (!t->nmaptexture)
7746                 t->nmaptexture = r_texture_blanknormalmap;
7747         t->glosstexture = r_texture_black;
7748         t->glowtexture = t->currentskinframe->glow;
7749         t->fogtexture = t->currentskinframe->fog;
7750         t->reflectmasktexture = t->currentskinframe->reflect;
7751         if (t->backgroundnumskinframes)
7752         {
7753                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7754                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7755                 t->backgroundglosstexture = r_texture_black;
7756                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7757                 if (!t->backgroundnmaptexture)
7758                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7759         }
7760         else
7761         {
7762                 t->backgroundbasetexture = r_texture_white;
7763                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7764                 t->backgroundglosstexture = r_texture_black;
7765                 t->backgroundglowtexture = NULL;
7766         }
7767         t->specularpower = r_shadow_glossexponent.value;
7768         // TODO: store reference values for these in the texture?
7769         t->specularscale = 0;
7770         if (r_shadow_gloss.integer > 0)
7771         {
7772                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7773                 {
7774                         if (r_shadow_glossintensity.value > 0)
7775                         {
7776                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7777                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7778                                 t->specularscale = r_shadow_glossintensity.value;
7779                         }
7780                 }
7781                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7782                 {
7783                         t->glosstexture = r_texture_white;
7784                         t->backgroundglosstexture = r_texture_white;
7785                         t->specularscale = r_shadow_gloss2intensity.value;
7786                         t->specularpower = r_shadow_gloss2exponent.value;
7787                 }
7788         }
7789         t->specularscale *= t->specularscalemod;
7790         t->specularpower *= t->specularpowermod;
7791
7792         // lightmaps mode looks bad with dlights using actual texturing, so turn
7793         // off the colormap and glossmap, but leave the normalmap on as it still
7794         // accurately represents the shading involved
7795         if (gl_lightmaps.integer)
7796         {
7797                 t->basetexture = r_texture_grey128;
7798                 t->pantstexture = r_texture_black;
7799                 t->shirttexture = r_texture_black;
7800                 t->nmaptexture = r_texture_blanknormalmap;
7801                 t->glosstexture = r_texture_black;
7802                 t->glowtexture = NULL;
7803                 t->fogtexture = NULL;
7804                 t->reflectmasktexture = NULL;
7805                 t->backgroundbasetexture = NULL;
7806                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7807                 t->backgroundglosstexture = r_texture_black;
7808                 t->backgroundglowtexture = NULL;
7809                 t->specularscale = 0;
7810                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7811         }
7812
7813         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7814         VectorClear(t->dlightcolor);
7815         t->currentnumlayers = 0;
7816         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7817         {
7818                 int blendfunc1, blendfunc2;
7819                 qboolean depthmask;
7820                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7821                 {
7822                         blendfunc1 = GL_SRC_ALPHA;
7823                         blendfunc2 = GL_ONE;
7824                 }
7825                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7826                 {
7827                         blendfunc1 = GL_SRC_ALPHA;
7828                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7829                 }
7830                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7831                 {
7832                         blendfunc1 = t->customblendfunc[0];
7833                         blendfunc2 = t->customblendfunc[1];
7834                 }
7835                 else
7836                 {
7837                         blendfunc1 = GL_ONE;
7838                         blendfunc2 = GL_ZERO;
7839                 }
7840                 // don't colormod evilblend textures
7841                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7842                         VectorSet(t->lightmapcolor, 1, 1, 1);
7843                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7844                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7845                 {
7846                         // fullbright is not affected by r_refdef.lightmapintensity
7847                         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]);
7848                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7849                                 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]);
7850                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7851                                 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]);
7852                 }
7853                 else
7854                 {
7855                         vec3_t ambientcolor;
7856                         float colorscale;
7857                         // set the color tint used for lights affecting this surface
7858                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7859                         colorscale = 2;
7860                         // q3bsp has no lightmap updates, so the lightstylevalue that
7861                         // would normally be baked into the lightmap must be
7862                         // applied to the color
7863                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7864                         if (model->type == mod_brushq3)
7865                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7866                         colorscale *= r_refdef.lightmapintensity;
7867                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7868                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7869                         // basic lit geometry
7870                         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]);
7871                         // add pants/shirt if needed
7872                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7873                                 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]);
7874                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7875                                 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]);
7876                         // now add ambient passes if needed
7877                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7878                         {
7879                                 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]);
7880                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7881                                         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]);
7882                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7883                                         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]);
7884                         }
7885                 }
7886                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7887                         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]);
7888                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7889                 {
7890                         // if this is opaque use alpha blend which will darken the earlier
7891                         // passes cheaply.
7892                         //
7893                         // if this is an alpha blended material, all the earlier passes
7894                         // were darkened by fog already, so we only need to add the fog
7895                         // color ontop through the fog mask texture
7896                         //
7897                         // if this is an additive blended material, all the earlier passes
7898                         // were darkened by fog already, and we should not add fog color
7899                         // (because the background was not darkened, there is no fog color
7900                         // that was lost behind it).
7901                         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]);
7902                 }
7903         }
7904
7905         return t->currentframe;
7906 }
7907
7908 rsurfacestate_t rsurface;
7909
7910 void RSurf_ActiveWorldEntity(void)
7911 {
7912         dp_model_t *model = r_refdef.scene.worldmodel;
7913         //if (rsurface.entity == r_refdef.scene.worldentity)
7914         //      return;
7915         rsurface.entity = r_refdef.scene.worldentity;
7916         rsurface.skeleton = NULL;
7917         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7918         rsurface.ent_skinnum = 0;
7919         rsurface.ent_qwskin = -1;
7920         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7921         rsurface.shadertime = r_refdef.scene.time;
7922         rsurface.matrix = identitymatrix;
7923         rsurface.inversematrix = identitymatrix;
7924         rsurface.matrixscale = 1;
7925         rsurface.inversematrixscale = 1;
7926         R_EntityMatrix(&identitymatrix);
7927         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7928         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7929         rsurface.fograngerecip = r_refdef.fograngerecip;
7930         rsurface.fogheightfade = r_refdef.fogheightfade;
7931         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7932         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7933         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7934         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7935         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7936         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7937         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7938         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7939         rsurface.colormod[3] = 1;
7940         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);
7941         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7942         rsurface.frameblend[0].lerp = 1;
7943         rsurface.ent_alttextures = false;
7944         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7945         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7946         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7947         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7948         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7949         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7950         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7951         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7952         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7953         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7954         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7955         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7956         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7957         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7958         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7959         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7960         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7961         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7962         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7963         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7964         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7965         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7966         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7967         rsurface.modelelement3i = model->surfmesh.data_element3i;
7968         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7969         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7970         rsurface.modelelement3s = model->surfmesh.data_element3s;
7971         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7972         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7973         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7974         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7975         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7976         rsurface.modelsurfaces = model->data_surfaces;
7977         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7978         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7979         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7980         rsurface.modelgeneratedvertex = false;
7981         rsurface.batchgeneratedvertex = false;
7982         rsurface.batchfirstvertex = 0;
7983         rsurface.batchnumvertices = 0;
7984         rsurface.batchfirsttriangle = 0;
7985         rsurface.batchnumtriangles = 0;
7986         rsurface.batchvertex3f  = NULL;
7987         rsurface.batchvertex3f_vertexbuffer = NULL;
7988         rsurface.batchvertex3f_bufferoffset = 0;
7989         rsurface.batchsvector3f = NULL;
7990         rsurface.batchsvector3f_vertexbuffer = NULL;
7991         rsurface.batchsvector3f_bufferoffset = 0;
7992         rsurface.batchtvector3f = NULL;
7993         rsurface.batchtvector3f_vertexbuffer = NULL;
7994         rsurface.batchtvector3f_bufferoffset = 0;
7995         rsurface.batchnormal3f  = NULL;
7996         rsurface.batchnormal3f_vertexbuffer = NULL;
7997         rsurface.batchnormal3f_bufferoffset = 0;
7998         rsurface.batchlightmapcolor4f = NULL;
7999         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8000         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8001         rsurface.batchtexcoordtexture2f = NULL;
8002         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8003         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8004         rsurface.batchtexcoordlightmap2f = NULL;
8005         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8006         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8007         rsurface.batchvertexmesh = NULL;
8008         rsurface.batchvertexmeshbuffer = NULL;
8009         rsurface.batchvertex3fbuffer = NULL;
8010         rsurface.batchelement3i = NULL;
8011         rsurface.batchelement3i_indexbuffer = NULL;
8012         rsurface.batchelement3i_bufferoffset = 0;
8013         rsurface.batchelement3s = NULL;
8014         rsurface.batchelement3s_indexbuffer = NULL;
8015         rsurface.batchelement3s_bufferoffset = 0;
8016         rsurface.passcolor4f = NULL;
8017         rsurface.passcolor4f_vertexbuffer = NULL;
8018         rsurface.passcolor4f_bufferoffset = 0;
8019 }
8020
8021 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8022 {
8023         dp_model_t *model = ent->model;
8024         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8025         //      return;
8026         rsurface.entity = (entity_render_t *)ent;
8027         rsurface.skeleton = ent->skeleton;
8028         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8029         rsurface.ent_skinnum = ent->skinnum;
8030         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;
8031         rsurface.ent_flags = ent->flags;
8032         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8033         rsurface.matrix = ent->matrix;
8034         rsurface.inversematrix = ent->inversematrix;
8035         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8036         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8037         R_EntityMatrix(&rsurface.matrix);
8038         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8039         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8040         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8041         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8042         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8043         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8044         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8045         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8046         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8047         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8048         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8049         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8050         rsurface.colormod[3] = ent->alpha;
8051         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8052         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8053         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8054         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8055         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8056         if (ent->model->brush.submodel && !prepass)
8057         {
8058                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8059                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8060         }
8061         if (model->surfmesh.isanimated && model->AnimateVertices)
8062         {
8063                 if (ent->animcache_vertex3f)
8064                 {
8065                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8066                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8067                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8068                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8069                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8070                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8071                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8072                 }
8073                 else if (wanttangents)
8074                 {
8075                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8076                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8077                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8078                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8079                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8080                         rsurface.modelvertexmesh = NULL;
8081                         rsurface.modelvertexmeshbuffer = NULL;
8082                         rsurface.modelvertex3fbuffer = NULL;
8083                 }
8084                 else if (wantnormals)
8085                 {
8086                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8087                         rsurface.modelsvector3f = NULL;
8088                         rsurface.modeltvector3f = NULL;
8089                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8090                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8091                         rsurface.modelvertexmesh = NULL;
8092                         rsurface.modelvertexmeshbuffer = NULL;
8093                         rsurface.modelvertex3fbuffer = NULL;
8094                 }
8095                 else
8096                 {
8097                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8098                         rsurface.modelsvector3f = NULL;
8099                         rsurface.modeltvector3f = NULL;
8100                         rsurface.modelnormal3f = NULL;
8101                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8102                         rsurface.modelvertexmesh = NULL;
8103                         rsurface.modelvertexmeshbuffer = NULL;
8104                         rsurface.modelvertex3fbuffer = NULL;
8105                 }
8106                 rsurface.modelvertex3f_vertexbuffer = 0;
8107                 rsurface.modelvertex3f_bufferoffset = 0;
8108                 rsurface.modelsvector3f_vertexbuffer = 0;
8109                 rsurface.modelsvector3f_bufferoffset = 0;
8110                 rsurface.modeltvector3f_vertexbuffer = 0;
8111                 rsurface.modeltvector3f_bufferoffset = 0;
8112                 rsurface.modelnormal3f_vertexbuffer = 0;
8113                 rsurface.modelnormal3f_bufferoffset = 0;
8114                 rsurface.modelgeneratedvertex = true;
8115         }
8116         else
8117         {
8118                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8119                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8120                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8121                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8122                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8123                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8124                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8125                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8126                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8127                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8128                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8129                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8130                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8131                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8132                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8133                 rsurface.modelgeneratedvertex = false;
8134         }
8135         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8136         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8137         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8138         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8139         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8140         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8141         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8142         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8143         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8144         rsurface.modelelement3i = model->surfmesh.data_element3i;
8145         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8146         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8147         rsurface.modelelement3s = model->surfmesh.data_element3s;
8148         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8149         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8150         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8151         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8152         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8153         rsurface.modelsurfaces = model->data_surfaces;
8154         rsurface.batchgeneratedvertex = false;
8155         rsurface.batchfirstvertex = 0;
8156         rsurface.batchnumvertices = 0;
8157         rsurface.batchfirsttriangle = 0;
8158         rsurface.batchnumtriangles = 0;
8159         rsurface.batchvertex3f  = NULL;
8160         rsurface.batchvertex3f_vertexbuffer = NULL;
8161         rsurface.batchvertex3f_bufferoffset = 0;
8162         rsurface.batchsvector3f = NULL;
8163         rsurface.batchsvector3f_vertexbuffer = NULL;
8164         rsurface.batchsvector3f_bufferoffset = 0;
8165         rsurface.batchtvector3f = NULL;
8166         rsurface.batchtvector3f_vertexbuffer = NULL;
8167         rsurface.batchtvector3f_bufferoffset = 0;
8168         rsurface.batchnormal3f  = NULL;
8169         rsurface.batchnormal3f_vertexbuffer = NULL;
8170         rsurface.batchnormal3f_bufferoffset = 0;
8171         rsurface.batchlightmapcolor4f = NULL;
8172         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8173         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8174         rsurface.batchtexcoordtexture2f = NULL;
8175         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8176         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8177         rsurface.batchtexcoordlightmap2f = NULL;
8178         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8179         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8180         rsurface.batchvertexmesh = NULL;
8181         rsurface.batchvertexmeshbuffer = NULL;
8182         rsurface.batchvertex3fbuffer = NULL;
8183         rsurface.batchelement3i = NULL;
8184         rsurface.batchelement3i_indexbuffer = NULL;
8185         rsurface.batchelement3i_bufferoffset = 0;
8186         rsurface.batchelement3s = NULL;
8187         rsurface.batchelement3s_indexbuffer = NULL;
8188         rsurface.batchelement3s_bufferoffset = 0;
8189         rsurface.passcolor4f = NULL;
8190         rsurface.passcolor4f_vertexbuffer = NULL;
8191         rsurface.passcolor4f_bufferoffset = 0;
8192 }
8193
8194 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)
8195 {
8196         rsurface.entity = r_refdef.scene.worldentity;
8197         rsurface.skeleton = NULL;
8198         rsurface.ent_skinnum = 0;
8199         rsurface.ent_qwskin = -1;
8200         rsurface.ent_flags = entflags;
8201         rsurface.shadertime = r_refdef.scene.time - shadertime;
8202         rsurface.modelnumvertices = numvertices;
8203         rsurface.modelnumtriangles = numtriangles;
8204         rsurface.matrix = *matrix;
8205         rsurface.inversematrix = *inversematrix;
8206         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8207         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8208         R_EntityMatrix(&rsurface.matrix);
8209         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8210         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8211         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8212         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8213         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8214         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8215         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8216         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8217         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8218         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8219         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8220         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8221         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);
8222         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8223         rsurface.frameblend[0].lerp = 1;
8224         rsurface.ent_alttextures = false;
8225         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8226         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8227         if (wanttangents)
8228         {
8229                 rsurface.modelvertex3f = (float *)vertex3f;
8230                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8231                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8232                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8233         }
8234         else if (wantnormals)
8235         {
8236                 rsurface.modelvertex3f = (float *)vertex3f;
8237                 rsurface.modelsvector3f = NULL;
8238                 rsurface.modeltvector3f = NULL;
8239                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8240         }
8241         else
8242         {
8243                 rsurface.modelvertex3f = (float *)vertex3f;
8244                 rsurface.modelsvector3f = NULL;
8245                 rsurface.modeltvector3f = NULL;
8246                 rsurface.modelnormal3f = NULL;
8247         }
8248         rsurface.modelvertexmesh = NULL;
8249         rsurface.modelvertexmeshbuffer = NULL;
8250         rsurface.modelvertex3fbuffer = NULL;
8251         rsurface.modelvertex3f_vertexbuffer = 0;
8252         rsurface.modelvertex3f_bufferoffset = 0;
8253         rsurface.modelsvector3f_vertexbuffer = 0;
8254         rsurface.modelsvector3f_bufferoffset = 0;
8255         rsurface.modeltvector3f_vertexbuffer = 0;
8256         rsurface.modeltvector3f_bufferoffset = 0;
8257         rsurface.modelnormal3f_vertexbuffer = 0;
8258         rsurface.modelnormal3f_bufferoffset = 0;
8259         rsurface.modelgeneratedvertex = true;
8260         rsurface.modellightmapcolor4f  = (float *)color4f;
8261         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8262         rsurface.modellightmapcolor4f_bufferoffset = 0;
8263         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8264         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8265         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8266         rsurface.modeltexcoordlightmap2f  = NULL;
8267         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8268         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8269         rsurface.modelelement3i = (int *)element3i;
8270         rsurface.modelelement3i_indexbuffer = NULL;
8271         rsurface.modelelement3i_bufferoffset = 0;
8272         rsurface.modelelement3s = (unsigned short *)element3s;
8273         rsurface.modelelement3s_indexbuffer = NULL;
8274         rsurface.modelelement3s_bufferoffset = 0;
8275         rsurface.modellightmapoffsets = NULL;
8276         rsurface.modelsurfaces = NULL;
8277         rsurface.batchgeneratedvertex = false;
8278         rsurface.batchfirstvertex = 0;
8279         rsurface.batchnumvertices = 0;
8280         rsurface.batchfirsttriangle = 0;
8281         rsurface.batchnumtriangles = 0;
8282         rsurface.batchvertex3f  = NULL;
8283         rsurface.batchvertex3f_vertexbuffer = NULL;
8284         rsurface.batchvertex3f_bufferoffset = 0;
8285         rsurface.batchsvector3f = NULL;
8286         rsurface.batchsvector3f_vertexbuffer = NULL;
8287         rsurface.batchsvector3f_bufferoffset = 0;
8288         rsurface.batchtvector3f = NULL;
8289         rsurface.batchtvector3f_vertexbuffer = NULL;
8290         rsurface.batchtvector3f_bufferoffset = 0;
8291         rsurface.batchnormal3f  = NULL;
8292         rsurface.batchnormal3f_vertexbuffer = NULL;
8293         rsurface.batchnormal3f_bufferoffset = 0;
8294         rsurface.batchlightmapcolor4f = NULL;
8295         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8296         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8297         rsurface.batchtexcoordtexture2f = NULL;
8298         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8299         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8300         rsurface.batchtexcoordlightmap2f = NULL;
8301         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8302         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8303         rsurface.batchvertexmesh = NULL;
8304         rsurface.batchvertexmeshbuffer = NULL;
8305         rsurface.batchvertex3fbuffer = NULL;
8306         rsurface.batchelement3i = NULL;
8307         rsurface.batchelement3i_indexbuffer = NULL;
8308         rsurface.batchelement3i_bufferoffset = 0;
8309         rsurface.batchelement3s = NULL;
8310         rsurface.batchelement3s_indexbuffer = NULL;
8311         rsurface.batchelement3s_bufferoffset = 0;
8312         rsurface.passcolor4f = NULL;
8313         rsurface.passcolor4f_vertexbuffer = NULL;
8314         rsurface.passcolor4f_bufferoffset = 0;
8315
8316         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8317         {
8318                 if ((wantnormals || wanttangents) && !normal3f)
8319                 {
8320                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8321                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8322                 }
8323                 if (wanttangents && !svector3f)
8324                 {
8325                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8326                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8327                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8328                 }
8329         }
8330 }
8331
8332 float RSurf_FogPoint(const float *v)
8333 {
8334         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8335         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8336         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8337         float FogHeightFade = r_refdef.fogheightfade;
8338         float fogfrac;
8339         unsigned int fogmasktableindex;
8340         if (r_refdef.fogplaneviewabove)
8341                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8342         else
8343                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8344         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8345         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8346 }
8347
8348 float RSurf_FogVertex(const float *v)
8349 {
8350         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8351         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8352         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8353         float FogHeightFade = rsurface.fogheightfade;
8354         float fogfrac;
8355         unsigned int fogmasktableindex;
8356         if (r_refdef.fogplaneviewabove)
8357                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8358         else
8359                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8360         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8361         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8362 }
8363
8364 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8365 {
8366         int i;
8367         for (i = 0;i < numelements;i++)
8368                 outelement3i[i] = inelement3i[i] + adjust;
8369 }
8370
8371 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8372 extern cvar_t gl_vbo;
8373 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8374 {
8375         int deformindex;
8376         int firsttriangle;
8377         int numtriangles;
8378         int firstvertex;
8379         int endvertex;
8380         int numvertices;
8381         int surfacefirsttriangle;
8382         int surfacenumtriangles;
8383         int surfacefirstvertex;
8384         int surfaceendvertex;
8385         int surfacenumvertices;
8386         int batchnumvertices;
8387         int batchnumtriangles;
8388         int needsupdate;
8389         int i, j;
8390         qboolean gaps;
8391         qboolean dynamicvertex;
8392         float amplitude;
8393         float animpos;
8394         float scale;
8395         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8396         float waveparms[4];
8397         q3shaderinfo_deform_t *deform;
8398         const msurface_t *surface, *firstsurface;
8399         r_vertexmesh_t *vertexmesh;
8400         if (!texturenumsurfaces)
8401                 return;
8402         // find vertex range of this surface batch
8403         gaps = false;
8404         firstsurface = texturesurfacelist[0];
8405         firsttriangle = firstsurface->num_firsttriangle;
8406         batchnumvertices = 0;
8407         batchnumtriangles = 0;
8408         firstvertex = endvertex = firstsurface->num_firstvertex;
8409         for (i = 0;i < texturenumsurfaces;i++)
8410         {
8411                 surface = texturesurfacelist[i];
8412                 if (surface != firstsurface + i)
8413                         gaps = true;
8414                 surfacefirstvertex = surface->num_firstvertex;
8415                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8416                 surfacenumvertices = surface->num_vertices;
8417                 surfacenumtriangles = surface->num_triangles;
8418                 if (firstvertex > surfacefirstvertex)
8419                         firstvertex = surfacefirstvertex;
8420                 if (endvertex < surfaceendvertex)
8421                         endvertex = surfaceendvertex;
8422                 batchnumvertices += surfacenumvertices;
8423                 batchnumtriangles += surfacenumtriangles;
8424         }
8425
8426         // we now know the vertex range used, and if there are any gaps in it
8427         rsurface.batchfirstvertex = firstvertex;
8428         rsurface.batchnumvertices = endvertex - firstvertex;
8429         rsurface.batchfirsttriangle = firsttriangle;
8430         rsurface.batchnumtriangles = batchnumtriangles;
8431
8432         // this variable holds flags for which properties have been updated that
8433         // may require regenerating vertexmesh array...
8434         needsupdate = 0;
8435
8436         // check if any dynamic vertex processing must occur
8437         dynamicvertex = false;
8438
8439         // if there is a chance of animated vertex colors, it's a dynamic batch
8440         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8441         {
8442                 dynamicvertex = true;
8443                 batchneed |= BATCHNEED_NOGAPS;
8444                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8445         }
8446
8447         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8448         {
8449                 switch (deform->deform)
8450                 {
8451                 default:
8452                 case Q3DEFORM_PROJECTIONSHADOW:
8453                 case Q3DEFORM_TEXT0:
8454                 case Q3DEFORM_TEXT1:
8455                 case Q3DEFORM_TEXT2:
8456                 case Q3DEFORM_TEXT3:
8457                 case Q3DEFORM_TEXT4:
8458                 case Q3DEFORM_TEXT5:
8459                 case Q3DEFORM_TEXT6:
8460                 case Q3DEFORM_TEXT7:
8461                 case Q3DEFORM_NONE:
8462                         break;
8463                 case Q3DEFORM_AUTOSPRITE:
8464                         dynamicvertex = true;
8465                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8466                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8467                         break;
8468                 case Q3DEFORM_AUTOSPRITE2:
8469                         dynamicvertex = true;
8470                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8471                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8472                         break;
8473                 case Q3DEFORM_NORMAL:
8474                         dynamicvertex = true;
8475                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8476                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8477                         break;
8478                 case Q3DEFORM_WAVE:
8479                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8480                                 break; // if wavefunc is a nop, ignore this transform
8481                         dynamicvertex = true;
8482                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8483                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8484                         break;
8485                 case Q3DEFORM_BULGE:
8486                         dynamicvertex = true;
8487                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8488                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8489                         break;
8490                 case Q3DEFORM_MOVE:
8491                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8492                                 break; // if wavefunc is a nop, ignore this transform
8493                         dynamicvertex = true;
8494                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8495                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8496                         break;
8497                 }
8498         }
8499         switch(rsurface.texture->tcgen.tcgen)
8500         {
8501         default:
8502         case Q3TCGEN_TEXTURE:
8503                 break;
8504         case Q3TCGEN_LIGHTMAP:
8505                 dynamicvertex = true;
8506                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8507                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8508                 break;
8509         case Q3TCGEN_VECTOR:
8510                 dynamicvertex = true;
8511                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8512                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8513                 break;
8514         case Q3TCGEN_ENVIRONMENT:
8515                 dynamicvertex = true;
8516                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8517                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8518                 break;
8519         }
8520         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8521         {
8522                 dynamicvertex = true;
8523                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8524                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8525         }
8526
8527         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8528         {
8529                 dynamicvertex = true;
8530                 batchneed |= BATCHNEED_NOGAPS;
8531                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8532         }
8533
8534         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8535         {
8536                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8537                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8538                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8539                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8540                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8541                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8542                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8543         }
8544
8545         // when the model data has no vertex buffer (dynamic mesh), we need to
8546         // eliminate gaps
8547         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8548                 batchneed |= BATCHNEED_NOGAPS;
8549
8550         // if needsupdate, we have to do a dynamic vertex batch for sure
8551         if (needsupdate & batchneed)
8552                 dynamicvertex = true;
8553
8554         // see if we need to build vertexmesh from arrays
8555         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8556                 dynamicvertex = true;
8557
8558         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8559         // also some drivers strongly dislike firstvertex
8560         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8561                 dynamicvertex = true;
8562
8563         rsurface.batchvertex3f = rsurface.modelvertex3f;
8564         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8565         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8566         rsurface.batchsvector3f = rsurface.modelsvector3f;
8567         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8568         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8569         rsurface.batchtvector3f = rsurface.modeltvector3f;
8570         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8571         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8572         rsurface.batchnormal3f = rsurface.modelnormal3f;
8573         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8574         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8575         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8576         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8577         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8578         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8579         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8580         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8581         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8582         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8583         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8584         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8585         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8586         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8587         rsurface.batchelement3i = rsurface.modelelement3i;
8588         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8589         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8590         rsurface.batchelement3s = rsurface.modelelement3s;
8591         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8592         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8593
8594         // if any dynamic vertex processing has to occur in software, we copy the
8595         // entire surface list together before processing to rebase the vertices
8596         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8597         //
8598         // if any gaps exist and we do not have a static vertex buffer, we have to
8599         // copy the surface list together to avoid wasting upload bandwidth on the
8600         // vertices in the gaps.
8601         //
8602         // if gaps exist and we have a static vertex buffer, we still have to
8603         // combine the index buffer ranges into one dynamic index buffer.
8604         //
8605         // in all cases we end up with data that can be drawn in one call.
8606
8607         if (!dynamicvertex)
8608         {
8609                 // static vertex data, just set pointers...
8610                 rsurface.batchgeneratedvertex = false;
8611                 // if there are gaps, we want to build a combined index buffer,
8612                 // otherwise use the original static buffer with an appropriate offset
8613                 if (gaps)
8614                 {
8615                         // build a new triangle elements array for this batch
8616                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8617                         rsurface.batchfirsttriangle = 0;
8618                         numtriangles = 0;
8619                         for (i = 0;i < texturenumsurfaces;i++)
8620                         {
8621                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8622                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8623                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8624                                 numtriangles += surfacenumtriangles;
8625                         }
8626                         rsurface.batchelement3i_indexbuffer = NULL;
8627                         rsurface.batchelement3i_bufferoffset = 0;
8628                         rsurface.batchelement3s = NULL;
8629                         rsurface.batchelement3s_indexbuffer = NULL;
8630                         rsurface.batchelement3s_bufferoffset = 0;
8631                         if (endvertex <= 65536)
8632                         {
8633                                 // make a 16bit (unsigned short) index array if possible
8634                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8635                                 for (i = 0;i < numtriangles*3;i++)
8636                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8637                         }
8638                 }
8639                 return;
8640         }
8641
8642         // something needs software processing, do it for real...
8643         // we only directly handle separate array data in this case and then
8644         // generate interleaved data if needed...
8645         rsurface.batchgeneratedvertex = true;
8646
8647         // now copy the vertex data into a combined array and make an index array
8648         // (this is what Quake3 does all the time)
8649         //if (gaps || rsurface.batchfirstvertex)
8650         {
8651                 rsurface.batchvertex3fbuffer = NULL;
8652                 rsurface.batchvertexmesh = NULL;
8653                 rsurface.batchvertexmeshbuffer = NULL;
8654                 rsurface.batchvertex3f = NULL;
8655                 rsurface.batchvertex3f_vertexbuffer = NULL;
8656                 rsurface.batchvertex3f_bufferoffset = 0;
8657                 rsurface.batchsvector3f = NULL;
8658                 rsurface.batchsvector3f_vertexbuffer = NULL;
8659                 rsurface.batchsvector3f_bufferoffset = 0;
8660                 rsurface.batchtvector3f = NULL;
8661                 rsurface.batchtvector3f_vertexbuffer = NULL;
8662                 rsurface.batchtvector3f_bufferoffset = 0;
8663                 rsurface.batchnormal3f = NULL;
8664                 rsurface.batchnormal3f_vertexbuffer = NULL;
8665                 rsurface.batchnormal3f_bufferoffset = 0;
8666                 rsurface.batchlightmapcolor4f = NULL;
8667                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8668                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8669                 rsurface.batchtexcoordtexture2f = NULL;
8670                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8671                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8672                 rsurface.batchtexcoordlightmap2f = NULL;
8673                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8674                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8675                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8676                 rsurface.batchelement3i_indexbuffer = NULL;
8677                 rsurface.batchelement3i_bufferoffset = 0;
8678                 rsurface.batchelement3s = NULL;
8679                 rsurface.batchelement3s_indexbuffer = NULL;
8680                 rsurface.batchelement3s_bufferoffset = 0;
8681                 // we'll only be setting up certain arrays as needed
8682                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8683                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8684                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8685                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8686                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8687                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8688                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8689                 {
8690                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8691                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8692                 }
8693                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8694                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8695                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8696                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8697                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8698                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8699                 numvertices = 0;
8700                 numtriangles = 0;
8701                 for (i = 0;i < texturenumsurfaces;i++)
8702                 {
8703                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8704                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8705                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8706                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8707                         // copy only the data requested
8708                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8709                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8710                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8711                         {
8712                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8713                                 {
8714                                         if (rsurface.batchvertex3f)
8715                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8716                                         else
8717                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8718                                 }
8719                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8720                                 {
8721                                         if (rsurface.modelnormal3f)
8722                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8723                                         else
8724                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8725                                 }
8726                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8727                                 {
8728                                         if (rsurface.modelsvector3f)
8729                                         {
8730                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8731                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8732                                         }
8733                                         else
8734                                         {
8735                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8736                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8737                                         }
8738                                 }
8739                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8740                                 {
8741                                         if (rsurface.modellightmapcolor4f)
8742                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8743                                         else
8744                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8745                                 }
8746                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8747                                 {
8748                                         if (rsurface.modeltexcoordtexture2f)
8749                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8750                                         else
8751                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8752                                 }
8753                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8754                                 {
8755                                         if (rsurface.modeltexcoordlightmap2f)
8756                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8757                                         else
8758                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8759                                 }
8760                         }
8761                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8762                         numvertices += surfacenumvertices;
8763                         numtriangles += surfacenumtriangles;
8764                 }
8765
8766                 // generate a 16bit index array as well if possible
8767                 // (in general, dynamic batches fit)
8768                 if (numvertices <= 65536)
8769                 {
8770                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8771                         for (i = 0;i < numtriangles*3;i++)
8772                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8773                 }
8774
8775                 // since we've copied everything, the batch now starts at 0
8776                 rsurface.batchfirstvertex = 0;
8777                 rsurface.batchnumvertices = batchnumvertices;
8778                 rsurface.batchfirsttriangle = 0;
8779                 rsurface.batchnumtriangles = batchnumtriangles;
8780         }
8781
8782         // q1bsp surfaces rendered in vertex color mode have to have colors
8783         // calculated based on lightstyles
8784         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8785         {
8786                 // generate color arrays for the surfaces in this list
8787                 int c[4];
8788                 int scale;
8789                 int size3;
8790                 const int *offsets;
8791                 const unsigned char *lm;
8792                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8793                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8794                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8795                 numvertices = 0;
8796                 for (i = 0;i < texturenumsurfaces;i++)
8797                 {
8798                         surface = texturesurfacelist[i];
8799                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8800                         surfacenumvertices = surface->num_vertices;
8801                         if (surface->lightmapinfo->samples)
8802                         {
8803                                 for (j = 0;j < surfacenumvertices;j++)
8804                                 {
8805                                         lm = surface->lightmapinfo->samples + offsets[j];
8806                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8807                                         VectorScale(lm, scale, c);
8808                                         if (surface->lightmapinfo->styles[1] != 255)
8809                                         {
8810                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8811                                                 lm += size3;
8812                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8813                                                 VectorMA(c, scale, lm, c);
8814                                                 if (surface->lightmapinfo->styles[2] != 255)
8815                                                 {
8816                                                         lm += size3;
8817                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8818                                                         VectorMA(c, scale, lm, c);
8819                                                         if (surface->lightmapinfo->styles[3] != 255)
8820                                                         {
8821                                                                 lm += size3;
8822                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8823                                                                 VectorMA(c, scale, lm, c);
8824                                                         }
8825                                                 }
8826                                         }
8827                                         c[0] >>= 7;
8828                                         c[1] >>= 7;
8829                                         c[2] >>= 7;
8830                                         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);
8831                                         numvertices++;
8832                                 }
8833                         }
8834                         else
8835                         {
8836                                 for (j = 0;j < surfacenumvertices;j++)
8837                                 {
8838                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8839                                         numvertices++;
8840                                 }
8841                         }
8842                 }
8843         }
8844
8845         // if vertices are deformed (sprite flares and things in maps, possibly
8846         // water waves, bulges and other deformations), modify the copied vertices
8847         // in place
8848         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8849         {
8850                 switch (deform->deform)
8851                 {
8852                 default:
8853                 case Q3DEFORM_PROJECTIONSHADOW:
8854                 case Q3DEFORM_TEXT0:
8855                 case Q3DEFORM_TEXT1:
8856                 case Q3DEFORM_TEXT2:
8857                 case Q3DEFORM_TEXT3:
8858                 case Q3DEFORM_TEXT4:
8859                 case Q3DEFORM_TEXT5:
8860                 case Q3DEFORM_TEXT6:
8861                 case Q3DEFORM_TEXT7:
8862                 case Q3DEFORM_NONE:
8863                         break;
8864                 case Q3DEFORM_AUTOSPRITE:
8865                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8866                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8867                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8868                         VectorNormalize(newforward);
8869                         VectorNormalize(newright);
8870                         VectorNormalize(newup);
8871 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8872 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8873 //                      rsurface.batchvertex3f_bufferoffset = 0;
8874 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8875 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8876 //                      rsurface.batchsvector3f_bufferoffset = 0;
8877 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8878 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8879 //                      rsurface.batchtvector3f_bufferoffset = 0;
8880 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8881 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8882 //                      rsurface.batchnormal3f_bufferoffset = 0;
8883                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8884                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8885                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8886                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8887                                 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);
8888                         // a single autosprite surface can contain multiple sprites...
8889                         for (j = 0;j < batchnumvertices - 3;j += 4)
8890                         {
8891                                 VectorClear(center);
8892                                 for (i = 0;i < 4;i++)
8893                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8894                                 VectorScale(center, 0.25f, center);
8895                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8896                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8897                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8898                                 for (i = 0;i < 4;i++)
8899                                 {
8900                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8901                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8902                                 }
8903                         }
8904                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8905                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8906                         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);
8907                         break;
8908                 case Q3DEFORM_AUTOSPRITE2:
8909                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8910                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8911                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8912                         VectorNormalize(newforward);
8913                         VectorNormalize(newright);
8914                         VectorNormalize(newup);
8915 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8916 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8917 //                      rsurface.batchvertex3f_bufferoffset = 0;
8918                         {
8919                                 const float *v1, *v2;
8920                                 vec3_t start, end;
8921                                 float f, l;
8922                                 struct
8923                                 {
8924                                         float length2;
8925                                         const float *v1;
8926                                         const float *v2;
8927                                 }
8928                                 shortest[2];
8929                                 memset(shortest, 0, sizeof(shortest));
8930                                 // a single autosprite surface can contain multiple sprites...
8931                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8932                                 {
8933                                         VectorClear(center);
8934                                         for (i = 0;i < 4;i++)
8935                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8936                                         VectorScale(center, 0.25f, center);
8937                                         // find the two shortest edges, then use them to define the
8938                                         // axis vectors for rotating around the central axis
8939                                         for (i = 0;i < 6;i++)
8940                                         {
8941                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8942                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8943                                                 l = VectorDistance2(v1, v2);
8944                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8945                                                 if (v1[2] != v2[2])
8946                                                         l += (1.0f / 1024.0f);
8947                                                 if (shortest[0].length2 > l || i == 0)
8948                                                 {
8949                                                         shortest[1] = shortest[0];
8950                                                         shortest[0].length2 = l;
8951                                                         shortest[0].v1 = v1;
8952                                                         shortest[0].v2 = v2;
8953                                                 }
8954                                                 else if (shortest[1].length2 > l || i == 1)
8955                                                 {
8956                                                         shortest[1].length2 = l;
8957                                                         shortest[1].v1 = v1;
8958                                                         shortest[1].v2 = v2;
8959                                                 }
8960                                         }
8961                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8962                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8963                                         // this calculates the right vector from the shortest edge
8964                                         // and the up vector from the edge midpoints
8965                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8966                                         VectorNormalize(right);
8967                                         VectorSubtract(end, start, up);
8968                                         VectorNormalize(up);
8969                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8970                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8971                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8972                                         VectorNegate(forward, forward);
8973                                         VectorReflect(forward, 0, up, forward);
8974                                         VectorNormalize(forward);
8975                                         CrossProduct(up, forward, newright);
8976                                         VectorNormalize(newright);
8977                                         // rotate the quad around the up axis vector, this is made
8978                                         // especially easy by the fact we know the quad is flat,
8979                                         // so we only have to subtract the center position and
8980                                         // measure distance along the right vector, and then
8981                                         // multiply that by the newright vector and add back the
8982                                         // center position
8983                                         // we also need to subtract the old position to undo the
8984                                         // displacement from the center, which we do with a
8985                                         // DotProduct, the subtraction/addition of center is also
8986                                         // optimized into DotProducts here
8987                                         l = DotProduct(right, center);
8988                                         for (i = 0;i < 4;i++)
8989                                         {
8990                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8991                                                 f = DotProduct(right, v1) - l;
8992                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8993                                         }
8994                                 }
8995                         }
8996                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8997                         {
8998 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8999 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9000 //                              rsurface.batchnormal3f_bufferoffset = 0;
9001                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9002                         }
9003                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9004                         {
9005 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9006 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9007 //                              rsurface.batchsvector3f_bufferoffset = 0;
9008 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9009 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9010 //                              rsurface.batchtvector3f_bufferoffset = 0;
9011                                 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);
9012                         }
9013                         break;
9014                 case Q3DEFORM_NORMAL:
9015                         // deform the normals to make reflections wavey
9016                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9017                         rsurface.batchnormal3f_vertexbuffer = NULL;
9018                         rsurface.batchnormal3f_bufferoffset = 0;
9019                         for (j = 0;j < batchnumvertices;j++)
9020                         {
9021                                 float vertex[3];
9022                                 float *normal = rsurface.batchnormal3f + 3*j;
9023                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9024                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9025                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9026                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9027                                 VectorNormalize(normal);
9028                         }
9029                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9030                         {
9031 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9032 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9033 //                              rsurface.batchsvector3f_bufferoffset = 0;
9034 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9035 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9036 //                              rsurface.batchtvector3f_bufferoffset = 0;
9037                                 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);
9038                         }
9039                         break;
9040                 case Q3DEFORM_WAVE:
9041                         // deform vertex array to make wavey water and flags and such
9042                         waveparms[0] = deform->waveparms[0];
9043                         waveparms[1] = deform->waveparms[1];
9044                         waveparms[2] = deform->waveparms[2];
9045                         waveparms[3] = deform->waveparms[3];
9046                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9047                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9048                         // this is how a divisor of vertex influence on deformation
9049                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9050                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9051 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9052 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9053 //                      rsurface.batchvertex3f_bufferoffset = 0;
9054 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9055 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9056 //                      rsurface.batchnormal3f_bufferoffset = 0;
9057                         for (j = 0;j < batchnumvertices;j++)
9058                         {
9059                                 // if the wavefunc depends on time, evaluate it per-vertex
9060                                 if (waveparms[3])
9061                                 {
9062                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9063                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9064                                 }
9065                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9066                         }
9067                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9068                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9069                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9070                         {
9071 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9072 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9073 //                              rsurface.batchsvector3f_bufferoffset = 0;
9074 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9075 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9076 //                              rsurface.batchtvector3f_bufferoffset = 0;
9077                                 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);
9078                         }
9079                         break;
9080                 case Q3DEFORM_BULGE:
9081                         // deform vertex array to make the surface have moving bulges
9082 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9083 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9084 //                      rsurface.batchvertex3f_bufferoffset = 0;
9085 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9086 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9087 //                      rsurface.batchnormal3f_bufferoffset = 0;
9088                         for (j = 0;j < batchnumvertices;j++)
9089                         {
9090                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9091                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9092                         }
9093                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9094                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9095                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9096                         {
9097 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9098 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9099 //                              rsurface.batchsvector3f_bufferoffset = 0;
9100 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9101 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9102 //                              rsurface.batchtvector3f_bufferoffset = 0;
9103                                 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);
9104                         }
9105                         break;
9106                 case Q3DEFORM_MOVE:
9107                         // deform vertex array
9108                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9109                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9110                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9111                         VectorScale(deform->parms, scale, waveparms);
9112 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9113 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9114 //                      rsurface.batchvertex3f_bufferoffset = 0;
9115                         for (j = 0;j < batchnumvertices;j++)
9116                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9117                         break;
9118                 }
9119         }
9120
9121         // generate texcoords based on the chosen texcoord source
9122         switch(rsurface.texture->tcgen.tcgen)
9123         {
9124         default:
9125         case Q3TCGEN_TEXTURE:
9126                 break;
9127         case Q3TCGEN_LIGHTMAP:
9128 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9129 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9130 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9131                 if (rsurface.batchtexcoordlightmap2f)
9132                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9133                 break;
9134         case Q3TCGEN_VECTOR:
9135 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9136 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9137 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9138                 for (j = 0;j < batchnumvertices;j++)
9139                 {
9140                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9141                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9142                 }
9143                 break;
9144         case Q3TCGEN_ENVIRONMENT:
9145                 // make environment reflections using a spheremap
9146                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9147                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9148                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9149                 for (j = 0;j < batchnumvertices;j++)
9150                 {
9151                         // identical to Q3A's method, but executed in worldspace so
9152                         // carried models can be shiny too
9153
9154                         float viewer[3], d, reflected[3], worldreflected[3];
9155
9156                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9157                         // VectorNormalize(viewer);
9158
9159                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9160
9161                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9162                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9163                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9164                         // note: this is proportinal to viewer, so we can normalize later
9165
9166                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9167                         VectorNormalize(worldreflected);
9168
9169                         // note: this sphere map only uses world x and z!
9170                         // so positive and negative y will LOOK THE SAME.
9171                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9172                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9173                 }
9174                 break;
9175         }
9176         // the only tcmod that needs software vertex processing is turbulent, so
9177         // check for it here and apply the changes if needed
9178         // and we only support that as the first one
9179         // (handling a mixture of turbulent and other tcmods would be problematic
9180         //  without punting it entirely to a software path)
9181         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9182         {
9183                 amplitude = rsurface.texture->tcmods[0].parms[1];
9184                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9185 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9186 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9187 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9188                 for (j = 0;j < batchnumvertices;j++)
9189                 {
9190                         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);
9191                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9192                 }
9193         }
9194
9195         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9196         {
9197                 // convert the modified arrays to vertex structs
9198 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9199 //              rsurface.batchvertexmeshbuffer = NULL;
9200                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9201                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9202                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9203                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9204                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9205                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9206                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9207                 {
9208                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9209                         {
9210                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9211                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9212                         }
9213                 }
9214                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9215                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9216                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9217                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9218                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9219                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9220                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9221                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9222                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9223         }
9224 }
9225
9226 void RSurf_DrawBatch(void)
9227 {
9228         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9229         // through the pipeline, killing it earlier in the pipeline would have
9230         // per-surface overhead rather than per-batch overhead, so it's best to
9231         // reject it here, before it hits glDraw.
9232         if (rsurface.batchnumtriangles == 0)
9233                 return;
9234 #if 0
9235         // batch debugging code
9236         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9237         {
9238                 int i;
9239                 int j;
9240                 int c;
9241                 const int *e;
9242                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9243                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9244                 {
9245                         c = e[i];
9246                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9247                         {
9248                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9249                                 {
9250                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9251                                                 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);
9252                                         break;
9253                                 }
9254                         }
9255                 }
9256         }
9257 #endif
9258         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);
9259 }
9260
9261 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9262 {
9263         // pick the closest matching water plane
9264         int planeindex, vertexindex, bestplaneindex = -1;
9265         float d, bestd;
9266         vec3_t vert;
9267         const float *v;
9268         r_waterstate_waterplane_t *p;
9269         qboolean prepared = false;
9270         bestd = 0;
9271         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9272         {
9273                 if(p->camera_entity != rsurface.texture->camera_entity)
9274                         continue;
9275                 d = 0;
9276                 if(!prepared)
9277                 {
9278                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9279                         prepared = true;
9280                         if(rsurface.batchnumvertices == 0)
9281                                 break;
9282                 }
9283                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9284                 {
9285                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9286                         d += fabs(PlaneDiff(vert, &p->plane));
9287                 }
9288                 if (bestd > d || bestplaneindex < 0)
9289                 {
9290                         bestd = d;
9291                         bestplaneindex = planeindex;
9292                 }
9293         }
9294         return bestplaneindex;
9295         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9296         // this situation though, as it might be better to render single larger
9297         // batches with useless stuff (backface culled for example) than to
9298         // render multiple smaller batches
9299 }
9300
9301 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9302 {
9303         int i;
9304         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9305         rsurface.passcolor4f_vertexbuffer = 0;
9306         rsurface.passcolor4f_bufferoffset = 0;
9307         for (i = 0;i < rsurface.batchnumvertices;i++)
9308                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9309 }
9310
9311 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9312 {
9313         int i;
9314         float f;
9315         const float *v;
9316         const float *c;
9317         float *c2;
9318         if (rsurface.passcolor4f)
9319         {
9320                 // generate color arrays
9321                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9322                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9323                 rsurface.passcolor4f_vertexbuffer = 0;
9324                 rsurface.passcolor4f_bufferoffset = 0;
9325                 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)
9326                 {
9327                         f = RSurf_FogVertex(v);
9328                         c2[0] = c[0] * f;
9329                         c2[1] = c[1] * f;
9330                         c2[2] = c[2] * f;
9331                         c2[3] = c[3];
9332                 }
9333         }
9334         else
9335         {
9336                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9337                 rsurface.passcolor4f_vertexbuffer = 0;
9338                 rsurface.passcolor4f_bufferoffset = 0;
9339                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9340                 {
9341                         f = RSurf_FogVertex(v);
9342                         c2[0] = f;
9343                         c2[1] = f;
9344                         c2[2] = f;
9345                         c2[3] = 1;
9346                 }
9347         }
9348 }
9349
9350 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9351 {
9352         int i;
9353         float f;
9354         const float *v;
9355         const float *c;
9356         float *c2;
9357         if (!rsurface.passcolor4f)
9358                 return;
9359         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9360         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9361         rsurface.passcolor4f_vertexbuffer = 0;
9362         rsurface.passcolor4f_bufferoffset = 0;
9363         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)
9364         {
9365                 f = RSurf_FogVertex(v);
9366                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9367                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9368                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9369                 c2[3] = c[3];
9370         }
9371 }
9372
9373 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9374 {
9375         int i;
9376         const float *c;
9377         float *c2;
9378         if (!rsurface.passcolor4f)
9379                 return;
9380         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9381         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9382         rsurface.passcolor4f_vertexbuffer = 0;
9383         rsurface.passcolor4f_bufferoffset = 0;
9384         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9385         {
9386                 c2[0] = c[0] * r;
9387                 c2[1] = c[1] * g;
9388                 c2[2] = c[2] * b;
9389                 c2[3] = c[3] * a;
9390         }
9391 }
9392
9393 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9394 {
9395         int i;
9396         const float *c;
9397         float *c2;
9398         if (!rsurface.passcolor4f)
9399                 return;
9400         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9401         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9402         rsurface.passcolor4f_vertexbuffer = 0;
9403         rsurface.passcolor4f_bufferoffset = 0;
9404         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9405         {
9406                 c2[0] = c[0] + r_refdef.scene.ambient;
9407                 c2[1] = c[1] + r_refdef.scene.ambient;
9408                 c2[2] = c[2] + r_refdef.scene.ambient;
9409                 c2[3] = c[3];
9410         }
9411 }
9412
9413 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9414 {
9415         // TODO: optimize
9416         rsurface.passcolor4f = NULL;
9417         rsurface.passcolor4f_vertexbuffer = 0;
9418         rsurface.passcolor4f_bufferoffset = 0;
9419         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9420         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9421         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9422         GL_Color(r, g, b, a);
9423         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9424         RSurf_DrawBatch();
9425 }
9426
9427 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9428 {
9429         // TODO: optimize applyfog && applycolor case
9430         // just apply fog if necessary, and tint the fog color array if necessary
9431         rsurface.passcolor4f = NULL;
9432         rsurface.passcolor4f_vertexbuffer = 0;
9433         rsurface.passcolor4f_bufferoffset = 0;
9434         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9435         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9436         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9437         GL_Color(r, g, b, a);
9438         RSurf_DrawBatch();
9439 }
9440
9441 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9442 {
9443         // TODO: optimize
9444         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9445         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9446         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9447         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9448         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9449         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9450         GL_Color(r, g, b, a);
9451         RSurf_DrawBatch();
9452 }
9453
9454 static void RSurf_DrawBatch_GL11_ClampColor(void)
9455 {
9456         int i;
9457         const float *c1;
9458         float *c2;
9459         if (!rsurface.passcolor4f)
9460                 return;
9461         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9462         {
9463                 c2[0] = bound(0.0f, c1[0], 1.0f);
9464                 c2[1] = bound(0.0f, c1[1], 1.0f);
9465                 c2[2] = bound(0.0f, c1[2], 1.0f);
9466                 c2[3] = bound(0.0f, c1[3], 1.0f);
9467         }
9468 }
9469
9470 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9471 {
9472         int i;
9473         float f;
9474         const float *v;
9475         const float *n;
9476         float *c;
9477         //vec3_t eyedir;
9478
9479         // fake shading
9480         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9481         rsurface.passcolor4f_vertexbuffer = 0;
9482         rsurface.passcolor4f_bufferoffset = 0;
9483         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)
9484         {
9485                 f = -DotProduct(r_refdef.view.forward, n);
9486                 f = max(0, f);
9487                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9488                 f *= r_refdef.lightmapintensity;
9489                 Vector4Set(c, f, f, f, 1);
9490         }
9491 }
9492
9493 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9494 {
9495         RSurf_DrawBatch_GL11_ApplyFakeLight();
9496         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9497         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9498         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9499         GL_Color(r, g, b, a);
9500         RSurf_DrawBatch();
9501 }
9502
9503 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9504 {
9505         int i;
9506         float f;
9507         float alpha;
9508         const float *v;
9509         const float *n;
9510         float *c;
9511         vec3_t ambientcolor;
9512         vec3_t diffusecolor;
9513         vec3_t lightdir;
9514         // TODO: optimize
9515         // model lighting
9516         VectorCopy(rsurface.modellight_lightdir, lightdir);
9517         f = 0.5f * r_refdef.lightmapintensity;
9518         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9519         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9520         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9521         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9522         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9523         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9524         alpha = *a;
9525         if (VectorLength2(diffusecolor) > 0)
9526         {
9527                 // q3-style directional shading
9528                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9529                 rsurface.passcolor4f_vertexbuffer = 0;
9530                 rsurface.passcolor4f_bufferoffset = 0;
9531                 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)
9532                 {
9533                         if ((f = DotProduct(n, lightdir)) > 0)
9534                                 VectorMA(ambientcolor, f, diffusecolor, c);
9535                         else
9536                                 VectorCopy(ambientcolor, c);
9537                         c[3] = alpha;
9538                 }
9539                 *r = 1;
9540                 *g = 1;
9541                 *b = 1;
9542                 *a = 1;
9543                 *applycolor = false;
9544         }
9545         else
9546         {
9547                 *r = ambientcolor[0];
9548                 *g = ambientcolor[1];
9549                 *b = ambientcolor[2];
9550                 rsurface.passcolor4f = NULL;
9551                 rsurface.passcolor4f_vertexbuffer = 0;
9552                 rsurface.passcolor4f_bufferoffset = 0;
9553         }
9554 }
9555
9556 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9557 {
9558         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9559         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9560         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9561         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9562         GL_Color(r, g, b, a);
9563         RSurf_DrawBatch();
9564 }
9565
9566 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9567 {
9568         int i;
9569         float f;
9570         const float *v;
9571         float *c;
9572
9573         // fake shading
9574         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9575         rsurface.passcolor4f_vertexbuffer = 0;
9576         rsurface.passcolor4f_bufferoffset = 0;
9577
9578         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9579         {
9580                 f = 1 - RSurf_FogVertex(v);
9581                 c[0] = r;
9582                 c[1] = g;
9583                 c[2] = b;
9584                 c[3] = f * a;
9585         }
9586 }
9587
9588 void RSurf_SetupDepthAndCulling(void)
9589 {
9590         // submodels are biased to avoid z-fighting with world surfaces that they
9591         // may be exactly overlapping (avoids z-fighting artifacts on certain
9592         // doors and things in Quake maps)
9593         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9594         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9595         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9596         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9597 }
9598
9599 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9600 {
9601         // transparent sky would be ridiculous
9602         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9603                 return;
9604         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9605         skyrenderlater = true;
9606         RSurf_SetupDepthAndCulling();
9607         GL_DepthMask(true);
9608         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9609         // skymasking on them, and Quake3 never did sky masking (unlike
9610         // software Quake and software Quake2), so disable the sky masking
9611         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9612         // and skymasking also looks very bad when noclipping outside the
9613         // level, so don't use it then either.
9614         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9615         {
9616                 R_Mesh_ResetTextureState();
9617                 if (skyrendermasked)
9618                 {
9619                         R_SetupShader_DepthOrShadow(false);
9620                         // depth-only (masking)
9621                         GL_ColorMask(0,0,0,0);
9622                         // just to make sure that braindead drivers don't draw
9623                         // anything despite that colormask...
9624                         GL_BlendFunc(GL_ZERO, GL_ONE);
9625                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9626                         if (rsurface.batchvertex3fbuffer)
9627                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9628                         else
9629                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9630                 }
9631                 else
9632                 {
9633                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9634                         // fog sky
9635                         GL_BlendFunc(GL_ONE, GL_ZERO);
9636                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9637                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9638                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9639                 }
9640                 RSurf_DrawBatch();
9641                 if (skyrendermasked)
9642                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9643         }
9644         R_Mesh_ResetTextureState();
9645         GL_Color(1, 1, 1, 1);
9646 }
9647
9648 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9649 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9650 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9651 {
9652         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9653                 return;
9654         if (prepass)
9655         {
9656                 // render screenspace normalmap to texture
9657                 GL_DepthMask(true);
9658                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9659                 RSurf_DrawBatch();
9660         }
9661
9662         // bind lightmap texture
9663
9664         // water/refraction/reflection/camera surfaces have to be handled specially
9665         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9666         {
9667                 int start, end, startplaneindex;
9668                 for (start = 0;start < texturenumsurfaces;start = end)
9669                 {
9670                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9671                         if(startplaneindex < 0)
9672                         {
9673                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9674                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9675                                 end = start + 1;
9676                                 continue;
9677                         }
9678                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9679                                 ;
9680                         // now that we have a batch using the same planeindex, render it
9681                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9682                         {
9683                                 // render water or distortion background
9684                                 GL_DepthMask(true);
9685                                 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), false);
9686                                 RSurf_DrawBatch();
9687                                 // blend surface on top
9688                                 GL_DepthMask(false);
9689                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9690                                 RSurf_DrawBatch();
9691                         }
9692                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9693                         {
9694                                 // render surface with reflection texture as input
9695                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9696                                 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), false);
9697                                 RSurf_DrawBatch();
9698                         }
9699                 }
9700                 return;
9701         }
9702
9703         // render surface batch normally
9704         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9705         R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, texturenumsurfaces, texturesurfacelist, NULL, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) != 0);
9706         RSurf_DrawBatch();
9707 }
9708
9709 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9710 {
9711         // OpenGL 1.3 path - anything not completely ancient
9712         qboolean applycolor;
9713         qboolean applyfog;
9714         int layerindex;
9715         const texturelayer_t *layer;
9716         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);
9717         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9718
9719         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9720         {
9721                 vec4_t layercolor;
9722                 int layertexrgbscale;
9723                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9724                 {
9725                         if (layerindex == 0)
9726                                 GL_AlphaTest(true);
9727                         else
9728                         {
9729                                 GL_AlphaTest(false);
9730                                 GL_DepthFunc(GL_EQUAL);
9731                         }
9732                 }
9733                 GL_DepthMask(layer->depthmask && writedepth);
9734                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9735                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9736                 {
9737                         layertexrgbscale = 4;
9738                         VectorScale(layer->color, 0.25f, layercolor);
9739                 }
9740                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9741                 {
9742                         layertexrgbscale = 2;
9743                         VectorScale(layer->color, 0.5f, layercolor);
9744                 }
9745                 else
9746                 {
9747                         layertexrgbscale = 1;
9748                         VectorScale(layer->color, 1.0f, layercolor);
9749                 }
9750                 layercolor[3] = layer->color[3];
9751                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9752                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9753                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9754                 switch (layer->type)
9755                 {
9756                 case TEXTURELAYERTYPE_LITTEXTURE:
9757                         // single-pass lightmapped texture with 2x rgbscale
9758                         R_Mesh_TexBind(0, r_texture_white);
9759                         R_Mesh_TexMatrix(0, NULL);
9760                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9761                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9762                         R_Mesh_TexBind(1, layer->texture);
9763                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9764                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9765                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9766                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9767                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9768                         else if (FAKELIGHT_ENABLED)
9769                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9770                         else if (rsurface.uselightmaptexture)
9771                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9772                         else
9773                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9774                         break;
9775                 case TEXTURELAYERTYPE_TEXTURE:
9776                         // singletexture unlit texture with transparency support
9777                         R_Mesh_TexBind(0, layer->texture);
9778                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9779                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9780                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9781                         R_Mesh_TexBind(1, 0);
9782                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9783                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9784                         break;
9785                 case TEXTURELAYERTYPE_FOG:
9786                         // singletexture fogging
9787                         if (layer->texture)
9788                         {
9789                                 R_Mesh_TexBind(0, layer->texture);
9790                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9791                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9792                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9793                         }
9794                         else
9795                         {
9796                                 R_Mesh_TexBind(0, 0);
9797                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9798                         }
9799                         R_Mesh_TexBind(1, 0);
9800                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9801                         // generate a color array for the fog pass
9802                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9803                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9804                         RSurf_DrawBatch();
9805                         break;
9806                 default:
9807                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9808                 }
9809         }
9810         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9811         {
9812                 GL_DepthFunc(GL_LEQUAL);
9813                 GL_AlphaTest(false);
9814         }
9815 }
9816
9817 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9818 {
9819         // OpenGL 1.1 - crusty old voodoo path
9820         qboolean applyfog;
9821         int layerindex;
9822         const texturelayer_t *layer;
9823         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);
9824         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9825
9826         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9827         {
9828                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9829                 {
9830                         if (layerindex == 0)
9831                                 GL_AlphaTest(true);
9832                         else
9833                         {
9834                                 GL_AlphaTest(false);
9835                                 GL_DepthFunc(GL_EQUAL);
9836                         }
9837                 }
9838                 GL_DepthMask(layer->depthmask && writedepth);
9839                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9840                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9841                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9842                 switch (layer->type)
9843                 {
9844                 case TEXTURELAYERTYPE_LITTEXTURE:
9845                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9846                         {
9847                                 // two-pass lit texture with 2x rgbscale
9848                                 // first the lightmap pass
9849                                 R_Mesh_TexBind(0, r_texture_white);
9850                                 R_Mesh_TexMatrix(0, NULL);
9851                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9852                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9853                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9854                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9855                                 else if (FAKELIGHT_ENABLED)
9856                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9857                                 else if (rsurface.uselightmaptexture)
9858                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9859                                 else
9860                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9861                                 // then apply the texture to it
9862                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9863                                 R_Mesh_TexBind(0, layer->texture);
9864                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9865                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9866                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9867                                 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);
9868                         }
9869                         else
9870                         {
9871                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9872                                 R_Mesh_TexBind(0, layer->texture);
9873                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9874                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9875                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9876                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9877                                         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);
9878                                 else
9879                                         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);
9880                         }
9881                         break;
9882                 case TEXTURELAYERTYPE_TEXTURE:
9883                         // singletexture unlit texture with transparency support
9884                         R_Mesh_TexBind(0, layer->texture);
9885                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9886                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9887                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9888                         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);
9889                         break;
9890                 case TEXTURELAYERTYPE_FOG:
9891                         // singletexture fogging
9892                         if (layer->texture)
9893                         {
9894                                 R_Mesh_TexBind(0, layer->texture);
9895                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9896                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9897                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9898                         }
9899                         else
9900                         {
9901                                 R_Mesh_TexBind(0, 0);
9902                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9903                         }
9904                         // generate a color array for the fog pass
9905                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9906                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9907                         RSurf_DrawBatch();
9908                         break;
9909                 default:
9910                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9911                 }
9912         }
9913         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9914         {
9915                 GL_DepthFunc(GL_LEQUAL);
9916                 GL_AlphaTest(false);
9917         }
9918 }
9919
9920 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9921 {
9922         int vi;
9923         int j;
9924         r_vertexgeneric_t *batchvertex;
9925         float c[4];
9926
9927 //      R_Mesh_ResetTextureState();
9928         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9929
9930         if(rsurface.texture && rsurface.texture->currentskinframe)
9931         {
9932                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9933                 c[3] *= rsurface.texture->currentalpha;
9934         }
9935         else
9936         {
9937                 c[0] = 1;
9938                 c[1] = 0;
9939                 c[2] = 1;
9940                 c[3] = 1;
9941         }
9942
9943         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9944         {
9945                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9946                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9947                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9948         }
9949
9950         // brighten it up (as texture value 127 means "unlit")
9951         c[0] *= 2 * r_refdef.view.colorscale;
9952         c[1] *= 2 * r_refdef.view.colorscale;
9953         c[2] *= 2 * r_refdef.view.colorscale;
9954
9955         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9956                 c[3] *= r_wateralpha.value;
9957
9958         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9959         {
9960                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9961                 GL_DepthMask(false);
9962         }
9963         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9964         {
9965                 GL_BlendFunc(GL_ONE, GL_ONE);
9966                 GL_DepthMask(false);
9967         }
9968         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9969         {
9970                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9971                 GL_DepthMask(false);
9972         }
9973         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9974         {
9975                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9976                 GL_DepthMask(false);
9977         }
9978         else
9979         {
9980                 GL_BlendFunc(GL_ONE, GL_ZERO);
9981                 GL_DepthMask(writedepth);
9982         }
9983
9984         if (r_showsurfaces.integer == 3)
9985         {
9986                 rsurface.passcolor4f = NULL;
9987
9988                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9989                 {
9990                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9991
9992                         rsurface.passcolor4f = NULL;
9993                         rsurface.passcolor4f_vertexbuffer = 0;
9994                         rsurface.passcolor4f_bufferoffset = 0;
9995                 }
9996                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9997                 {
9998                         qboolean applycolor = true;
9999                         float one = 1.0;
10000
10001                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10002
10003                         r_refdef.lightmapintensity = 1;
10004                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10005                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10006                 }
10007                 else if (FAKELIGHT_ENABLED)
10008                 {
10009                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10010
10011                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10012                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10013                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10014                 }
10015                 else
10016                 {
10017                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10018
10019                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10020                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10021                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10022                 }
10023
10024                 if(!rsurface.passcolor4f)
10025                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10026
10027                 RSurf_DrawBatch_GL11_ApplyAmbient();
10028                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10029                 if(r_refdef.fogenabled)
10030                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10031                 RSurf_DrawBatch_GL11_ClampColor();
10032
10033                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10034                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10035                 RSurf_DrawBatch();
10036         }
10037         else if (!r_refdef.view.showdebug)
10038         {
10039                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10040                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10041                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10042                 {
10043                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10044                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10045                 }
10046                 R_Mesh_PrepareVertices_Generic_Unlock();
10047                 RSurf_DrawBatch();
10048         }
10049         else if (r_showsurfaces.integer == 4)
10050         {
10051                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10052                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10053                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10054                 {
10055                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10056                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10057                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10058                 }
10059                 R_Mesh_PrepareVertices_Generic_Unlock();
10060                 RSurf_DrawBatch();
10061         }
10062         else if (r_showsurfaces.integer == 2)
10063         {
10064                 const int *e;
10065                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10066                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10067                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10068                 {
10069                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10070                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10071                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10072                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10073                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10074                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10075                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10076                 }
10077                 R_Mesh_PrepareVertices_Generic_Unlock();
10078                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10079         }
10080         else
10081         {
10082                 int texturesurfaceindex;
10083                 int k;
10084                 const msurface_t *surface;
10085                 float surfacecolor4f[4];
10086                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10087                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10088                 vi = 0;
10089                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10090                 {
10091                         surface = texturesurfacelist[texturesurfaceindex];
10092                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10093                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10094                         for (j = 0;j < surface->num_vertices;j++)
10095                         {
10096                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10097                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10098                                 vi++;
10099                         }
10100                 }
10101                 R_Mesh_PrepareVertices_Generic_Unlock();
10102                 RSurf_DrawBatch();
10103         }
10104 }
10105
10106 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10107 {
10108         CHECKGLERROR
10109         RSurf_SetupDepthAndCulling();
10110         if (r_showsurfaces.integer)
10111         {
10112                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10113                 return;
10114         }
10115         switch (vid.renderpath)
10116         {
10117         case RENDERPATH_GL20:
10118         case RENDERPATH_D3D9:
10119         case RENDERPATH_D3D10:
10120         case RENDERPATH_D3D11:
10121         case RENDERPATH_SOFT:
10122         case RENDERPATH_GLES2:
10123                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10124                 break;
10125         case RENDERPATH_GL13:
10126         case RENDERPATH_GLES1:
10127                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10128                 break;
10129         case RENDERPATH_GL11:
10130                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10131                 break;
10132         }
10133         CHECKGLERROR
10134 }
10135
10136 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10137 {
10138         CHECKGLERROR
10139         RSurf_SetupDepthAndCulling();
10140         if (r_showsurfaces.integer)
10141         {
10142                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10143                 return;
10144         }
10145         switch (vid.renderpath)
10146         {
10147         case RENDERPATH_GL20:
10148         case RENDERPATH_D3D9:
10149         case RENDERPATH_D3D10:
10150         case RENDERPATH_D3D11:
10151         case RENDERPATH_SOFT:
10152         case RENDERPATH_GLES2:
10153                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10154                 break;
10155         case RENDERPATH_GL13:
10156         case RENDERPATH_GLES1:
10157                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10158                 break;
10159         case RENDERPATH_GL11:
10160                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10161                 break;
10162         }
10163         CHECKGLERROR
10164 }
10165
10166 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10167 {
10168         int i, j;
10169         int texturenumsurfaces, endsurface;
10170         texture_t *texture;
10171         const msurface_t *surface;
10172         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10173
10174         // if the model is static it doesn't matter what value we give for
10175         // wantnormals and wanttangents, so this logic uses only rules applicable
10176         // to a model, knowing that they are meaningless otherwise
10177         if (ent == r_refdef.scene.worldentity)
10178                 RSurf_ActiveWorldEntity();
10179         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10180                 RSurf_ActiveModelEntity(ent, false, false, false);
10181         else
10182         {
10183                 switch (vid.renderpath)
10184                 {
10185                 case RENDERPATH_GL20:
10186                 case RENDERPATH_D3D9:
10187                 case RENDERPATH_D3D10:
10188                 case RENDERPATH_D3D11:
10189                 case RENDERPATH_SOFT:
10190                 case RENDERPATH_GLES2:
10191                         RSurf_ActiveModelEntity(ent, true, true, false);
10192                         break;
10193                 case RENDERPATH_GL11:
10194                 case RENDERPATH_GL13:
10195                 case RENDERPATH_GLES1:
10196                         RSurf_ActiveModelEntity(ent, true, false, false);
10197                         break;
10198                 }
10199         }
10200
10201         if (r_transparentdepthmasking.integer)
10202         {
10203                 qboolean setup = false;
10204                 for (i = 0;i < numsurfaces;i = j)
10205                 {
10206                         j = i + 1;
10207                         surface = rsurface.modelsurfaces + surfacelist[i];
10208                         texture = surface->texture;
10209                         rsurface.texture = R_GetCurrentTexture(texture);
10210                         rsurface.lightmaptexture = NULL;
10211                         rsurface.deluxemaptexture = NULL;
10212                         rsurface.uselightmaptexture = false;
10213                         // scan ahead until we find a different texture
10214                         endsurface = min(i + 1024, numsurfaces);
10215                         texturenumsurfaces = 0;
10216                         texturesurfacelist[texturenumsurfaces++] = surface;
10217                         for (;j < endsurface;j++)
10218                         {
10219                                 surface = rsurface.modelsurfaces + surfacelist[j];
10220                                 if (texture != surface->texture)
10221                                         break;
10222                                 texturesurfacelist[texturenumsurfaces++] = surface;
10223                         }
10224                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10225                                 continue;
10226                         // render the range of surfaces as depth
10227                         if (!setup)
10228                         {
10229                                 setup = true;
10230                                 GL_ColorMask(0,0,0,0);
10231                                 GL_Color(1,1,1,1);
10232                                 GL_DepthTest(true);
10233                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10234                                 GL_DepthMask(true);
10235 //                              R_Mesh_ResetTextureState();
10236                                 R_SetupShader_DepthOrShadow(false);
10237                         }
10238                         RSurf_SetupDepthAndCulling();
10239                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10240                         if (rsurface.batchvertex3fbuffer)
10241                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10242                         else
10243                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10244                         RSurf_DrawBatch();
10245                 }
10246                 if (setup)
10247                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10248         }
10249
10250         for (i = 0;i < numsurfaces;i = j)
10251         {
10252                 j = i + 1;
10253                 surface = rsurface.modelsurfaces + surfacelist[i];
10254                 texture = surface->texture;
10255                 rsurface.texture = R_GetCurrentTexture(texture);
10256                 // scan ahead until we find a different texture
10257                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10258                 texturenumsurfaces = 0;
10259                 texturesurfacelist[texturenumsurfaces++] = surface;
10260                 if(FAKELIGHT_ENABLED)
10261                 {
10262                         rsurface.lightmaptexture = NULL;
10263                         rsurface.deluxemaptexture = NULL;
10264                         rsurface.uselightmaptexture = false;
10265                         for (;j < endsurface;j++)
10266                         {
10267                                 surface = rsurface.modelsurfaces + surfacelist[j];
10268                                 if (texture != surface->texture)
10269                                         break;
10270                                 texturesurfacelist[texturenumsurfaces++] = surface;
10271                         }
10272                 }
10273                 else
10274                 {
10275                         rsurface.lightmaptexture = surface->lightmaptexture;
10276                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10277                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10278                         for (;j < endsurface;j++)
10279                         {
10280                                 surface = rsurface.modelsurfaces + surfacelist[j];
10281                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10282                                         break;
10283                                 texturesurfacelist[texturenumsurfaces++] = surface;
10284                         }
10285                 }
10286                 // render the range of surfaces
10287                 if (ent == r_refdef.scene.worldentity)
10288                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10289                 else
10290                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10291         }
10292         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10293 }
10294
10295 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10296 {
10297         // transparent surfaces get pushed off into the transparent queue
10298         int surfacelistindex;
10299         const msurface_t *surface;
10300         vec3_t tempcenter, center;
10301         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10302         {
10303                 surface = texturesurfacelist[surfacelistindex];
10304                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10305                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10306                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10307                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10308                 if (queueentity->transparent_offset) // transparent offset
10309                 {
10310                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10311                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10312                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10313                 }
10314                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10315         }
10316 }
10317
10318 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10319 {
10320         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10321                 return;
10322         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10323                 return;
10324         RSurf_SetupDepthAndCulling();
10325         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10326         if (rsurface.batchvertex3fbuffer)
10327                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10328         else
10329                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10330         RSurf_DrawBatch();
10331 }
10332
10333 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10334 {
10335         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10336         CHECKGLERROR
10337         if (depthonly)
10338                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10339         else if (prepass)
10340         {
10341                 if (!rsurface.texture->currentnumlayers)
10342                         return;
10343                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10344                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10345                 else
10346                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10347         }
10348         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10349                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10350         else if (!rsurface.texture->currentnumlayers)
10351                 return;
10352         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10353         {
10354                 // in the deferred case, transparent surfaces were queued during prepass
10355                 if (!r_shadow_usingdeferredprepass)
10356                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10357         }
10358         else
10359         {
10360                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10361                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10362         }
10363         CHECKGLERROR
10364 }
10365
10366 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10367 {
10368         int i, j;
10369         texture_t *texture;
10370         R_FrameData_SetMark();
10371         // break the surface list down into batches by texture and use of lightmapping
10372         for (i = 0;i < numsurfaces;i = j)
10373         {
10374                 j = i + 1;
10375                 // texture is the base texture pointer, rsurface.texture is the
10376                 // current frame/skin the texture is directing us to use (for example
10377                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10378                 // use skin 1 instead)
10379                 texture = surfacelist[i]->texture;
10380                 rsurface.texture = R_GetCurrentTexture(texture);
10381                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10382                 {
10383                         // if this texture is not the kind we want, skip ahead to the next one
10384                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10385                                 ;
10386                         continue;
10387                 }
10388                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10389                 {
10390                         rsurface.lightmaptexture = NULL;
10391                         rsurface.deluxemaptexture = NULL;
10392                         rsurface.uselightmaptexture = false;
10393                         // simply scan ahead until we find a different texture or lightmap state
10394                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10395                                 ;
10396                 }
10397                 else
10398                 {
10399                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10400                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10401                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10402                         // simply scan ahead until we find a different texture or lightmap state
10403                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10404                                 ;
10405                 }
10406                 // render the range of surfaces
10407                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10408         }
10409         R_FrameData_ReturnToMark();
10410 }
10411
10412 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10413 {
10414         CHECKGLERROR
10415         if (depthonly)
10416                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10417         else if (prepass)
10418         {
10419                 if (!rsurface.texture->currentnumlayers)
10420                         return;
10421                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10422                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10423                 else
10424                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10425         }
10426         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10427                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10428         else if (!rsurface.texture->currentnumlayers)
10429                 return;
10430         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10431         {
10432                 // in the deferred case, transparent surfaces were queued during prepass
10433                 if (!r_shadow_usingdeferredprepass)
10434                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10435         }
10436         else
10437         {
10438                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10439                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10440         }
10441         CHECKGLERROR
10442 }
10443
10444 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10445 {
10446         int i, j;
10447         texture_t *texture;
10448         R_FrameData_SetMark();
10449         // break the surface list down into batches by texture and use of lightmapping
10450         for (i = 0;i < numsurfaces;i = j)
10451         {
10452                 j = i + 1;
10453                 // texture is the base texture pointer, rsurface.texture is the
10454                 // current frame/skin the texture is directing us to use (for example
10455                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10456                 // use skin 1 instead)
10457                 texture = surfacelist[i]->texture;
10458                 rsurface.texture = R_GetCurrentTexture(texture);
10459                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10460                 {
10461                         // if this texture is not the kind we want, skip ahead to the next one
10462                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10463                                 ;
10464                         continue;
10465                 }
10466                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10467                 {
10468                         rsurface.lightmaptexture = NULL;
10469                         rsurface.deluxemaptexture = NULL;
10470                         rsurface.uselightmaptexture = false;
10471                         // simply scan ahead until we find a different texture or lightmap state
10472                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10473                                 ;
10474                 }
10475                 else
10476                 {
10477                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10478                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10479                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10480                         // simply scan ahead until we find a different texture or lightmap state
10481                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10482                                 ;
10483                 }
10484                 // render the range of surfaces
10485                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10486         }
10487         R_FrameData_ReturnToMark();
10488 }
10489
10490 float locboxvertex3f[6*4*3] =
10491 {
10492         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10493         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10494         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10495         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10496         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10497         1,0,0, 0,0,0, 0,1,0, 1,1,0
10498 };
10499
10500 unsigned short locboxelements[6*2*3] =
10501 {
10502          0, 1, 2, 0, 2, 3,
10503          4, 5, 6, 4, 6, 7,
10504          8, 9,10, 8,10,11,
10505         12,13,14, 12,14,15,
10506         16,17,18, 16,18,19,
10507         20,21,22, 20,22,23
10508 };
10509
10510 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10511 {
10512         int i, j;
10513         cl_locnode_t *loc = (cl_locnode_t *)ent;
10514         vec3_t mins, size;
10515         float vertex3f[6*4*3];
10516         CHECKGLERROR
10517         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10518         GL_DepthMask(false);
10519         GL_DepthRange(0, 1);
10520         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10521         GL_DepthTest(true);
10522         GL_CullFace(GL_NONE);
10523         R_EntityMatrix(&identitymatrix);
10524
10525 //      R_Mesh_ResetTextureState();
10526
10527         i = surfacelist[0];
10528         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10529                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10530                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10531                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10532
10533         if (VectorCompare(loc->mins, loc->maxs))
10534         {
10535                 VectorSet(size, 2, 2, 2);
10536                 VectorMA(loc->mins, -0.5f, size, mins);
10537         }
10538         else
10539         {
10540                 VectorCopy(loc->mins, mins);
10541                 VectorSubtract(loc->maxs, loc->mins, size);
10542         }
10543
10544         for (i = 0;i < 6*4*3;)
10545                 for (j = 0;j < 3;j++, i++)
10546                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10547
10548         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10549         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10550         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10551 }
10552
10553 void R_DrawLocs(void)
10554 {
10555         int index;
10556         cl_locnode_t *loc, *nearestloc;
10557         vec3_t center;
10558         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10559         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10560         {
10561                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10562                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10563         }
10564 }
10565
10566 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10567 {
10568         if (decalsystem->decals)
10569                 Mem_Free(decalsystem->decals);
10570         memset(decalsystem, 0, sizeof(*decalsystem));
10571 }
10572
10573 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)
10574 {
10575         tridecal_t *decal;
10576         tridecal_t *decals;
10577         int i;
10578
10579         // expand or initialize the system
10580         if (decalsystem->maxdecals <= decalsystem->numdecals)
10581         {
10582                 decalsystem_t old = *decalsystem;
10583                 qboolean useshortelements;
10584                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10585                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10586                 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)));
10587                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10588                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10589                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10590                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10591                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10592                 if (decalsystem->numdecals)
10593                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10594                 if (old.decals)
10595                         Mem_Free(old.decals);
10596                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10597                         decalsystem->element3i[i] = i;
10598                 if (useshortelements)
10599                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10600                                 decalsystem->element3s[i] = i;
10601         }
10602
10603         // grab a decal and search for another free slot for the next one
10604         decals = decalsystem->decals;
10605         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10606         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10607                 ;
10608         decalsystem->freedecal = i;
10609         if (decalsystem->numdecals <= i)
10610                 decalsystem->numdecals = i + 1;
10611
10612         // initialize the decal
10613         decal->lived = 0;
10614         decal->triangleindex = triangleindex;
10615         decal->surfaceindex = surfaceindex;
10616         decal->decalsequence = decalsequence;
10617         decal->color4f[0][0] = c0[0];
10618         decal->color4f[0][1] = c0[1];
10619         decal->color4f[0][2] = c0[2];
10620         decal->color4f[0][3] = 1;
10621         decal->color4f[1][0] = c1[0];
10622         decal->color4f[1][1] = c1[1];
10623         decal->color4f[1][2] = c1[2];
10624         decal->color4f[1][3] = 1;
10625         decal->color4f[2][0] = c2[0];
10626         decal->color4f[2][1] = c2[1];
10627         decal->color4f[2][2] = c2[2];
10628         decal->color4f[2][3] = 1;
10629         decal->vertex3f[0][0] = v0[0];
10630         decal->vertex3f[0][1] = v0[1];
10631         decal->vertex3f[0][2] = v0[2];
10632         decal->vertex3f[1][0] = v1[0];
10633         decal->vertex3f[1][1] = v1[1];
10634         decal->vertex3f[1][2] = v1[2];
10635         decal->vertex3f[2][0] = v2[0];
10636         decal->vertex3f[2][1] = v2[1];
10637         decal->vertex3f[2][2] = v2[2];
10638         decal->texcoord2f[0][0] = t0[0];
10639         decal->texcoord2f[0][1] = t0[1];
10640         decal->texcoord2f[1][0] = t1[0];
10641         decal->texcoord2f[1][1] = t1[1];
10642         decal->texcoord2f[2][0] = t2[0];
10643         decal->texcoord2f[2][1] = t2[1];
10644         TriangleNormal(v0, v1, v2, decal->plane);
10645         VectorNormalize(decal->plane);
10646         decal->plane[3] = DotProduct(v0, decal->plane);
10647 }
10648
10649 extern cvar_t cl_decals_bias;
10650 extern cvar_t cl_decals_models;
10651 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10652 // baseparms, parms, temps
10653 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)
10654 {
10655         int cornerindex;
10656         int index;
10657         float v[9][3];
10658         const float *vertex3f;
10659         const float *normal3f;
10660         int numpoints;
10661         float points[2][9][3];
10662         float temp[3];
10663         float tc[9][2];
10664         float f;
10665         float c[9][4];
10666         const int *e;
10667
10668         e = rsurface.modelelement3i + 3*triangleindex;
10669
10670         vertex3f = rsurface.modelvertex3f;
10671         normal3f = rsurface.modelnormal3f;
10672
10673         if (normal3f)
10674         {
10675                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10676                 {
10677                         index = 3*e[cornerindex];
10678                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10679                 }
10680         }
10681         else
10682         {
10683                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10684                 {
10685                         index = 3*e[cornerindex];
10686                         VectorCopy(vertex3f + index, v[cornerindex]);
10687                 }
10688         }
10689
10690         // cull backfaces
10691         //TriangleNormal(v[0], v[1], v[2], normal);
10692         //if (DotProduct(normal, localnormal) < 0.0f)
10693         //      continue;
10694         // clip by each of the box planes formed from the projection matrix
10695         // if anything survives, we emit the decal
10696         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]);
10697         if (numpoints < 3)
10698                 return;
10699         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]);
10700         if (numpoints < 3)
10701                 return;
10702         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]);
10703         if (numpoints < 3)
10704                 return;
10705         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]);
10706         if (numpoints < 3)
10707                 return;
10708         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]);
10709         if (numpoints < 3)
10710                 return;
10711         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]);
10712         if (numpoints < 3)
10713                 return;
10714         // some part of the triangle survived, so we have to accept it...
10715         if (dynamic)
10716         {
10717                 // dynamic always uses the original triangle
10718                 numpoints = 3;
10719                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10720                 {
10721                         index = 3*e[cornerindex];
10722                         VectorCopy(vertex3f + index, v[cornerindex]);
10723                 }
10724         }
10725         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10726         {
10727                 // convert vertex positions to texcoords
10728                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10729                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10730                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10731                 // calculate distance fade from the projection origin
10732                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10733                 f = bound(0.0f, f, 1.0f);
10734                 c[cornerindex][0] = r * f;
10735                 c[cornerindex][1] = g * f;
10736                 c[cornerindex][2] = b * f;
10737                 c[cornerindex][3] = 1.0f;
10738                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10739         }
10740         if (dynamic)
10741                 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);
10742         else
10743                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10744                         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);
10745 }
10746 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)
10747 {
10748         matrix4x4_t projection;
10749         decalsystem_t *decalsystem;
10750         qboolean dynamic;
10751         dp_model_t *model;
10752         const msurface_t *surface;
10753         const msurface_t *surfaces;
10754         const int *surfacelist;
10755         const texture_t *texture;
10756         int numtriangles;
10757         int numsurfacelist;
10758         int surfacelistindex;
10759         int surfaceindex;
10760         int triangleindex;
10761         float localorigin[3];
10762         float localnormal[3];
10763         float localmins[3];
10764         float localmaxs[3];
10765         float localsize;
10766         //float normal[3];
10767         float planes[6][4];
10768         float angles[3];
10769         bih_t *bih;
10770         int bih_triangles_count;
10771         int bih_triangles[256];
10772         int bih_surfaces[256];
10773
10774         decalsystem = &ent->decalsystem;
10775         model = ent->model;
10776         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10777         {
10778                 R_DecalSystem_Reset(&ent->decalsystem);
10779                 return;
10780         }
10781
10782         if (!model->brush.data_leafs && !cl_decals_models.integer)
10783         {
10784                 if (decalsystem->model)
10785                         R_DecalSystem_Reset(decalsystem);
10786                 return;
10787         }
10788
10789         if (decalsystem->model != model)
10790                 R_DecalSystem_Reset(decalsystem);
10791         decalsystem->model = model;
10792
10793         RSurf_ActiveModelEntity(ent, true, false, false);
10794
10795         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10796         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10797         VectorNormalize(localnormal);
10798         localsize = worldsize*rsurface.inversematrixscale;
10799         localmins[0] = localorigin[0] - localsize;
10800         localmins[1] = localorigin[1] - localsize;
10801         localmins[2] = localorigin[2] - localsize;
10802         localmaxs[0] = localorigin[0] + localsize;
10803         localmaxs[1] = localorigin[1] + localsize;
10804         localmaxs[2] = localorigin[2] + localsize;
10805
10806         //VectorCopy(localnormal, planes[4]);
10807         //VectorVectors(planes[4], planes[2], planes[0]);
10808         AnglesFromVectors(angles, localnormal, NULL, false);
10809         AngleVectors(angles, planes[0], planes[2], planes[4]);
10810         VectorNegate(planes[0], planes[1]);
10811         VectorNegate(planes[2], planes[3]);
10812         VectorNegate(planes[4], planes[5]);
10813         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10814         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10815         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10816         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10817         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10818         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10819
10820 #if 1
10821 // works
10822 {
10823         matrix4x4_t forwardprojection;
10824         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10825         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10826 }
10827 #else
10828 // broken
10829 {
10830         float projectionvector[4][3];
10831         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10832         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10833         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10834         projectionvector[0][0] = planes[0][0] * ilocalsize;
10835         projectionvector[0][1] = planes[1][0] * ilocalsize;
10836         projectionvector[0][2] = planes[2][0] * ilocalsize;
10837         projectionvector[1][0] = planes[0][1] * ilocalsize;
10838         projectionvector[1][1] = planes[1][1] * ilocalsize;
10839         projectionvector[1][2] = planes[2][1] * ilocalsize;
10840         projectionvector[2][0] = planes[0][2] * ilocalsize;
10841         projectionvector[2][1] = planes[1][2] * ilocalsize;
10842         projectionvector[2][2] = planes[2][2] * ilocalsize;
10843         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10844         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10845         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10846         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10847 }
10848 #endif
10849
10850         dynamic = model->surfmesh.isanimated;
10851         numsurfacelist = model->nummodelsurfaces;
10852         surfacelist = model->sortedmodelsurfaces;
10853         surfaces = model->data_surfaces;
10854
10855         bih = NULL;
10856         bih_triangles_count = -1;
10857         if(!dynamic)
10858         {
10859                 if(model->render_bih.numleafs)
10860                         bih = &model->render_bih;
10861                 else if(model->collision_bih.numleafs)
10862                         bih = &model->collision_bih;
10863         }
10864         if(bih)
10865                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10866         if(bih_triangles_count == 0)
10867                 return;
10868         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10869                 return;
10870         if(bih_triangles_count > 0)
10871         {
10872                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10873                 {
10874                         surfaceindex = bih_surfaces[triangleindex];
10875                         surface = surfaces + surfaceindex;
10876                         texture = surface->texture;
10877                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10878                                 continue;
10879                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10880                                 continue;
10881                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10882                 }
10883         }
10884         else
10885         {
10886                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10887                 {
10888                         surfaceindex = surfacelist[surfacelistindex];
10889                         surface = surfaces + surfaceindex;
10890                         // check cull box first because it rejects more than any other check
10891                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10892                                 continue;
10893                         // skip transparent surfaces
10894                         texture = surface->texture;
10895                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10896                                 continue;
10897                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10898                                 continue;
10899                         numtriangles = surface->num_triangles;
10900                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10901                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10902                 }
10903         }
10904 }
10905
10906 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10907 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)
10908 {
10909         int renderentityindex;
10910         float worldmins[3];
10911         float worldmaxs[3];
10912         entity_render_t *ent;
10913
10914         if (!cl_decals_newsystem.integer)
10915                 return;
10916
10917         worldmins[0] = worldorigin[0] - worldsize;
10918         worldmins[1] = worldorigin[1] - worldsize;
10919         worldmins[2] = worldorigin[2] - worldsize;
10920         worldmaxs[0] = worldorigin[0] + worldsize;
10921         worldmaxs[1] = worldorigin[1] + worldsize;
10922         worldmaxs[2] = worldorigin[2] + worldsize;
10923
10924         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10925
10926         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10927         {
10928                 ent = r_refdef.scene.entities[renderentityindex];
10929                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10930                         continue;
10931
10932                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10933         }
10934 }
10935
10936 typedef struct r_decalsystem_splatqueue_s
10937 {
10938         vec3_t worldorigin;
10939         vec3_t worldnormal;
10940         float color[4];
10941         float tcrange[4];
10942         float worldsize;
10943         int decalsequence;
10944 }
10945 r_decalsystem_splatqueue_t;
10946
10947 int r_decalsystem_numqueued = 0;
10948 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10949
10950 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)
10951 {
10952         r_decalsystem_splatqueue_t *queue;
10953
10954         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10955                 return;
10956
10957         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10958         VectorCopy(worldorigin, queue->worldorigin);
10959         VectorCopy(worldnormal, queue->worldnormal);
10960         Vector4Set(queue->color, r, g, b, a);
10961         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10962         queue->worldsize = worldsize;
10963         queue->decalsequence = cl.decalsequence++;
10964 }
10965
10966 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10967 {
10968         int i;
10969         r_decalsystem_splatqueue_t *queue;
10970
10971         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10972                 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);
10973         r_decalsystem_numqueued = 0;
10974 }
10975
10976 extern cvar_t cl_decals_max;
10977 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10978 {
10979         int i;
10980         decalsystem_t *decalsystem = &ent->decalsystem;
10981         int numdecals;
10982         int killsequence;
10983         tridecal_t *decal;
10984         float frametime;
10985         float lifetime;
10986
10987         if (!decalsystem->numdecals)
10988                 return;
10989
10990         if (r_showsurfaces.integer)
10991                 return;
10992
10993         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10994         {
10995                 R_DecalSystem_Reset(decalsystem);
10996                 return;
10997         }
10998
10999         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11000         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11001
11002         if (decalsystem->lastupdatetime)
11003                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11004         else
11005                 frametime = 0;
11006         decalsystem->lastupdatetime = r_refdef.scene.time;
11007         decal = decalsystem->decals;
11008         numdecals = decalsystem->numdecals;
11009
11010         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11011         {
11012                 if (decal->color4f[0][3])
11013                 {
11014                         decal->lived += frametime;
11015                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11016                         {
11017                                 memset(decal, 0, sizeof(*decal));
11018                                 if (decalsystem->freedecal > i)
11019                                         decalsystem->freedecal = i;
11020                         }
11021                 }
11022         }
11023         decal = decalsystem->decals;
11024         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11025                 numdecals--;
11026
11027         // collapse the array by shuffling the tail decals into the gaps
11028         for (;;)
11029         {
11030                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11031                         decalsystem->freedecal++;
11032                 if (decalsystem->freedecal == numdecals)
11033                         break;
11034                 decal[decalsystem->freedecal] = decal[--numdecals];
11035         }
11036
11037         decalsystem->numdecals = numdecals;
11038
11039         if (numdecals <= 0)
11040         {
11041                 // if there are no decals left, reset decalsystem
11042                 R_DecalSystem_Reset(decalsystem);
11043         }
11044 }
11045
11046 extern skinframe_t *decalskinframe;
11047 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11048 {
11049         int i;
11050         decalsystem_t *decalsystem = &ent->decalsystem;
11051         int numdecals;
11052         tridecal_t *decal;
11053         float faderate;
11054         float alpha;
11055         float *v3f;
11056         float *c4f;
11057         float *t2f;
11058         const int *e;
11059         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11060         int numtris = 0;
11061
11062         numdecals = decalsystem->numdecals;
11063         if (!numdecals)
11064                 return;
11065
11066         if (r_showsurfaces.integer)
11067                 return;
11068
11069         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11070         {
11071                 R_DecalSystem_Reset(decalsystem);
11072                 return;
11073         }
11074
11075         // if the model is static it doesn't matter what value we give for
11076         // wantnormals and wanttangents, so this logic uses only rules applicable
11077         // to a model, knowing that they are meaningless otherwise
11078         if (ent == r_refdef.scene.worldentity)
11079                 RSurf_ActiveWorldEntity();
11080         else
11081                 RSurf_ActiveModelEntity(ent, false, false, false);
11082
11083         decalsystem->lastupdatetime = r_refdef.scene.time;
11084         decal = decalsystem->decals;
11085
11086         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11087
11088         // update vertex positions for animated models
11089         v3f = decalsystem->vertex3f;
11090         c4f = decalsystem->color4f;
11091         t2f = decalsystem->texcoord2f;
11092         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11093         {
11094                 if (!decal->color4f[0][3])
11095                         continue;
11096
11097                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11098                         continue;
11099
11100                 // skip backfaces
11101                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11102                         continue;
11103
11104                 // update color values for fading decals
11105                 if (decal->lived >= cl_decals_time.value)
11106                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11107                 else
11108                         alpha = 1.0f;
11109
11110                 c4f[ 0] = decal->color4f[0][0] * alpha;
11111                 c4f[ 1] = decal->color4f[0][1] * alpha;
11112                 c4f[ 2] = decal->color4f[0][2] * alpha;
11113                 c4f[ 3] = 1;
11114                 c4f[ 4] = decal->color4f[1][0] * alpha;
11115                 c4f[ 5] = decal->color4f[1][1] * alpha;
11116                 c4f[ 6] = decal->color4f[1][2] * alpha;
11117                 c4f[ 7] = 1;
11118                 c4f[ 8] = decal->color4f[2][0] * alpha;
11119                 c4f[ 9] = decal->color4f[2][1] * alpha;
11120                 c4f[10] = decal->color4f[2][2] * alpha;
11121                 c4f[11] = 1;
11122
11123                 t2f[0] = decal->texcoord2f[0][0];
11124                 t2f[1] = decal->texcoord2f[0][1];
11125                 t2f[2] = decal->texcoord2f[1][0];
11126                 t2f[3] = decal->texcoord2f[1][1];
11127                 t2f[4] = decal->texcoord2f[2][0];
11128                 t2f[5] = decal->texcoord2f[2][1];
11129
11130                 // update vertex positions for animated models
11131                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11132                 {
11133                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11134                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11135                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11136                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11137                 }
11138                 else
11139                 {
11140                         VectorCopy(decal->vertex3f[0], v3f);
11141                         VectorCopy(decal->vertex3f[1], v3f + 3);
11142                         VectorCopy(decal->vertex3f[2], v3f + 6);
11143                 }
11144
11145                 if (r_refdef.fogenabled)
11146                 {
11147                         alpha = RSurf_FogVertex(v3f);
11148                         VectorScale(c4f, alpha, c4f);
11149                         alpha = RSurf_FogVertex(v3f + 3);
11150                         VectorScale(c4f + 4, alpha, c4f + 4);
11151                         alpha = RSurf_FogVertex(v3f + 6);
11152                         VectorScale(c4f + 8, alpha, c4f + 8);
11153                 }
11154
11155                 v3f += 9;
11156                 c4f += 12;
11157                 t2f += 6;
11158                 numtris++;
11159         }
11160
11161         if (numtris > 0)
11162         {
11163                 r_refdef.stats.drawndecals += numtris;
11164
11165                 // now render the decals all at once
11166                 // (this assumes they all use one particle font texture!)
11167                 RSurf_ActiveCustomEntity(&rsurface.matrix, &rsurface.inversematrix, rsurface.ent_flags, ent->shadertime, 1, 1, 1, 1, numdecals*3, decalsystem->vertex3f, decalsystem->texcoord2f, NULL, NULL, NULL, decalsystem->color4f, numtris, decalsystem->element3i, decalsystem->element3s, false, false);
11168 //              R_Mesh_ResetTextureState();
11169                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11170                 GL_DepthMask(false);
11171                 GL_DepthRange(0, 1);
11172                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11173                 GL_DepthTest(true);
11174                 GL_CullFace(GL_NONE);
11175                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11176                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11177                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11178         }
11179 }
11180
11181 static void R_DrawModelDecals(void)
11182 {
11183         int i, numdecals;
11184
11185         // fade faster when there are too many decals
11186         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11187         for (i = 0;i < r_refdef.scene.numentities;i++)
11188                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11189
11190         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11191         for (i = 0;i < r_refdef.scene.numentities;i++)
11192                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11193                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11194
11195         R_DecalSystem_ApplySplatEntitiesQueue();
11196
11197         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11198         for (i = 0;i < r_refdef.scene.numentities;i++)
11199                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11200
11201         r_refdef.stats.totaldecals += numdecals;
11202
11203         if (r_showsurfaces.integer)
11204                 return;
11205
11206         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11207
11208         for (i = 0;i < r_refdef.scene.numentities;i++)
11209         {
11210                 if (!r_refdef.viewcache.entityvisible[i])
11211                         continue;
11212                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11213                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11214         }
11215 }
11216
11217 extern cvar_t mod_collision_bih;
11218 void R_DrawDebugModel(void)
11219 {
11220         entity_render_t *ent = rsurface.entity;
11221         int i, j, k, l, flagsmask;
11222         const msurface_t *surface;
11223         dp_model_t *model = ent->model;
11224         vec3_t v;
11225
11226         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11227                 return;
11228
11229         if (r_showoverdraw.value > 0)
11230         {
11231                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11232                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11233                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11234                 GL_DepthTest(false);
11235                 GL_DepthMask(false);
11236                 GL_DepthRange(0, 1);
11237                 GL_BlendFunc(GL_ONE, GL_ONE);
11238                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11239                 {
11240                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11241                                 continue;
11242                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11243                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11244                         {
11245                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11246                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11247                                 if (!rsurface.texture->currentlayers->depthmask)
11248                                         GL_Color(c, 0, 0, 1.0f);
11249                                 else if (ent == r_refdef.scene.worldentity)
11250                                         GL_Color(c, c, c, 1.0f);
11251                                 else
11252                                         GL_Color(0, c, 0, 1.0f);
11253                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11254                                 RSurf_DrawBatch();
11255                         }
11256                 }
11257                 rsurface.texture = NULL;
11258         }
11259
11260         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11261
11262 //      R_Mesh_ResetTextureState();
11263         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11264         GL_DepthRange(0, 1);
11265         GL_DepthTest(!r_showdisabledepthtest.integer);
11266         GL_DepthMask(false);
11267         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11268
11269         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11270         {
11271                 int triangleindex;
11272                 int bihleafindex;
11273                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11274                 const q3mbrush_t *brush;
11275                 const bih_t *bih = &model->collision_bih;
11276                 const bih_leaf_t *bihleaf;
11277                 float vertex3f[3][3];
11278                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11279                 cullbox = false;
11280                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11281                 {
11282                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11283                                 continue;
11284                         switch (bihleaf->type)
11285                         {
11286                         case BIH_BRUSH:
11287                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11288                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11289                                 {
11290                                         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);
11291                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11292                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11293                                 }
11294                                 break;
11295                         case BIH_COLLISIONTRIANGLE:
11296                                 triangleindex = bihleaf->itemindex;
11297                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11298                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11299                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11300                                 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);
11301                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11302                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11303                                 break;
11304                         case BIH_RENDERTRIANGLE:
11305                                 triangleindex = bihleaf->itemindex;
11306                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11307                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11308                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11309                                 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);
11310                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11311                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11312                                 break;
11313                         }
11314                 }
11315         }
11316
11317         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11318
11319         if (r_showtris.integer && qglPolygonMode)
11320         {
11321                 if (r_showdisabledepthtest.integer)
11322                 {
11323                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11324                         GL_DepthMask(false);
11325                 }
11326                 else
11327                 {
11328                         GL_BlendFunc(GL_ONE, GL_ZERO);
11329                         GL_DepthMask(true);
11330                 }
11331                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11332                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11333                 {
11334                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11335                                 continue;
11336                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11337                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11338                         {
11339                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11340                                 if (!rsurface.texture->currentlayers->depthmask)
11341                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11342                                 else if (ent == r_refdef.scene.worldentity)
11343                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11344                                 else
11345                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11346                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11347                                 RSurf_DrawBatch();
11348                         }
11349                 }
11350                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11351                 rsurface.texture = NULL;
11352         }
11353
11354         if (r_shownormals.value != 0 && qglBegin)
11355         {
11356                 if (r_showdisabledepthtest.integer)
11357                 {
11358                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11359                         GL_DepthMask(false);
11360                 }
11361                 else
11362                 {
11363                         GL_BlendFunc(GL_ONE, GL_ZERO);
11364                         GL_DepthMask(true);
11365                 }
11366                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11367                 {
11368                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11369                                 continue;
11370                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11371                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11372                         {
11373                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11374                                 qglBegin(GL_LINES);
11375                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11376                                 {
11377                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11378                                         {
11379                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11380                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11381                                                 qglVertex3f(v[0], v[1], v[2]);
11382                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11383                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11384                                                 qglVertex3f(v[0], v[1], v[2]);
11385                                         }
11386                                 }
11387                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11388                                 {
11389                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11390                                         {
11391                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11392                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11393                                                 qglVertex3f(v[0], v[1], v[2]);
11394                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11395                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11396                                                 qglVertex3f(v[0], v[1], v[2]);
11397                                         }
11398                                 }
11399                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11400                                 {
11401                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11402                                         {
11403                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11404                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11405                                                 qglVertex3f(v[0], v[1], v[2]);
11406                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11407                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11408                                                 qglVertex3f(v[0], v[1], v[2]);
11409                                         }
11410                                 }
11411                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11412                                 {
11413                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11414                                         {
11415                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11416                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11417                                                 qglVertex3f(v[0], v[1], v[2]);
11418                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11419                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11420                                                 qglVertex3f(v[0], v[1], v[2]);
11421                                         }
11422                                 }
11423                                 qglEnd();
11424                                 CHECKGLERROR
11425                         }
11426                 }
11427                 rsurface.texture = NULL;
11428         }
11429 }
11430
11431 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11432 int r_maxsurfacelist = 0;
11433 const msurface_t **r_surfacelist = NULL;
11434 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11435 {
11436         int i, j, endj, flagsmask;
11437         dp_model_t *model = r_refdef.scene.worldmodel;
11438         msurface_t *surfaces;
11439         unsigned char *update;
11440         int numsurfacelist = 0;
11441         if (model == NULL)
11442                 return;
11443
11444         if (r_maxsurfacelist < model->num_surfaces)
11445         {
11446                 r_maxsurfacelist = model->num_surfaces;
11447                 if (r_surfacelist)
11448                         Mem_Free((msurface_t**)r_surfacelist);
11449                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11450         }
11451
11452         RSurf_ActiveWorldEntity();
11453
11454         surfaces = model->data_surfaces;
11455         update = model->brushq1.lightmapupdateflags;
11456
11457         // update light styles on this submodel
11458         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11459         {
11460                 model_brush_lightstyleinfo_t *style;
11461                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11462                 {
11463                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11464                         {
11465                                 int *list = style->surfacelist;
11466                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11467                                 for (j = 0;j < style->numsurfaces;j++)
11468                                         update[list[j]] = true;
11469                         }
11470                 }
11471         }
11472
11473         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11474
11475         if (debug)
11476         {
11477                 R_DrawDebugModel();
11478                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11479                 return;
11480         }
11481
11482         rsurface.lightmaptexture = NULL;
11483         rsurface.deluxemaptexture = NULL;
11484         rsurface.uselightmaptexture = false;
11485         rsurface.texture = NULL;
11486         rsurface.rtlight = NULL;
11487         numsurfacelist = 0;
11488         // add visible surfaces to draw list
11489         for (i = 0;i < model->nummodelsurfaces;i++)
11490         {
11491                 j = model->sortedmodelsurfaces[i];
11492                 if (r_refdef.viewcache.world_surfacevisible[j])
11493                         r_surfacelist[numsurfacelist++] = surfaces + j;
11494         }
11495         // update lightmaps if needed
11496         if (model->brushq1.firstrender)
11497         {
11498                 model->brushq1.firstrender = false;
11499                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11500                         if (update[j])
11501                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11502         }
11503         else if (update)
11504         {
11505                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11506                         if (r_refdef.viewcache.world_surfacevisible[j])
11507                                 if (update[j])
11508                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11509         }
11510         // don't do anything if there were no surfaces
11511         if (!numsurfacelist)
11512         {
11513                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11514                 return;
11515         }
11516         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11517
11518         // add to stats if desired
11519         if (r_speeds.integer && !skysurfaces && !depthonly)
11520         {
11521                 r_refdef.stats.world_surfaces += numsurfacelist;
11522                 for (j = 0;j < numsurfacelist;j++)
11523                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11524         }
11525
11526         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11527 }
11528
11529 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11530 {
11531         int i, j, endj, flagsmask;
11532         dp_model_t *model = ent->model;
11533         msurface_t *surfaces;
11534         unsigned char *update;
11535         int numsurfacelist = 0;
11536         if (model == NULL)
11537                 return;
11538
11539         if (r_maxsurfacelist < model->num_surfaces)
11540         {
11541                 r_maxsurfacelist = model->num_surfaces;
11542                 if (r_surfacelist)
11543                         Mem_Free((msurface_t **)r_surfacelist);
11544                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11545         }
11546
11547         // if the model is static it doesn't matter what value we give for
11548         // wantnormals and wanttangents, so this logic uses only rules applicable
11549         // to a model, knowing that they are meaningless otherwise
11550         if (ent == r_refdef.scene.worldentity)
11551                 RSurf_ActiveWorldEntity();
11552         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11553                 RSurf_ActiveModelEntity(ent, false, false, false);
11554         else if (prepass)
11555                 RSurf_ActiveModelEntity(ent, true, true, true);
11556         else if (depthonly)
11557         {
11558                 switch (vid.renderpath)
11559                 {
11560                 case RENDERPATH_GL20:
11561                 case RENDERPATH_D3D9:
11562                 case RENDERPATH_D3D10:
11563                 case RENDERPATH_D3D11:
11564                 case RENDERPATH_SOFT:
11565                 case RENDERPATH_GLES2:
11566                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11567                         break;
11568                 case RENDERPATH_GL11:
11569                 case RENDERPATH_GL13:
11570                 case RENDERPATH_GLES1:
11571                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11572                         break;
11573                 }
11574         }
11575         else
11576         {
11577                 switch (vid.renderpath)
11578                 {
11579                 case RENDERPATH_GL20:
11580                 case RENDERPATH_D3D9:
11581                 case RENDERPATH_D3D10:
11582                 case RENDERPATH_D3D11:
11583                 case RENDERPATH_SOFT:
11584                 case RENDERPATH_GLES2:
11585                         RSurf_ActiveModelEntity(ent, true, true, false);
11586                         break;
11587                 case RENDERPATH_GL11:
11588                 case RENDERPATH_GL13:
11589                 case RENDERPATH_GLES1:
11590                         RSurf_ActiveModelEntity(ent, true, false, false);
11591                         break;
11592                 }
11593         }
11594
11595         surfaces = model->data_surfaces;
11596         update = model->brushq1.lightmapupdateflags;
11597
11598         // update light styles
11599         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11600         {
11601                 model_brush_lightstyleinfo_t *style;
11602                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11603                 {
11604                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11605                         {
11606                                 int *list = style->surfacelist;
11607                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11608                                 for (j = 0;j < style->numsurfaces;j++)
11609                                         update[list[j]] = true;
11610                         }
11611                 }
11612         }
11613
11614         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11615
11616         if (debug)
11617         {
11618                 R_DrawDebugModel();
11619                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11620                 return;
11621         }
11622
11623         rsurface.lightmaptexture = NULL;
11624         rsurface.deluxemaptexture = NULL;
11625         rsurface.uselightmaptexture = false;
11626         rsurface.texture = NULL;
11627         rsurface.rtlight = NULL;
11628         numsurfacelist = 0;
11629         // add visible surfaces to draw list
11630         for (i = 0;i < model->nummodelsurfaces;i++)
11631                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11632         // don't do anything if there were no surfaces
11633         if (!numsurfacelist)
11634         {
11635                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11636                 return;
11637         }
11638         // update lightmaps if needed
11639         if (update)
11640         {
11641                 int updated = 0;
11642                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11643                 {
11644                         if (update[j])
11645                         {
11646                                 updated++;
11647                                 R_BuildLightMap(ent, surfaces + j);
11648                         }
11649                 }
11650         }
11651         if (update)
11652                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11653                         if (update[j])
11654                                 R_BuildLightMap(ent, surfaces + j);
11655         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11656
11657         // add to stats if desired
11658         if (r_speeds.integer && !skysurfaces && !depthonly)
11659         {
11660                 r_refdef.stats.entities_surfaces += numsurfacelist;
11661                 for (j = 0;j < numsurfacelist;j++)
11662                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11663         }
11664
11665         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11666 }
11667
11668 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11669 {
11670         static texture_t texture;
11671         static msurface_t surface;
11672         const msurface_t *surfacelist = &surface;
11673
11674         // fake enough texture and surface state to render this geometry
11675
11676         texture.update_lastrenderframe = -1; // regenerate this texture
11677         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11678         texture.currentskinframe = skinframe;
11679         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11680         texture.offsetmapping = OFFSETMAPPING_OFF;
11681         texture.offsetscale = 1;
11682         texture.specularscalemod = 1;
11683         texture.specularpowermod = 1;
11684
11685         surface.texture = &texture;
11686         surface.num_triangles = numtriangles;
11687         surface.num_firsttriangle = firsttriangle;
11688         surface.num_vertices = numvertices;
11689         surface.num_firstvertex = firstvertex;
11690
11691         // now render it
11692         rsurface.texture = R_GetCurrentTexture(surface.texture);
11693         rsurface.lightmaptexture = NULL;
11694         rsurface.deluxemaptexture = NULL;
11695         rsurface.uselightmaptexture = false;
11696         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11697 }
11698
11699 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)
11700 {
11701         static msurface_t surface;
11702         const msurface_t *surfacelist = &surface;
11703
11704         // fake enough texture and surface state to render this geometry
11705         surface.texture = texture;
11706         surface.num_triangles = numtriangles;
11707         surface.num_firsttriangle = firsttriangle;
11708         surface.num_vertices = numvertices;
11709         surface.num_firstvertex = firstvertex;
11710
11711         // now render it
11712         rsurface.texture = R_GetCurrentTexture(surface.texture);
11713         rsurface.lightmaptexture = NULL;
11714         rsurface.deluxemaptexture = NULL;
11715         rsurface.uselightmaptexture = false;
11716         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11717 }