]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Begin a quick re-write of how motionblur values are calculated
[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_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
201 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
202
203 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"};
204
205 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"};
206
207 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
208
209 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
210
211 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
212 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"};
213
214 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."};
215
216 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)"};
217
218 extern cvar_t v_glslgamma;
219
220 extern qboolean v_flipped_state;
221
222 static struct r_bloomstate_s
223 {
224         qboolean enabled;
225         qboolean hdr;
226
227         int bloomwidth, bloomheight;
228
229         textype_t texturetype;
230         int viewfbo; // used to check if r_viewfbo cvar has changed
231
232         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
233         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
234         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
235
236         int screentexturewidth, screentextureheight;
237         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
238
239         int bloomtexturewidth, bloomtextureheight;
240         rtexture_t *texture_bloom;
241
242         // arrays for rendering the screen passes
243         float screentexcoord2f[8];
244         float bloomtexcoord2f[8];
245         float offsettexcoord2f[8];
246
247         r_viewport_t viewport;
248 }
249 r_bloomstate;
250
251 r_waterstate_t r_waterstate;
252
253 /// shadow volume bsp struct with automatically growing nodes buffer
254 svbsp_t r_svbsp;
255
256 rtexture_t *r_texture_blanknormalmap;
257 rtexture_t *r_texture_white;
258 rtexture_t *r_texture_grey128;
259 rtexture_t *r_texture_black;
260 rtexture_t *r_texture_notexture;
261 rtexture_t *r_texture_whitecube;
262 rtexture_t *r_texture_normalizationcube;
263 rtexture_t *r_texture_fogattenuation;
264 rtexture_t *r_texture_fogheighttexture;
265 rtexture_t *r_texture_gammaramps;
266 unsigned int r_texture_gammaramps_serial;
267 //rtexture_t *r_texture_fogintensity;
268 rtexture_t *r_texture_reflectcube;
269
270 // TODO: hash lookups?
271 typedef struct cubemapinfo_s
272 {
273         char basename[64];
274         rtexture_t *texture;
275 }
276 cubemapinfo_t;
277
278 int r_texture_numcubemaps;
279 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
280
281 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
282 unsigned int r_numqueries;
283 unsigned int r_maxqueries;
284
285 typedef struct r_qwskincache_s
286 {
287         char name[MAX_QPATH];
288         skinframe_t *skinframe;
289 }
290 r_qwskincache_t;
291
292 static r_qwskincache_t *r_qwskincache;
293 static int r_qwskincache_size;
294
295 /// vertex coordinates for a quad that covers the screen exactly
296 extern const float r_screenvertex3f[12];
297 extern const float r_d3dscreenvertex3f[12];
298 const float r_screenvertex3f[12] =
299 {
300         0, 0, 0,
301         1, 0, 0,
302         1, 1, 0,
303         0, 1, 0
304 };
305 const float r_d3dscreenvertex3f[12] =
306 {
307         0, 1, 0,
308         1, 1, 0,
309         1, 0, 0,
310         0, 0, 0
311 };
312
313 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
314 {
315         int i;
316         for (i = 0;i < verts;i++)
317         {
318                 out[0] = in[0] * r;
319                 out[1] = in[1] * g;
320                 out[2] = in[2] * b;
321                 out[3] = in[3];
322                 in += 4;
323                 out += 4;
324         }
325 }
326
327 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
328 {
329         int i;
330         for (i = 0;i < verts;i++)
331         {
332                 out[0] = r;
333                 out[1] = g;
334                 out[2] = b;
335                 out[3] = a;
336                 out += 4;
337         }
338 }
339
340 // FIXME: move this to client?
341 void FOG_clear(void)
342 {
343         if (gamemode == GAME_NEHAHRA)
344         {
345                 Cvar_Set("gl_fogenable", "0");
346                 Cvar_Set("gl_fogdensity", "0.2");
347                 Cvar_Set("gl_fogred", "0.3");
348                 Cvar_Set("gl_foggreen", "0.3");
349                 Cvar_Set("gl_fogblue", "0.3");
350         }
351         r_refdef.fog_density = 0;
352         r_refdef.fog_red = 0;
353         r_refdef.fog_green = 0;
354         r_refdef.fog_blue = 0;
355         r_refdef.fog_alpha = 1;
356         r_refdef.fog_start = 0;
357         r_refdef.fog_end = 16384;
358         r_refdef.fog_height = 1<<30;
359         r_refdef.fog_fadedepth = 128;
360         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
361 }
362
363 static void R_BuildBlankTextures(void)
364 {
365         unsigned char data[4];
366         data[2] = 128; // normal X
367         data[1] = 128; // normal Y
368         data[0] = 255; // normal Z
369         data[3] = 128; // height
370         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
371         data[0] = 255;
372         data[1] = 255;
373         data[2] = 255;
374         data[3] = 255;
375         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 128;
377         data[1] = 128;
378         data[2] = 128;
379         data[3] = 255;
380         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 0;
382         data[1] = 0;
383         data[2] = 0;
384         data[3] = 255;
385         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386 }
387
388 static void R_BuildNoTexture(void)
389 {
390         int x, y;
391         unsigned char pix[16][16][4];
392         // this makes a light grey/dark grey checkerboard texture
393         for (y = 0;y < 16;y++)
394         {
395                 for (x = 0;x < 16;x++)
396                 {
397                         if ((y < 8) ^ (x < 8))
398                         {
399                                 pix[y][x][0] = 128;
400                                 pix[y][x][1] = 128;
401                                 pix[y][x][2] = 128;
402                                 pix[y][x][3] = 255;
403                         }
404                         else
405                         {
406                                 pix[y][x][0] = 64;
407                                 pix[y][x][1] = 64;
408                                 pix[y][x][2] = 64;
409                                 pix[y][x][3] = 255;
410                         }
411                 }
412         }
413         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
414 }
415
416 static void R_BuildWhiteCube(void)
417 {
418         unsigned char data[6*1*1*4];
419         memset(data, 255, sizeof(data));
420         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
421 }
422
423 static void R_BuildNormalizationCube(void)
424 {
425         int x, y, side;
426         vec3_t v;
427         vec_t s, t, intensity;
428 #define NORMSIZE 64
429         unsigned char *data;
430         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
431         for (side = 0;side < 6;side++)
432         {
433                 for (y = 0;y < NORMSIZE;y++)
434                 {
435                         for (x = 0;x < NORMSIZE;x++)
436                         {
437                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
438                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
439                                 switch(side)
440                                 {
441                                 default:
442                                 case 0:
443                                         v[0] = 1;
444                                         v[1] = -t;
445                                         v[2] = -s;
446                                         break;
447                                 case 1:
448                                         v[0] = -1;
449                                         v[1] = -t;
450                                         v[2] = s;
451                                         break;
452                                 case 2:
453                                         v[0] = s;
454                                         v[1] = 1;
455                                         v[2] = t;
456                                         break;
457                                 case 3:
458                                         v[0] = s;
459                                         v[1] = -1;
460                                         v[2] = -t;
461                                         break;
462                                 case 4:
463                                         v[0] = s;
464                                         v[1] = -t;
465                                         v[2] = 1;
466                                         break;
467                                 case 5:
468                                         v[0] = -s;
469                                         v[1] = -t;
470                                         v[2] = -1;
471                                         break;
472                                 }
473                                 intensity = 127.0f / sqrt(DotProduct(v, v));
474                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
475                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
476                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
477                                 data[((side*64+y)*64+x)*4+3] = 255;
478                         }
479                 }
480         }
481         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
482         Mem_Free(data);
483 }
484
485 static void R_BuildFogTexture(void)
486 {
487         int x, b;
488 #define FOGWIDTH 256
489         unsigned char data1[FOGWIDTH][4];
490         //unsigned char data2[FOGWIDTH][4];
491         double d, r, alpha;
492
493         r_refdef.fogmasktable_start = r_refdef.fog_start;
494         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
495         r_refdef.fogmasktable_range = r_refdef.fogrange;
496         r_refdef.fogmasktable_density = r_refdef.fog_density;
497
498         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
499         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
500         {
501                 d = (x * r - r_refdef.fogmasktable_start);
502                 if(developer_extra.integer)
503                         Con_DPrintf("%f ", d);
504                 d = max(0, d);
505                 if (r_fog_exp2.integer)
506                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
507                 else
508                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
509                 if(developer_extra.integer)
510                         Con_DPrintf(" : %f ", alpha);
511                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
512                 if(developer_extra.integer)
513                         Con_DPrintf(" = %f\n", alpha);
514                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
515         }
516
517         for (x = 0;x < FOGWIDTH;x++)
518         {
519                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
520                 data1[x][0] = b;
521                 data1[x][1] = b;
522                 data1[x][2] = b;
523                 data1[x][3] = 255;
524                 //data2[x][0] = 255 - b;
525                 //data2[x][1] = 255 - b;
526                 //data2[x][2] = 255 - b;
527                 //data2[x][3] = 255;
528         }
529         if (r_texture_fogattenuation)
530         {
531                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
532                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
533         }
534         else
535         {
536                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
537                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
538         }
539 }
540
541 static void R_BuildFogHeightTexture(void)
542 {
543         unsigned char *inpixels;
544         int size;
545         int x;
546         int y;
547         int j;
548         float c[4];
549         float f;
550         inpixels = NULL;
551         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
552         if (r_refdef.fogheighttexturename[0])
553                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
554         if (!inpixels)
555         {
556                 r_refdef.fog_height_tablesize = 0;
557                 if (r_texture_fogheighttexture)
558                         R_FreeTexture(r_texture_fogheighttexture);
559                 r_texture_fogheighttexture = NULL;
560                 if (r_refdef.fog_height_table2d)
561                         Mem_Free(r_refdef.fog_height_table2d);
562                 r_refdef.fog_height_table2d = NULL;
563                 if (r_refdef.fog_height_table1d)
564                         Mem_Free(r_refdef.fog_height_table1d);
565                 r_refdef.fog_height_table1d = NULL;
566                 return;
567         }
568         size = image_width;
569         r_refdef.fog_height_tablesize = size;
570         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
571         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
572         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
573         Mem_Free(inpixels);
574         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
575         // average fog color table accounting for every fog layer between a point
576         // and the camera.  (Note: attenuation is handled separately!)
577         for (y = 0;y < size;y++)
578         {
579                 for (x = 0;x < size;x++)
580                 {
581                         Vector4Clear(c);
582                         f = 0;
583                         if (x < y)
584                         {
585                                 for (j = x;j <= y;j++)
586                                 {
587                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
588                                         f++;
589                                 }
590                         }
591                         else
592                         {
593                                 for (j = x;j >= y;j--)
594                                 {
595                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
596                                         f++;
597                                 }
598                         }
599                         f = 1.0f / f;
600                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
601                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
602                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
603                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
604                 }
605         }
606         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
607 }
608
609 //=======================================================================================================================================================
610
611 static const char *builtinshaderstring =
612 #include "shader_glsl.h"
613 ;
614
615 const char *builtinhlslshaderstring =
616 #include "shader_hlsl.h"
617 ;
618
619 char *glslshaderstring = NULL;
620 char *hlslshaderstring = NULL;
621
622 //=======================================================================================================================================================
623
624 typedef struct shaderpermutationinfo_s
625 {
626         const char *pretext;
627         const char *name;
628 }
629 shaderpermutationinfo_t;
630
631 typedef struct shadermodeinfo_s
632 {
633         const char *vertexfilename;
634         const char *geometryfilename;
635         const char *fragmentfilename;
636         const char *pretext;
637         const char *name;
638 }
639 shadermodeinfo_t;
640
641 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
642 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
643 {
644         {"#define USEDIFFUSE\n", " diffuse"},
645         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
646         {"#define USEVIEWTINT\n", " viewtint"},
647         {"#define USECOLORMAPPING\n", " colormapping"},
648         {"#define USESATURATION\n", " saturation"},
649         {"#define USEFOGINSIDE\n", " foginside"},
650         {"#define USEFOGOUTSIDE\n", " fogoutside"},
651         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
652         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
653         {"#define USEGAMMARAMPS\n", " gammaramps"},
654         {"#define USECUBEFILTER\n", " cubefilter"},
655         {"#define USEGLOW\n", " glow"},
656         {"#define USEBLOOM\n", " bloom"},
657         {"#define USESPECULAR\n", " specular"},
658         {"#define USEPOSTPROCESSING\n", " postprocessing"},
659         {"#define USEREFLECTION\n", " reflection"},
660         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
661         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
662         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
663         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
664         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
665         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
666         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
667         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
668         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
669         {"#define USEALPHAKILL\n", " alphakill"},
670         {"#define USEREFLECTCUBE\n", " reflectcube"},
671         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
672         {"#define USEBOUNCEGRID\n", " bouncegrid"},
673         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
674         {"#define USETRIPPY\n", " trippy"},
675 };
676
677 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
678 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
679 {
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
682         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
696 };
697
698 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
699 {
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
716 };
717
718 struct r_glsl_permutation_s;
719 typedef struct r_glsl_permutation_s
720 {
721         /// hash lookup data
722         struct r_glsl_permutation_s *hashnext;
723         unsigned int mode;
724         unsigned int permutation;
725
726         /// indicates if we have tried compiling this permutation already
727         qboolean compiled;
728         /// 0 if compilation failed
729         int program;
730         // texture units assigned to each detected uniform
731         int tex_Texture_First;
732         int tex_Texture_Second;
733         int tex_Texture_GammaRamps;
734         int tex_Texture_Normal;
735         int tex_Texture_Color;
736         int tex_Texture_Gloss;
737         int tex_Texture_Glow;
738         int tex_Texture_SecondaryNormal;
739         int tex_Texture_SecondaryColor;
740         int tex_Texture_SecondaryGloss;
741         int tex_Texture_SecondaryGlow;
742         int tex_Texture_Pants;
743         int tex_Texture_Shirt;
744         int tex_Texture_FogHeightTexture;
745         int tex_Texture_FogMask;
746         int tex_Texture_Lightmap;
747         int tex_Texture_Deluxemap;
748         int tex_Texture_Attenuation;
749         int tex_Texture_Cube;
750         int tex_Texture_Refraction;
751         int tex_Texture_Reflection;
752         int tex_Texture_ShadowMap2D;
753         int tex_Texture_CubeProjection;
754         int tex_Texture_ScreenDepth;
755         int tex_Texture_ScreenNormalMap;
756         int tex_Texture_ScreenDiffuse;
757         int tex_Texture_ScreenSpecular;
758         int tex_Texture_ReflectMask;
759         int tex_Texture_ReflectCube;
760         int tex_Texture_BounceGrid;
761         /// locations of detected uniforms in program object, or -1 if not found
762         int loc_Texture_First;
763         int loc_Texture_Second;
764         int loc_Texture_GammaRamps;
765         int loc_Texture_Normal;
766         int loc_Texture_Color;
767         int loc_Texture_Gloss;
768         int loc_Texture_Glow;
769         int loc_Texture_SecondaryNormal;
770         int loc_Texture_SecondaryColor;
771         int loc_Texture_SecondaryGloss;
772         int loc_Texture_SecondaryGlow;
773         int loc_Texture_Pants;
774         int loc_Texture_Shirt;
775         int loc_Texture_FogHeightTexture;
776         int loc_Texture_FogMask;
777         int loc_Texture_Lightmap;
778         int loc_Texture_Deluxemap;
779         int loc_Texture_Attenuation;
780         int loc_Texture_Cube;
781         int loc_Texture_Refraction;
782         int loc_Texture_Reflection;
783         int loc_Texture_ShadowMap2D;
784         int loc_Texture_CubeProjection;
785         int loc_Texture_ScreenDepth;
786         int loc_Texture_ScreenNormalMap;
787         int loc_Texture_ScreenDiffuse;
788         int loc_Texture_ScreenSpecular;
789         int loc_Texture_ReflectMask;
790         int loc_Texture_ReflectCube;
791         int loc_Texture_BounceGrid;
792         int loc_Alpha;
793         int loc_BloomBlur_Parameters;
794         int loc_ClientTime;
795         int loc_Color_Ambient;
796         int loc_Color_Diffuse;
797         int loc_Color_Specular;
798         int loc_Color_Glow;
799         int loc_Color_Pants;
800         int loc_Color_Shirt;
801         int loc_DeferredColor_Ambient;
802         int loc_DeferredColor_Diffuse;
803         int loc_DeferredColor_Specular;
804         int loc_DeferredMod_Diffuse;
805         int loc_DeferredMod_Specular;
806         int loc_DistortScaleRefractReflect;
807         int loc_EyePosition;
808         int loc_FogColor;
809         int loc_FogHeightFade;
810         int loc_FogPlane;
811         int loc_FogPlaneViewDist;
812         int loc_FogRangeRecip;
813         int loc_LightColor;
814         int loc_LightDir;
815         int loc_LightPosition;
816         int loc_OffsetMapping_ScaleSteps;
817         int loc_PixelSize;
818         int loc_ReflectColor;
819         int loc_ReflectFactor;
820         int loc_ReflectOffset;
821         int loc_RefractColor;
822         int loc_Saturation;
823         int loc_ScreenCenterRefractReflect;
824         int loc_ScreenScaleRefractReflect;
825         int loc_ScreenToDepth;
826         int loc_ShadowMap_Parameters;
827         int loc_ShadowMap_TextureScale;
828         int loc_SpecularPower;
829         int loc_UserVec1;
830         int loc_UserVec2;
831         int loc_UserVec3;
832         int loc_UserVec4;
833         int loc_ViewTintColor;
834         int loc_ViewToLight;
835         int loc_ModelToLight;
836         int loc_TexMatrix;
837         int loc_BackgroundTexMatrix;
838         int loc_ModelViewProjectionMatrix;
839         int loc_ModelViewMatrix;
840         int loc_PixelToScreenTexCoord;
841         int loc_ModelToReflectCube;
842         int loc_ShadowMapMatrix;
843         int loc_BloomColorSubtract;
844         int loc_NormalmapScrollBlend;
845         int loc_BounceGridMatrix;
846         int loc_BounceGridIntensity;
847 }
848 r_glsl_permutation_t;
849
850 #define SHADERPERMUTATION_HASHSIZE 256
851
852
853 // non-degradable "lightweight" shader parameters to keep the permutations simpler
854 // these can NOT degrade! only use for simple stuff
855 enum
856 {
857         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
858         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
859         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
861         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
862         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
863         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
864 };
865 #define SHADERSTATICPARMS_COUNT 7
866
867 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
868 static int shaderstaticparms_count = 0;
869
870 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
871 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
872 qboolean R_CompileShader_CheckStaticParms(void)
873 {
874         static int r_compileshader_staticparms_save[1];
875         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
876         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
877
878         // detect all
879         if (r_glsl_saturation_redcompensate.integer)
880                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
881         if (r_glsl_vertextextureblend_usebothalphas.integer)
882                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
883         if (r_shadow_glossexact.integer)
884                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
885         if (r_glsl_postprocess.integer)
886         {
887                 if (r_glsl_postprocess_uservec1_enable.integer)
888                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
889                 if (r_glsl_postprocess_uservec2_enable.integer)
890                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
891                 if (r_glsl_postprocess_uservec3_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
893                 if (r_glsl_postprocess_uservec4_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
895         }
896         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
897 }
898
899 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
900         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
901                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
902         else \
903                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
904 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
905 {
906         shaderstaticparms_count = 0;
907
908         // emit all
909         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
910         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
911         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
912         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
916 }
917
918 /// information about each possible shader permutation
919 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
920 /// currently selected permutation
921 r_glsl_permutation_t *r_glsl_permutation;
922 /// storage for permutations linked in the hash table
923 memexpandablearray_t r_glsl_permutationarray;
924
925 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
926 {
927         //unsigned int hashdepth = 0;
928         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
929         r_glsl_permutation_t *p;
930         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
931         {
932                 if (p->mode == mode && p->permutation == permutation)
933                 {
934                         //if (hashdepth > 10)
935                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
936                         return p;
937                 }
938                 //hashdepth++;
939         }
940         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
941         p->mode = mode;
942         p->permutation = permutation;
943         p->hashnext = r_glsl_permutationhash[mode][hashindex];
944         r_glsl_permutationhash[mode][hashindex] = p;
945         //if (hashdepth > 10)
946         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
947         return p;
948 }
949
950 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
951 {
952         char *shaderstring;
953         if (!filename || !filename[0])
954                 return NULL;
955         if (!strcmp(filename, "glsl/default.glsl"))
956         {
957                 if (!glslshaderstring)
958                 {
959                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
960                         if (glslshaderstring)
961                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
962                         else
963                                 glslshaderstring = (char *)builtinshaderstring;
964                 }
965                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
966                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
967                 return shaderstring;
968         }
969         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
970         if (shaderstring)
971         {
972                 if (printfromdisknotice)
973                         Con_DPrintf("from disk %s... ", filename);
974                 return shaderstring;
975         }
976         return shaderstring;
977 }
978
979 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
980 {
981         int i;
982         int sampler;
983         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
984         char *vertexstring, *geometrystring, *fragmentstring;
985         char permutationname[256];
986         int vertstrings_count = 0;
987         int geomstrings_count = 0;
988         int fragstrings_count = 0;
989         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
990         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
991         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
992
993         if (p->compiled)
994                 return;
995         p->compiled = true;
996         p->program = 0;
997
998         permutationname[0] = 0;
999         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1000         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1001         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1002
1003         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1004
1005         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1006         if(vid.support.gl20shaders130)
1007         {
1008                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1009                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1010                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1011                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1012                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1013                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1014         }
1015
1016         // the first pretext is which type of shader to compile as
1017         // (later these will all be bound together as a program object)
1018         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1019         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1020         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1021
1022         // the second pretext is the mode (for example a light source)
1023         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1024         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1025         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1026         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1027
1028         // now add all the permutation pretexts
1029         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1030         {
1031                 if (permutation & (1<<i))
1032                 {
1033                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1034                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1035                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1036                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1037                 }
1038                 else
1039                 {
1040                         // keep line numbers correct
1041                         vertstrings_list[vertstrings_count++] = "\n";
1042                         geomstrings_list[geomstrings_count++] = "\n";
1043                         fragstrings_list[fragstrings_count++] = "\n";
1044                 }
1045         }
1046
1047         // add static parms
1048         R_CompileShader_AddStaticParms(mode, permutation);
1049         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1050         vertstrings_count += shaderstaticparms_count;
1051         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1052         geomstrings_count += shaderstaticparms_count;
1053         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054         fragstrings_count += shaderstaticparms_count;
1055
1056         // now append the shader text itself
1057         vertstrings_list[vertstrings_count++] = vertexstring;
1058         geomstrings_list[geomstrings_count++] = geometrystring;
1059         fragstrings_list[fragstrings_count++] = fragmentstring;
1060
1061         // if any sources were NULL, clear the respective list
1062         if (!vertexstring)
1063                 vertstrings_count = 0;
1064         if (!geometrystring)
1065                 geomstrings_count = 0;
1066         if (!fragmentstring)
1067                 fragstrings_count = 0;
1068
1069         // compile the shader program
1070         if (vertstrings_count + geomstrings_count + fragstrings_count)
1071                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1072         if (p->program)
1073         {
1074                 CHECKGLERROR
1075                 qglUseProgram(p->program);CHECKGLERROR
1076                 // look up all the uniform variable names we care about, so we don't
1077                 // have to look them up every time we set them
1078
1079                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1080                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1081                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1082                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1083                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1084                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1085                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1086                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1087                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1088                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1089                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1090                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1091                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1092                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1093                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1094                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1095                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1096                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1097                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1098                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1099                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1100                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1101                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1102                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1103                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1104                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1105                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1106                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1107                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1108                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1109                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1110                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1111                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1112                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1113                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1114                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1115                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1116                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1117                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1118                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1119                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1120                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1121                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1122                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1123                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1124                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1125                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1126                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1127                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1128                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1129                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1130                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1131                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1132                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1133                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1134                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1135                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1136                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1137                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1138                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1139                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1140                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1141                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1142                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1143                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1144                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1145                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1146                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1147                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1148                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1149                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1150                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1151                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1152                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1153                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1154                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1155                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1156                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1157                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1158                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1159                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1160                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1161                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1162                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1163                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1164                 // initialize the samplers to refer to the texture units we use
1165                 p->tex_Texture_First = -1;
1166                 p->tex_Texture_Second = -1;
1167                 p->tex_Texture_GammaRamps = -1;
1168                 p->tex_Texture_Normal = -1;
1169                 p->tex_Texture_Color = -1;
1170                 p->tex_Texture_Gloss = -1;
1171                 p->tex_Texture_Glow = -1;
1172                 p->tex_Texture_SecondaryNormal = -1;
1173                 p->tex_Texture_SecondaryColor = -1;
1174                 p->tex_Texture_SecondaryGloss = -1;
1175                 p->tex_Texture_SecondaryGlow = -1;
1176                 p->tex_Texture_Pants = -1;
1177                 p->tex_Texture_Shirt = -1;
1178                 p->tex_Texture_FogHeightTexture = -1;
1179                 p->tex_Texture_FogMask = -1;
1180                 p->tex_Texture_Lightmap = -1;
1181                 p->tex_Texture_Deluxemap = -1;
1182                 p->tex_Texture_Attenuation = -1;
1183                 p->tex_Texture_Cube = -1;
1184                 p->tex_Texture_Refraction = -1;
1185                 p->tex_Texture_Reflection = -1;
1186                 p->tex_Texture_ShadowMap2D = -1;
1187                 p->tex_Texture_CubeProjection = -1;
1188                 p->tex_Texture_ScreenDepth = -1;
1189                 p->tex_Texture_ScreenNormalMap = -1;
1190                 p->tex_Texture_ScreenDiffuse = -1;
1191                 p->tex_Texture_ScreenSpecular = -1;
1192                 p->tex_Texture_ReflectMask = -1;
1193                 p->tex_Texture_ReflectCube = -1;
1194                 p->tex_Texture_BounceGrid = -1;
1195                 sampler = 0;
1196                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1197                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1198                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1199                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1200                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1201                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1202                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1203                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1204                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1205                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1206                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1207                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1208                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1209                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1210                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1211                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1212                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1213                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1214                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1215                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1216                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1217                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1218                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1219                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1220                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1221                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1222                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1223                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1224                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1225                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1226                 CHECKGLERROR
1227                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1228         }
1229         else
1230                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1231
1232         // free the strings
1233         if (vertexstring)
1234                 Mem_Free(vertexstring);
1235         if (geometrystring)
1236                 Mem_Free(geometrystring);
1237         if (fragmentstring)
1238                 Mem_Free(fragmentstring);
1239 }
1240
1241 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1242 {
1243         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1244         if (r_glsl_permutation != perm)
1245         {
1246                 r_glsl_permutation = perm;
1247                 if (!r_glsl_permutation->program)
1248                 {
1249                         if (!r_glsl_permutation->compiled)
1250                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1251                         if (!r_glsl_permutation->program)
1252                         {
1253                                 // remove features until we find a valid permutation
1254                                 int i;
1255                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1256                                 {
1257                                         // reduce i more quickly whenever it would not remove any bits
1258                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1259                                         if (!(permutation & j))
1260                                                 continue;
1261                                         permutation -= j;
1262                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1263                                         if (!r_glsl_permutation->compiled)
1264                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1265                                         if (r_glsl_permutation->program)
1266                                                 break;
1267                                 }
1268                                 if (i >= SHADERPERMUTATION_COUNT)
1269                                 {
1270                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1271                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1272                                         qglUseProgram(0);CHECKGLERROR
1273                                         return; // no bit left to clear, entire mode is broken
1274                                 }
1275                         }
1276                 }
1277                 CHECKGLERROR
1278                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1279         }
1280         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1281         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1282         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1283 }
1284
1285 #ifdef SUPPORTD3D
1286
1287 #ifdef SUPPORTD3D
1288 #include <d3d9.h>
1289 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1290 extern D3DCAPS9 vid_d3d9caps;
1291 #endif
1292
1293 struct r_hlsl_permutation_s;
1294 typedef struct r_hlsl_permutation_s
1295 {
1296         /// hash lookup data
1297         struct r_hlsl_permutation_s *hashnext;
1298         unsigned int mode;
1299         unsigned int permutation;
1300
1301         /// indicates if we have tried compiling this permutation already
1302         qboolean compiled;
1303         /// NULL if compilation failed
1304         IDirect3DVertexShader9 *vertexshader;
1305         IDirect3DPixelShader9 *pixelshader;
1306 }
1307 r_hlsl_permutation_t;
1308
1309 typedef enum D3DVSREGISTER_e
1310 {
1311         D3DVSREGISTER_TexMatrix = 0, // float4x4
1312         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1313         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1314         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1315         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1316         D3DVSREGISTER_ModelToLight = 20, // float4x4
1317         D3DVSREGISTER_EyePosition = 24,
1318         D3DVSREGISTER_FogPlane = 25,
1319         D3DVSREGISTER_LightDir = 26,
1320         D3DVSREGISTER_LightPosition = 27,
1321 }
1322 D3DVSREGISTER_t;
1323
1324 typedef enum D3DPSREGISTER_e
1325 {
1326         D3DPSREGISTER_Alpha = 0,
1327         D3DPSREGISTER_BloomBlur_Parameters = 1,
1328         D3DPSREGISTER_ClientTime = 2,
1329         D3DPSREGISTER_Color_Ambient = 3,
1330         D3DPSREGISTER_Color_Diffuse = 4,
1331         D3DPSREGISTER_Color_Specular = 5,
1332         D3DPSREGISTER_Color_Glow = 6,
1333         D3DPSREGISTER_Color_Pants = 7,
1334         D3DPSREGISTER_Color_Shirt = 8,
1335         D3DPSREGISTER_DeferredColor_Ambient = 9,
1336         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1337         D3DPSREGISTER_DeferredColor_Specular = 11,
1338         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1339         D3DPSREGISTER_DeferredMod_Specular = 13,
1340         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1341         D3DPSREGISTER_EyePosition = 15, // unused
1342         D3DPSREGISTER_FogColor = 16,
1343         D3DPSREGISTER_FogHeightFade = 17,
1344         D3DPSREGISTER_FogPlane = 18,
1345         D3DPSREGISTER_FogPlaneViewDist = 19,
1346         D3DPSREGISTER_FogRangeRecip = 20,
1347         D3DPSREGISTER_LightColor = 21,
1348         D3DPSREGISTER_LightDir = 22, // unused
1349         D3DPSREGISTER_LightPosition = 23,
1350         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1351         D3DPSREGISTER_PixelSize = 25,
1352         D3DPSREGISTER_ReflectColor = 26,
1353         D3DPSREGISTER_ReflectFactor = 27,
1354         D3DPSREGISTER_ReflectOffset = 28,
1355         D3DPSREGISTER_RefractColor = 29,
1356         D3DPSREGISTER_Saturation = 30,
1357         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1358         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1359         D3DPSREGISTER_ScreenToDepth = 33,
1360         D3DPSREGISTER_ShadowMap_Parameters = 34,
1361         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1362         D3DPSREGISTER_SpecularPower = 36,
1363         D3DPSREGISTER_UserVec1 = 37,
1364         D3DPSREGISTER_UserVec2 = 38,
1365         D3DPSREGISTER_UserVec3 = 39,
1366         D3DPSREGISTER_UserVec4 = 40,
1367         D3DPSREGISTER_ViewTintColor = 41,
1368         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1369         D3DPSREGISTER_BloomColorSubtract = 43,
1370         D3DPSREGISTER_ViewToLight = 44, // float4x4
1371         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1372         D3DPSREGISTER_NormalmapScrollBlend = 52,
1373         // next at 53
1374 }
1375 D3DPSREGISTER_t;
1376
1377 /// information about each possible shader permutation
1378 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1379 /// currently selected permutation
1380 r_hlsl_permutation_t *r_hlsl_permutation;
1381 /// storage for permutations linked in the hash table
1382 memexpandablearray_t r_hlsl_permutationarray;
1383
1384 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1385 {
1386         //unsigned int hashdepth = 0;
1387         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1388         r_hlsl_permutation_t *p;
1389         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1390         {
1391                 if (p->mode == mode && p->permutation == permutation)
1392                 {
1393                         //if (hashdepth > 10)
1394                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1395                         return p;
1396                 }
1397                 //hashdepth++;
1398         }
1399         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1400         p->mode = mode;
1401         p->permutation = permutation;
1402         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1403         r_hlsl_permutationhash[mode][hashindex] = p;
1404         //if (hashdepth > 10)
1405         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1406         return p;
1407 }
1408
1409 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1410 {
1411         char *shaderstring;
1412         if (!filename || !filename[0])
1413                 return NULL;
1414         if (!strcmp(filename, "hlsl/default.hlsl"))
1415         {
1416                 if (!hlslshaderstring)
1417                 {
1418                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1419                         if (hlslshaderstring)
1420                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1421                         else
1422                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1423                 }
1424                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1425                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1426                 return shaderstring;
1427         }
1428         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429         if (shaderstring)
1430         {
1431                 if (printfromdisknotice)
1432                         Con_DPrintf("from disk %s... ", filename);
1433                 return shaderstring;
1434         }
1435         return shaderstring;
1436 }
1437
1438 #include <d3dx9.h>
1439 //#include <d3dx9shader.h>
1440 //#include <d3dx9mesh.h>
1441
1442 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1443 {
1444         DWORD *vsbin = NULL;
1445         DWORD *psbin = NULL;
1446         fs_offset_t vsbinsize;
1447         fs_offset_t psbinsize;
1448 //      IDirect3DVertexShader9 *vs = NULL;
1449 //      IDirect3DPixelShader9 *ps = NULL;
1450         ID3DXBuffer *vslog = NULL;
1451         ID3DXBuffer *vsbuffer = NULL;
1452         ID3DXConstantTable *vsconstanttable = NULL;
1453         ID3DXBuffer *pslog = NULL;
1454         ID3DXBuffer *psbuffer = NULL;
1455         ID3DXConstantTable *psconstanttable = NULL;
1456         int vsresult = 0;
1457         int psresult = 0;
1458         char temp[MAX_INPUTLINE];
1459         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1460         qboolean debugshader = gl_paranoid.integer != 0;
1461         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1462         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1463         if (!debugshader)
1464         {
1465                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1466                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1467         }
1468         if ((!vsbin && vertstring) || (!psbin && fragstring))
1469         {
1470                 const char* dllnames_d3dx9 [] =
1471                 {
1472                         "d3dx9_43.dll",
1473                         "d3dx9_42.dll",
1474                         "d3dx9_41.dll",
1475                         "d3dx9_40.dll",
1476                         "d3dx9_39.dll",
1477                         "d3dx9_38.dll",
1478                         "d3dx9_37.dll",
1479                         "d3dx9_36.dll",
1480                         "d3dx9_35.dll",
1481                         "d3dx9_34.dll",
1482                         "d3dx9_33.dll",
1483                         "d3dx9_32.dll",
1484                         "d3dx9_31.dll",
1485                         "d3dx9_30.dll",
1486                         "d3dx9_29.dll",
1487                         "d3dx9_28.dll",
1488                         "d3dx9_27.dll",
1489                         "d3dx9_26.dll",
1490                         "d3dx9_25.dll",
1491                         "d3dx9_24.dll",
1492                         NULL
1493                 };
1494                 dllhandle_t d3dx9_dll = NULL;
1495                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1496                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1497                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1498                 dllfunction_t d3dx9_dllfuncs[] =
1499                 {
1500                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1501                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1502                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1503                         {NULL, NULL}
1504                 };
1505                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1506                 {
1507                         DWORD shaderflags = 0;
1508                         if (debugshader)
1509                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1510                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1511                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1512                         if (vertstring && vertstring[0])
1513                         {
1514                                 if (debugshader)
1515                                 {
1516 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1517 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1518                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1519                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1520                                 }
1521                                 else
1522                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1523                                 if (vsbuffer)
1524                                 {
1525                                         vsbinsize = vsbuffer->GetBufferSize();
1526                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1527                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1528                                         vsbuffer->Release();
1529                                 }
1530                                 if (vslog)
1531                                 {
1532                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1533                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1534                                         vslog->Release();
1535                                 }
1536                         }
1537                         if (fragstring && fragstring[0])
1538                         {
1539                                 if (debugshader)
1540                                 {
1541 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1542 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1543                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1544                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1545                                 }
1546                                 else
1547                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1548                                 if (psbuffer)
1549                                 {
1550                                         psbinsize = psbuffer->GetBufferSize();
1551                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1552                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1553                                         psbuffer->Release();
1554                                 }
1555                                 if (pslog)
1556                                 {
1557                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1558                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1559                                         pslog->Release();
1560                                 }
1561                         }
1562                         Sys_UnloadLibrary(&d3dx9_dll);
1563                 }
1564                 else
1565                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1566         }
1567         if (vsbin && psbin)
1568         {
1569                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1570                 if (FAILED(vsresult))
1571                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1572                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1573                 if (FAILED(psresult))
1574                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1575         }
1576         // free the shader data
1577         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1578         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1579 }
1580
1581 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1582 {
1583         int i;
1584         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1585         int vertstring_length = 0;
1586         int geomstring_length = 0;
1587         int fragstring_length = 0;
1588         char *t;
1589         char *vertexstring, *geometrystring, *fragmentstring;
1590         char *vertstring, *geomstring, *fragstring;
1591         char permutationname[256];
1592         char cachename[256];
1593         int vertstrings_count = 0;
1594         int geomstrings_count = 0;
1595         int fragstrings_count = 0;
1596         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1597         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1598         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1599
1600         if (p->compiled)
1601                 return;
1602         p->compiled = true;
1603         p->vertexshader = NULL;
1604         p->pixelshader = NULL;
1605
1606         permutationname[0] = 0;
1607         cachename[0] = 0;
1608         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1609         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1610         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1611
1612         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1613         strlcat(cachename, "hlsl/", sizeof(cachename));
1614
1615         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1616         vertstrings_count = 0;
1617         geomstrings_count = 0;
1618         fragstrings_count = 0;
1619         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1620         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1621         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1622
1623         // the first pretext is which type of shader to compile as
1624         // (later these will all be bound together as a program object)
1625         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1626         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1627         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1628
1629         // the second pretext is the mode (for example a light source)
1630         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1631         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1632         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1633         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1634         strlcat(cachename, modeinfo->name, sizeof(cachename));
1635
1636         // now add all the permutation pretexts
1637         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1638         {
1639                 if (permutation & (1<<i))
1640                 {
1641                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1642                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1643                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1644                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1645                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1646                 }
1647                 else
1648                 {
1649                         // keep line numbers correct
1650                         vertstrings_list[vertstrings_count++] = "\n";
1651                         geomstrings_list[geomstrings_count++] = "\n";
1652                         fragstrings_list[fragstrings_count++] = "\n";
1653                 }
1654         }
1655
1656         // add static parms
1657         R_CompileShader_AddStaticParms(mode, permutation);
1658         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659         vertstrings_count += shaderstaticparms_count;
1660         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1661         geomstrings_count += shaderstaticparms_count;
1662         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663         fragstrings_count += shaderstaticparms_count;
1664
1665         // replace spaces in the cachename with _ characters
1666         for (i = 0;cachename[i];i++)
1667                 if (cachename[i] == ' ')
1668                         cachename[i] = '_';
1669
1670         // now append the shader text itself
1671         vertstrings_list[vertstrings_count++] = vertexstring;
1672         geomstrings_list[geomstrings_count++] = geometrystring;
1673         fragstrings_list[fragstrings_count++] = fragmentstring;
1674
1675         // if any sources were NULL, clear the respective list
1676         if (!vertexstring)
1677                 vertstrings_count = 0;
1678         if (!geometrystring)
1679                 geomstrings_count = 0;
1680         if (!fragmentstring)
1681                 fragstrings_count = 0;
1682
1683         vertstring_length = 0;
1684         for (i = 0;i < vertstrings_count;i++)
1685                 vertstring_length += strlen(vertstrings_list[i]);
1686         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1687         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1688                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1689
1690         geomstring_length = 0;
1691         for (i = 0;i < geomstrings_count;i++)
1692                 geomstring_length += strlen(geomstrings_list[i]);
1693         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1694         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1695                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1696
1697         fragstring_length = 0;
1698         for (i = 0;i < fragstrings_count;i++)
1699                 fragstring_length += strlen(fragstrings_list[i]);
1700         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1701         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1702                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1703
1704         // try to load the cached shader, or generate one
1705         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1706
1707         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1708                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1709         else
1710                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1711
1712         // free the strings
1713         if (vertstring)
1714                 Mem_Free(vertstring);
1715         if (geomstring)
1716                 Mem_Free(geomstring);
1717         if (fragstring)
1718                 Mem_Free(fragstring);
1719         if (vertexstring)
1720                 Mem_Free(vertexstring);
1721         if (geometrystring)
1722                 Mem_Free(geometrystring);
1723         if (fragmentstring)
1724                 Mem_Free(fragmentstring);
1725 }
1726
1727 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1728 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1729 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);}
1730 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);}
1731 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);}
1732 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);}
1733
1734 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1735 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1736 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);}
1737 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);}
1738 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);}
1739 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);}
1740
1741 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1742 {
1743         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1744         if (r_hlsl_permutation != perm)
1745         {
1746                 r_hlsl_permutation = perm;
1747                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1748                 {
1749                         if (!r_hlsl_permutation->compiled)
1750                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1751                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1752                         {
1753                                 // remove features until we find a valid permutation
1754                                 int i;
1755                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1756                                 {
1757                                         // reduce i more quickly whenever it would not remove any bits
1758                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1759                                         if (!(permutation & j))
1760                                                 continue;
1761                                         permutation -= j;
1762                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1763                                         if (!r_hlsl_permutation->compiled)
1764                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1765                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1766                                                 break;
1767                                 }
1768                                 if (i >= SHADERPERMUTATION_COUNT)
1769                                 {
1770                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1771                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1772                                         return; // no bit left to clear, entire mode is broken
1773                                 }
1774                         }
1775                 }
1776                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1777                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1778         }
1779         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1780         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1781         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1782 }
1783 #endif
1784
1785 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1786 {
1787         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1788         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1789         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1790         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1791 }
1792
1793 void R_GLSL_Restart_f(void)
1794 {
1795         unsigned int i, limit;
1796         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1797                 Mem_Free(glslshaderstring);
1798         glslshaderstring = NULL;
1799         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1800                 Mem_Free(hlslshaderstring);
1801         hlslshaderstring = NULL;
1802         switch(vid.renderpath)
1803         {
1804         case RENDERPATH_D3D9:
1805 #ifdef SUPPORTD3D
1806                 {
1807                         r_hlsl_permutation_t *p;
1808                         r_hlsl_permutation = NULL;
1809                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1810                         for (i = 0;i < limit;i++)
1811                         {
1812                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1813                                 {
1814                                         if (p->vertexshader)
1815                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1816                                         if (p->pixelshader)
1817                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1818                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1819                                 }
1820                         }
1821                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1822                 }
1823 #endif
1824                 break;
1825         case RENDERPATH_D3D10:
1826                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1827                 break;
1828         case RENDERPATH_D3D11:
1829                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1830                 break;
1831         case RENDERPATH_GL20:
1832         case RENDERPATH_GLES2:
1833                 {
1834                         r_glsl_permutation_t *p;
1835                         r_glsl_permutation = NULL;
1836                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1837                         for (i = 0;i < limit;i++)
1838                         {
1839                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1840                                 {
1841                                         GL_Backend_FreeProgram(p->program);
1842                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1843                                 }
1844                         }
1845                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1846                 }
1847                 break;
1848         case RENDERPATH_GL11:
1849         case RENDERPATH_GL13:
1850         case RENDERPATH_GLES1:
1851                 break;
1852         case RENDERPATH_SOFT:
1853                 break;
1854         }
1855 }
1856
1857 void R_GLSL_DumpShader_f(void)
1858 {
1859         int i;
1860         qfile_t *file;
1861
1862         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1863         if (file)
1864         {
1865                 FS_Print(file, "/* The engine may define the following macros:\n");
1866                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1867                 for (i = 0;i < SHADERMODE_COUNT;i++)
1868                         FS_Print(file, glslshadermodeinfo[i].pretext);
1869                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1870                         FS_Print(file, shaderpermutationinfo[i].pretext);
1871                 FS_Print(file, "*/\n");
1872                 FS_Print(file, builtinshaderstring);
1873                 FS_Close(file);
1874                 Con_Printf("glsl/default.glsl written\n");
1875         }
1876         else
1877                 Con_Printf("failed to write to glsl/default.glsl\n");
1878
1879         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1880         if (file)
1881         {
1882                 FS_Print(file, "/* The engine may define the following macros:\n");
1883                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1884                 for (i = 0;i < SHADERMODE_COUNT;i++)
1885                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1886                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1887                         FS_Print(file, shaderpermutationinfo[i].pretext);
1888                 FS_Print(file, "*/\n");
1889                 FS_Print(file, builtinhlslshaderstring);
1890                 FS_Close(file);
1891                 Con_Printf("hlsl/default.hlsl written\n");
1892         }
1893         else
1894                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1895 }
1896
1897 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy)
1898 {
1899         unsigned int permutation = 0;
1900         if (r_trippy.integer && !notrippy)
1901                 permutation |= SHADERPERMUTATION_TRIPPY;
1902         permutation |= SHADERPERMUTATION_VIEWTINT;
1903         if (first)
1904                 permutation |= SHADERPERMUTATION_DIFFUSE;
1905         if (second)
1906                 permutation |= SHADERPERMUTATION_SPECULAR;
1907         if (texturemode == GL_MODULATE)
1908                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1909         else if (texturemode == GL_ADD)
1910                 permutation |= SHADERPERMUTATION_GLOW;
1911         else if (texturemode == GL_DECAL)
1912                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1913         if (!second)
1914                 texturemode = GL_MODULATE;
1915         if (vid.allowalphatocoverage)
1916                 GL_AlphaToCoverage(false);
1917         switch (vid.renderpath)
1918         {
1919         case RENDERPATH_D3D9:
1920 #ifdef SUPPORTD3D
1921                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1922                 R_Mesh_TexBind(GL20TU_FIRST , first );
1923                 R_Mesh_TexBind(GL20TU_SECOND, second);
1924 #endif
1925                 break;
1926         case RENDERPATH_D3D10:
1927                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1928                 break;
1929         case RENDERPATH_D3D11:
1930                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1931                 break;
1932         case RENDERPATH_GL20:
1933         case RENDERPATH_GLES2:
1934                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1935                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1936                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1937                 break;
1938         case RENDERPATH_GL13:
1939         case RENDERPATH_GLES1:
1940                 R_Mesh_TexBind(0, first );
1941                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1942                 R_Mesh_TexBind(1, second);
1943                 if (second)
1944                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1945                 break;
1946         case RENDERPATH_GL11:
1947                 R_Mesh_TexBind(0, first );
1948                 break;
1949         case RENDERPATH_SOFT:
1950                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1951                 R_Mesh_TexBind(GL20TU_FIRST , first );
1952                 R_Mesh_TexBind(GL20TU_SECOND, second);
1953                 break;
1954         }
1955 }
1956
1957 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1958 {
1959         unsigned int permutation = 0;
1960         if (r_trippy.integer && !notrippy)
1961                 permutation |= SHADERPERMUTATION_TRIPPY;
1962         if (vid.allowalphatocoverage)
1963                 GL_AlphaToCoverage(false);
1964         switch (vid.renderpath)
1965         {
1966         case RENDERPATH_D3D9:
1967 #ifdef SUPPORTD3D
1968                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1969 #endif
1970                 break;
1971         case RENDERPATH_D3D10:
1972                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1973                 break;
1974         case RENDERPATH_D3D11:
1975                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1976                 break;
1977         case RENDERPATH_GL20:
1978         case RENDERPATH_GLES2:
1979                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1980                 break;
1981         case RENDERPATH_GL13:
1982         case RENDERPATH_GLES1:
1983                 R_Mesh_TexBind(0, 0);
1984                 R_Mesh_TexBind(1, 0);
1985                 break;
1986         case RENDERPATH_GL11:
1987                 R_Mesh_TexBind(0, 0);
1988                 break;
1989         case RENDERPATH_SOFT:
1990                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1991                 break;
1992         }
1993 }
1994
1995 void R_SetupShader_ShowDepth(qboolean notrippy)
1996 {
1997         int permutation = 0;
1998         if (r_trippy.integer && !notrippy)
1999                 permutation |= SHADERPERMUTATION_TRIPPY;
2000         if (r_trippy.integer)
2001                 permutation |= SHADERPERMUTATION_TRIPPY;
2002         if (vid.allowalphatocoverage)
2003                 GL_AlphaToCoverage(false);
2004         switch (vid.renderpath)
2005         {
2006         case RENDERPATH_D3D9:
2007 #ifdef SUPPORTHLSL
2008                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2009 #endif
2010                 break;
2011         case RENDERPATH_D3D10:
2012                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2013                 break;
2014         case RENDERPATH_D3D11:
2015                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2016                 break;
2017         case RENDERPATH_GL20:
2018         case RENDERPATH_GLES2:
2019                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2020                 break;
2021         case RENDERPATH_GL13:
2022         case RENDERPATH_GLES1:
2023                 break;
2024         case RENDERPATH_GL11:
2025                 break;
2026         case RENDERPATH_SOFT:
2027                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2028                 break;
2029         }
2030 }
2031
2032 extern qboolean r_shadow_usingdeferredprepass;
2033 extern cvar_t r_shadow_deferred_8bitrange;
2034 extern rtexture_t *r_shadow_attenuationgradienttexture;
2035 extern rtexture_t *r_shadow_attenuation2dtexture;
2036 extern rtexture_t *r_shadow_attenuation3dtexture;
2037 extern qboolean r_shadow_usingshadowmap2d;
2038 extern qboolean r_shadow_usingshadowmaportho;
2039 extern float r_shadow_shadowmap_texturescale[2];
2040 extern float r_shadow_shadowmap_parameters[4];
2041 extern qboolean r_shadow_shadowmapvsdct;
2042 extern qboolean r_shadow_shadowmapsampler;
2043 extern int r_shadow_shadowmappcf;
2044 extern rtexture_t *r_shadow_shadowmap2dtexture;
2045 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2046 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2047 extern matrix4x4_t r_shadow_shadowmapmatrix;
2048 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2049 extern int r_shadow_prepass_width;
2050 extern int r_shadow_prepass_height;
2051 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2052 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2053 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2054 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2055 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2056
2057 #define BLENDFUNC_ALLOWS_COLORMOD      1
2058 #define BLENDFUNC_ALLOWS_FOG           2
2059 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2060 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2061 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2062 static int R_BlendFuncFlags(int src, int dst)
2063 {
2064         int r = 0;
2065
2066         // a blendfunc allows colormod if:
2067         // a) it can never keep the destination pixel invariant, or
2068         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2069         // this is to prevent unintended side effects from colormod
2070
2071         // a blendfunc allows fog if:
2072         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2073         // this is to prevent unintended side effects from fog
2074
2075         // these checks are the output of fogeval.pl
2076
2077         r |= BLENDFUNC_ALLOWS_COLORMOD;
2078         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2079         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2080         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2081         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2082         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2084         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2085         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2086         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2087         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2088         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2089         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2090         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2091         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2095         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2096         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2098         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099
2100         return r;
2101 }
2102
2103 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)
2104 {
2105         // select a permutation of the lighting shader appropriate to this
2106         // combination of texture, entity, light source, and fogging, only use the
2107         // minimum features necessary to avoid wasting rendering time in the
2108         // fragment shader on features that are not being used
2109         unsigned int permutation = 0;
2110         unsigned int mode = 0;
2111         int blendfuncflags;
2112         static float dummy_colormod[3] = {1, 1, 1};
2113         float *colormod = rsurface.colormod;
2114         float m16f[16];
2115         matrix4x4_t tempmatrix;
2116         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2117         if (r_trippy.integer && !notrippy)
2118                 permutation |= SHADERPERMUTATION_TRIPPY;
2119         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2120                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2121         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2122                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2123         if (rsurfacepass == RSURFPASS_BACKGROUND)
2124         {
2125                 // distorted background
2126                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2127                 {
2128                         mode = SHADERMODE_WATER;
2129                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2130                         {
2131                                 // this is the right thing to do for wateralpha
2132                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2133                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2134                         }
2135                         else
2136                         {
2137                                 // this is the right thing to do for entity alpha
2138                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2139                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2140                         }
2141                 }
2142                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2143                 {
2144                         mode = SHADERMODE_REFRACTION;
2145                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2147                 }
2148                 else
2149                 {
2150                         mode = SHADERMODE_GENERIC;
2151                         permutation |= SHADERPERMUTATION_DIFFUSE;
2152                         GL_BlendFunc(GL_ONE, GL_ZERO);
2153                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2154                 }
2155                 if (vid.allowalphatocoverage)
2156                         GL_AlphaToCoverage(false);
2157         }
2158         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2159         {
2160                 if (r_glsl_offsetmapping.integer)
2161                 {
2162                         switch(rsurface.texture->offsetmapping)
2163                         {
2164                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2165                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2166                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2167                         case OFFSETMAPPING_OFF: break;
2168                         }
2169                 }
2170                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2171                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2172                 // normalmap (deferred prepass), may use alpha test on diffuse
2173                 mode = SHADERMODE_DEFERREDGEOMETRY;
2174                 GL_BlendFunc(GL_ONE, GL_ZERO);
2175                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2176                 if (vid.allowalphatocoverage)
2177                         GL_AlphaToCoverage(false);
2178         }
2179         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2180         {
2181                 if (r_glsl_offsetmapping.integer)
2182                 {
2183                         switch(rsurface.texture->offsetmapping)
2184                         {
2185                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2186                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2187                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2188                         case OFFSETMAPPING_OFF: break;
2189                         }
2190                 }
2191                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2192                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2193                 // light source
2194                 mode = SHADERMODE_LIGHTSOURCE;
2195                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2196                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2197                 if (diffusescale > 0)
2198                         permutation |= SHADERPERMUTATION_DIFFUSE;
2199                 if (specularscale > 0)
2200                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2201                 if (r_refdef.fogenabled)
2202                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2203                 if (rsurface.texture->colormapping)
2204                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2205                 if (r_shadow_usingshadowmap2d)
2206                 {
2207                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2208                         if(r_shadow_shadowmapvsdct)
2209                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2210
2211                         if (r_shadow_shadowmapsampler)
2212                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2213                         if (r_shadow_shadowmappcf > 1)
2214                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2215                         else if (r_shadow_shadowmappcf)
2216                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2217                 }
2218                 if (rsurface.texture->reflectmasktexture)
2219                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2220                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2221                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2222                 if (vid.allowalphatocoverage)
2223                         GL_AlphaToCoverage(false);
2224         }
2225         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2226         {
2227                 if (r_glsl_offsetmapping.integer)
2228                 {
2229                         switch(rsurface.texture->offsetmapping)
2230                         {
2231                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2232                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2233                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2234                         case OFFSETMAPPING_OFF: break;
2235                         }
2236                 }
2237                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2238                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2239                 // unshaded geometry (fullbright or ambient model lighting)
2240                 mode = SHADERMODE_FLATCOLOR;
2241                 ambientscale = diffusescale = specularscale = 0;
2242                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2243                         permutation |= SHADERPERMUTATION_GLOW;
2244                 if (r_refdef.fogenabled)
2245                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2246                 if (rsurface.texture->colormapping)
2247                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2248                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2249                 {
2250                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2251                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2252
2253                         if (r_shadow_shadowmapsampler)
2254                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2255                         if (r_shadow_shadowmappcf > 1)
2256                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2257                         else if (r_shadow_shadowmappcf)
2258                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2259                 }
2260                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2261                         permutation |= SHADERPERMUTATION_REFLECTION;
2262                 if (rsurface.texture->reflectmasktexture)
2263                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2264                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2265                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2266                 // when using alphatocoverage, we don't need alphakill
2267                 if (vid.allowalphatocoverage)
2268                 {
2269                         if (r_transparent_alphatocoverage.integer)
2270                         {
2271                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2272                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2273                         }
2274                         else
2275                                 GL_AlphaToCoverage(false);
2276                 }
2277         }
2278         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2279         {
2280                 if (r_glsl_offsetmapping.integer)
2281                 {
2282                         switch(rsurface.texture->offsetmapping)
2283                         {
2284                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2285                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2287                         case OFFSETMAPPING_OFF: break;
2288                         }
2289                 }
2290                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2291                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2292                 // directional model lighting
2293                 mode = SHADERMODE_LIGHTDIRECTION;
2294                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2295                         permutation |= SHADERPERMUTATION_GLOW;
2296                 permutation |= SHADERPERMUTATION_DIFFUSE;
2297                 if (specularscale > 0)
2298                         permutation |= SHADERPERMUTATION_SPECULAR;
2299                 if (r_refdef.fogenabled)
2300                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2301                 if (rsurface.texture->colormapping)
2302                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2303                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2304                 {
2305                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2306                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2307
2308                         if (r_shadow_shadowmapsampler)
2309                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2310                         if (r_shadow_shadowmappcf > 1)
2311                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2312                         else if (r_shadow_shadowmappcf)
2313                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2314                 }
2315                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2316                         permutation |= SHADERPERMUTATION_REFLECTION;
2317                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2318                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2319                 if (rsurface.texture->reflectmasktexture)
2320                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2321                 if (r_shadow_bouncegridtexture)
2322                 {
2323                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2324                         if (r_shadow_bouncegriddirectional)
2325                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2326                 }
2327                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2328                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2329                 // when using alphatocoverage, we don't need alphakill
2330                 if (vid.allowalphatocoverage)
2331                 {
2332                         if (r_transparent_alphatocoverage.integer)
2333                         {
2334                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2335                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2336                         }
2337                         else
2338                                 GL_AlphaToCoverage(false);
2339                 }
2340         }
2341         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2342         {
2343                 if (r_glsl_offsetmapping.integer)
2344                 {
2345                         switch(rsurface.texture->offsetmapping)
2346                         {
2347                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2348                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350                         case OFFSETMAPPING_OFF: break;
2351                         }
2352                 }
2353                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2354                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2355                 // ambient model lighting
2356                 mode = SHADERMODE_LIGHTDIRECTION;
2357                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2358                         permutation |= SHADERPERMUTATION_GLOW;
2359                 if (r_refdef.fogenabled)
2360                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2361                 if (rsurface.texture->colormapping)
2362                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2363                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2364                 {
2365                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2366                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2367
2368                         if (r_shadow_shadowmapsampler)
2369                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2370                         if (r_shadow_shadowmappcf > 1)
2371                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2372                         else if (r_shadow_shadowmappcf)
2373                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2374                 }
2375                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376                         permutation |= SHADERPERMUTATION_REFLECTION;
2377                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2378                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379                 if (rsurface.texture->reflectmasktexture)
2380                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381                 if (r_shadow_bouncegridtexture)
2382                 {
2383                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2384                         if (r_shadow_bouncegriddirectional)
2385                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2386                 }
2387                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2388                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2389                 // when using alphatocoverage, we don't need alphakill
2390                 if (vid.allowalphatocoverage)
2391                 {
2392                         if (r_transparent_alphatocoverage.integer)
2393                         {
2394                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2395                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2396                         }
2397                         else
2398                                 GL_AlphaToCoverage(false);
2399                 }
2400         }
2401         else
2402         {
2403                 if (r_glsl_offsetmapping.integer)
2404                 {
2405                         switch(rsurface.texture->offsetmapping)
2406                         {
2407                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2408                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410                         case OFFSETMAPPING_OFF: break;
2411                         }
2412                 }
2413                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2414                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2415                 // lightmapped wall
2416                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2417                         permutation |= SHADERPERMUTATION_GLOW;
2418                 if (r_refdef.fogenabled)
2419                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2420                 if (rsurface.texture->colormapping)
2421                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2422                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2423                 {
2424                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2425                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2426
2427                         if (r_shadow_shadowmapsampler)
2428                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2429                         if (r_shadow_shadowmappcf > 1)
2430                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2431                         else if (r_shadow_shadowmappcf)
2432                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2433                 }
2434                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2435                         permutation |= SHADERPERMUTATION_REFLECTION;
2436                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2437                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2438                 if (rsurface.texture->reflectmasktexture)
2439                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2440                 if (FAKELIGHT_ENABLED)
2441                 {
2442                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2443                         mode = SHADERMODE_FAKELIGHT;
2444                         permutation |= SHADERPERMUTATION_DIFFUSE;
2445                         if (specularscale > 0)
2446                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2447                 }
2448                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2449                 {
2450                         // deluxemapping (light direction texture)
2451                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2452                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2453                         else
2454                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2455                         permutation |= SHADERPERMUTATION_DIFFUSE;
2456                         if (specularscale > 0)
2457                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2458                 }
2459                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2460                 {
2461                         // fake deluxemapping (uniform light direction in tangentspace)
2462                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2463                         permutation |= SHADERPERMUTATION_DIFFUSE;
2464                         if (specularscale > 0)
2465                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2466                 }
2467                 else if (rsurface.uselightmaptexture)
2468                 {
2469                         // ordinary lightmapping (q1bsp, q3bsp)
2470                         mode = SHADERMODE_LIGHTMAP;
2471                 }
2472                 else
2473                 {
2474                         // ordinary vertex coloring (q3bsp)
2475                         mode = SHADERMODE_VERTEXCOLOR;
2476                 }
2477                 if (r_shadow_bouncegridtexture)
2478                 {
2479                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2480                         if (r_shadow_bouncegriddirectional)
2481                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2482                 }
2483                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2484                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2485                 // when using alphatocoverage, we don't need alphakill
2486                 if (vid.allowalphatocoverage)
2487                 {
2488                         if (r_transparent_alphatocoverage.integer)
2489                         {
2490                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2491                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2492                         }
2493                         else
2494                                 GL_AlphaToCoverage(false);
2495                 }
2496         }
2497         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2498                 colormod = dummy_colormod;
2499         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2500                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2501         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2502                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2503         switch(vid.renderpath)
2504         {
2505         case RENDERPATH_D3D9:
2506 #ifdef SUPPORTD3D
2507                 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);
2508                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2509                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2510                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2511                 if (mode == SHADERMODE_LIGHTSOURCE)
2512                 {
2513                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2514                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2515                 }
2516                 else
2517                 {
2518                         if (mode == SHADERMODE_LIGHTDIRECTION)
2519                         {
2520                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2521                         }
2522                 }
2523                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2524                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2525                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2526                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2527                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2528
2529                 if (mode == SHADERMODE_LIGHTSOURCE)
2530                 {
2531                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2532                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2533                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2536
2537                         // additive passes are only darkened by fog, not tinted
2538                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2539                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2540                 }
2541                 else
2542                 {
2543                         if (mode == SHADERMODE_FLATCOLOR)
2544                         {
2545                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2546                         }
2547                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2548                         {
2549                                 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]);
2550                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2551                                 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);
2552                                 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);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2556                         }
2557                         else
2558                         {
2559                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2561                                 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);
2562                                 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);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2564                         }
2565                         // additive passes are only darkened by fog, not tinted
2566                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2567                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2568                         else
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2570                         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);
2571                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2572                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2574                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2575                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2576                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2577                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2578                         if (mode == SHADERMODE_WATER)
2579                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2580                 }
2581                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2582                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2583                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2584                 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));
2585                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2586                 if (rsurface.texture->pantstexture)
2587                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2588                 else
2589                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2590                 if (rsurface.texture->shirttexture)
2591                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2592                 else
2593                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2594                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2595                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2596                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2597                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2598                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2599                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2600                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2601                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2602                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2603                         );
2604                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2605                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2606
2607                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2608                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2609                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2610                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2611                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2612                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2613                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2614                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2615                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2616                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2617                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2618                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2619                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2620                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2621                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2622                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2623                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2624                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2625                 {
2626                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2627                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2628                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2629                 }
2630                 else
2631                 {
2632                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2633                 }
2634 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2635 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2636                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2637                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2638                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2639                 {
2640                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2641                         if (rsurface.rtlight)
2642                         {
2643                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2644                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2645                         }
2646                 }
2647 #endif
2648                 break;
2649         case RENDERPATH_D3D10:
2650                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2651                 break;
2652         case RENDERPATH_D3D11:
2653                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2654                 break;
2655         case RENDERPATH_GL20:
2656         case RENDERPATH_GLES2:
2657                 if (!vid.useinterleavedarrays)
2658                 {
2659                         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);
2660                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2661                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2662                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2663                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2664                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2665                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2666                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2667                 }
2668                 else
2669                 {
2670                         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);
2671                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2672                 }
2673                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2674                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2675                 if (mode == SHADERMODE_LIGHTSOURCE)
2676                 {
2677                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2678                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2679                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2680                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2681                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2682                         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);
2683         
2684                         // additive passes are only darkened by fog, not tinted
2685                         if (r_glsl_permutation->loc_FogColor >= 0)
2686                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2687                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2688                 }
2689                 else
2690                 {
2691                         if (mode == SHADERMODE_FLATCOLOR)
2692                         {
2693                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2694                         }
2695                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2696                         {
2697                                 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]);
2698                                 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]);
2699                                 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);
2700                                 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);
2701                                 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);
2702                                 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]);
2703                                 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]);
2704                         }
2705                         else
2706                         {
2707                                 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]);
2708                                 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]);
2709                                 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);
2710                                 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);
2711                                 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);
2712                         }
2713                         // additive passes are only darkened by fog, not tinted
2714                         if (r_glsl_permutation->loc_FogColor >= 0)
2715                         {
2716                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2717                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2718                                 else
2719                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2720                         }
2721                         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);
2722                         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]);
2723                         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]);
2724                         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]);
2725                         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]);
2726                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2727                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2728                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2729                         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]);
2730                 }
2731                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2732                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2733                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2734                 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]);
2735                 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]);
2736
2737                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2738                 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));
2739                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2740                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2741                 {
2742                         if (rsurface.texture->pantstexture)
2743                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2744                         else
2745                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2746                 }
2747                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2748                 {
2749                         if (rsurface.texture->shirttexture)
2750                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2751                         else
2752                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2753                 }
2754                 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]);
2755                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2756                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2757                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2758                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2759                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2760                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2761                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2762                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2763                         );
2764                 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]);
2765                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2766                 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);}
2767                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2768
2769                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2770                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2771                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2772                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2773                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2774                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2775                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2776                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2777                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2778                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2779                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2780                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2781                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2782                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2783                 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);
2784                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2785                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2786                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2787                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2788                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2789                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2790                 {
2791                         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);
2792                         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);
2793                         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);
2794                 }
2795                 else
2796                 {
2797                         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);
2798                 }
2799                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2800                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2801                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2802                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2803                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2804                 {
2805                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2806                         if (rsurface.rtlight)
2807                         {
2808                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2809                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2810                         }
2811                 }
2812                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2813                 CHECKGLERROR
2814                 break;
2815         case RENDERPATH_GL11:
2816         case RENDERPATH_GL13:
2817         case RENDERPATH_GLES1:
2818                 break;
2819         case RENDERPATH_SOFT:
2820                 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);
2821                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2822                 R_SetupShader_SetPermutationSoft(mode, permutation);
2823                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2824                 if (mode == SHADERMODE_LIGHTSOURCE)
2825                 {
2826                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2827                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2828                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2829                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2830                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2831                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2832         
2833                         // additive passes are only darkened by fog, not tinted
2834                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2835                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2836                 }
2837                 else
2838                 {
2839                         if (mode == SHADERMODE_FLATCOLOR)
2840                         {
2841                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2842                         }
2843                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2844                         {
2845                                 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]);
2846                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2847                                 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);
2848                                 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);
2849                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2850                                 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]);
2851                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2852                         }
2853                         else
2854                         {
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2856                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2857                                 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);
2858                                 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);
2859                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2860                         }
2861                         // additive passes are only darkened by fog, not tinted
2862                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2864                         else
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2866                         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);
2867                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2868                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2869                         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]);
2870                         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]);
2871                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2872                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2873                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2874                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2875                 }
2876                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2877                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2878                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2879                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2880                 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]);
2881
2882                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2883                 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));
2884                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2885                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2886                 {
2887                         if (rsurface.texture->pantstexture)
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2889                         else
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2891                 }
2892                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2893                 {
2894                         if (rsurface.texture->shirttexture)
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2896                         else
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2898                 }
2899                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2900                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2901                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2902                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2903                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2904                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2905                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2906                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2907                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2908                         );
2909                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2910                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2911
2912                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2913                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2914                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2915                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2916                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2917                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2918                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2919                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2920                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2921                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2922                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2923                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2924                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2925                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2926                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2927                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2928                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2929                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2930                 {
2931                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2932                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2933                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2934                 }
2935                 else
2936                 {
2937                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2938                 }
2939 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2940 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2941                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2942                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2943                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2944                 {
2945                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2946                         if (rsurface.rtlight)
2947                         {
2948                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2949                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2950                         }
2951                 }
2952                 break;
2953         }
2954 }
2955
2956 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2957 {
2958         // select a permutation of the lighting shader appropriate to this
2959         // combination of texture, entity, light source, and fogging, only use the
2960         // minimum features necessary to avoid wasting rendering time in the
2961         // fragment shader on features that are not being used
2962         unsigned int permutation = 0;
2963         unsigned int mode = 0;
2964         const float *lightcolorbase = rtlight->currentcolor;
2965         float ambientscale = rtlight->ambientscale;
2966         float diffusescale = rtlight->diffusescale;
2967         float specularscale = rtlight->specularscale;
2968         // this is the location of the light in view space
2969         vec3_t viewlightorigin;
2970         // this transforms from view space (camera) to light space (cubemap)
2971         matrix4x4_t viewtolight;
2972         matrix4x4_t lighttoview;
2973         float viewtolight16f[16];
2974         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2975         // light source
2976         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2977         if (rtlight->currentcubemap != r_texture_whitecube)
2978                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2979         if (diffusescale > 0)
2980                 permutation |= SHADERPERMUTATION_DIFFUSE;
2981         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2982                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2983         if (r_shadow_usingshadowmap2d)
2984         {
2985                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2986                 if (r_shadow_shadowmapvsdct)
2987                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2988
2989                 if (r_shadow_shadowmapsampler)
2990                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2991                 if (r_shadow_shadowmappcf > 1)
2992                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2993                 else if (r_shadow_shadowmappcf)
2994                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2995         }
2996         if (vid.allowalphatocoverage)
2997                 GL_AlphaToCoverage(false);
2998         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2999         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3000         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3001         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3002         switch(vid.renderpath)
3003         {
3004         case RENDERPATH_D3D9:
3005 #ifdef SUPPORTD3D
3006                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3007                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3008                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3009                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3010                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3011                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3012                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3013                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3014                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3015                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3016                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3017
3018                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3019                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3020                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3021                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3022                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3023                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3024 #endif
3025                 break;
3026         case RENDERPATH_D3D10:
3027                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3028                 break;
3029         case RENDERPATH_D3D11:
3030                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3031                 break;
3032         case RENDERPATH_GL20:
3033         case RENDERPATH_GLES2:
3034                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3035                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3036                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3037                 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);
3038                 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);
3039                 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);
3040                 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]);
3041                 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]);
3042                 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));
3043                 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]);
3044                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3045
3046                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3047                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3048                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3049                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3050                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3051                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3052                 break;
3053         case RENDERPATH_GL11:
3054         case RENDERPATH_GL13:
3055         case RENDERPATH_GLES1:
3056                 break;
3057         case RENDERPATH_SOFT:
3058                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3059                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3060                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3061                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3062                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3063                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3064                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3065                 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]);
3066                 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));
3067                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3068                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3069
3070                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3071                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3072                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3073                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3074                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3075                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3076                 break;
3077         }
3078 }
3079
3080 #define SKINFRAME_HASH 1024
3081
3082 typedef struct
3083 {
3084         int loadsequence; // incremented each level change
3085         memexpandablearray_t array;
3086         skinframe_t *hash[SKINFRAME_HASH];
3087 }
3088 r_skinframe_t;
3089 r_skinframe_t r_skinframe;
3090
3091 void R_SkinFrame_PrepareForPurge(void)
3092 {
3093         r_skinframe.loadsequence++;
3094         // wrap it without hitting zero
3095         if (r_skinframe.loadsequence >= 200)
3096                 r_skinframe.loadsequence = 1;
3097 }
3098
3099 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3100 {
3101         if (!skinframe)
3102                 return;
3103         // mark the skinframe as used for the purging code
3104         skinframe->loadsequence = r_skinframe.loadsequence;
3105 }
3106
3107 void R_SkinFrame_Purge(void)
3108 {
3109         int i;
3110         skinframe_t *s;
3111         for (i = 0;i < SKINFRAME_HASH;i++)
3112         {
3113                 for (s = r_skinframe.hash[i];s;s = s->next)
3114                 {
3115                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3116                         {
3117                                 if (s->merged == s->base)
3118                                         s->merged = NULL;
3119                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3120                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3121                                 R_PurgeTexture(s->merged);s->merged = NULL;
3122                                 R_PurgeTexture(s->base  );s->base   = NULL;
3123                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3124                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3125                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3126                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3127                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3128                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3129                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3130                                 s->loadsequence = 0;
3131                         }
3132                 }
3133         }
3134 }
3135
3136 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3137         skinframe_t *item;
3138         char basename[MAX_QPATH];
3139
3140         Image_StripImageExtension(name, basename, sizeof(basename));
3141
3142         if( last == NULL ) {
3143                 int hashindex;
3144                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3145                 item = r_skinframe.hash[hashindex];
3146         } else {
3147                 item = last->next;
3148         }
3149
3150         // linearly search through the hash bucket
3151         for( ; item ; item = item->next ) {
3152                 if( !strcmp( item->basename, basename ) ) {
3153                         return item;
3154                 }
3155         }
3156         return NULL;
3157 }
3158
3159 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3160 {
3161         skinframe_t *item;
3162         int hashindex;
3163         char basename[MAX_QPATH];
3164
3165         Image_StripImageExtension(name, basename, sizeof(basename));
3166
3167         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3168         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3169                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3170                         break;
3171
3172         if (!item) {
3173                 rtexture_t *dyntexture;
3174                 // check whether its a dynamic texture
3175                 dyntexture = CL_GetDynTexture( basename );
3176                 if (!add && !dyntexture)
3177                         return NULL;
3178                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3179                 memset(item, 0, sizeof(*item));
3180                 strlcpy(item->basename, basename, sizeof(item->basename));
3181                 item->base = dyntexture; // either NULL or dyntexture handle
3182                 item->textureflags = textureflags;
3183                 item->comparewidth = comparewidth;
3184                 item->compareheight = compareheight;
3185                 item->comparecrc = comparecrc;
3186                 item->next = r_skinframe.hash[hashindex];
3187                 r_skinframe.hash[hashindex] = item;
3188         }
3189         else if( item->base == NULL )
3190         {
3191                 rtexture_t *dyntexture;
3192                 // check whether its a dynamic texture
3193                 // 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]
3194                 dyntexture = CL_GetDynTexture( basename );
3195                 item->base = dyntexture; // either NULL or dyntexture handle
3196         }
3197
3198         R_SkinFrame_MarkUsed(item);
3199         return item;
3200 }
3201
3202 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3203         { \
3204                 unsigned long long avgcolor[5], wsum; \
3205                 int pix, comp, w; \
3206                 avgcolor[0] = 0; \
3207                 avgcolor[1] = 0; \
3208                 avgcolor[2] = 0; \
3209                 avgcolor[3] = 0; \
3210                 avgcolor[4] = 0; \
3211                 wsum = 0; \
3212                 for(pix = 0; pix < cnt; ++pix) \
3213                 { \
3214                         w = 0; \
3215                         for(comp = 0; comp < 3; ++comp) \
3216                                 w += getpixel; \
3217                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3218                         { \
3219                                 ++wsum; \
3220                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3221                                 w = getpixel; \
3222                                 for(comp = 0; comp < 3; ++comp) \
3223                                         avgcolor[comp] += getpixel * w; \
3224                                 avgcolor[3] += w; \
3225                         } \
3226                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3227                         avgcolor[4] += getpixel; \
3228                 } \
3229                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3230                         avgcolor[3] = 1; \
3231                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3232                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3233                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3234                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3235         }
3236
3237 extern cvar_t gl_picmip;
3238 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3239 {
3240         int j;
3241         unsigned char *pixels;
3242         unsigned char *bumppixels;
3243         unsigned char *basepixels = NULL;
3244         int basepixels_width = 0;
3245         int basepixels_height = 0;
3246         skinframe_t *skinframe;
3247         rtexture_t *ddsbase = NULL;
3248         qboolean ddshasalpha = false;
3249         float ddsavgcolor[4];
3250         char basename[MAX_QPATH];
3251         int miplevel = R_PicmipForFlags(textureflags);
3252         int savemiplevel = miplevel;
3253         int mymiplevel;
3254
3255         if (cls.state == ca_dedicated)
3256                 return NULL;
3257
3258         // return an existing skinframe if already loaded
3259         // if loading of the first image fails, don't make a new skinframe as it
3260         // would cause all future lookups of this to be missing
3261         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3262         if (skinframe && skinframe->base)
3263                 return skinframe;
3264
3265         Image_StripImageExtension(name, basename, sizeof(basename));
3266
3267         // check for DDS texture file first
3268         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3269         {
3270                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3271                 if (basepixels == NULL)
3272                         return NULL;
3273         }
3274
3275         // FIXME handle miplevel
3276
3277         if (developer_loading.integer)
3278                 Con_Printf("loading skin \"%s\"\n", name);
3279
3280         // we've got some pixels to store, so really allocate this new texture now
3281         if (!skinframe)
3282                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3283         skinframe->stain = NULL;
3284         skinframe->merged = NULL;
3285         skinframe->base = NULL;
3286         skinframe->pants = NULL;
3287         skinframe->shirt = NULL;
3288         skinframe->nmap = NULL;
3289         skinframe->gloss = NULL;
3290         skinframe->glow = NULL;
3291         skinframe->fog = NULL;
3292         skinframe->reflect = NULL;
3293         skinframe->hasalpha = false;
3294
3295         if (ddsbase)
3296         {
3297                 skinframe->base = ddsbase;
3298                 skinframe->hasalpha = ddshasalpha;
3299                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3300                 if (r_loadfog && skinframe->hasalpha)
3301                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3302                 //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]);
3303         }
3304         else
3305         {
3306                 basepixels_width = image_width;
3307                 basepixels_height = image_height;
3308                 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);
3309                 if (textureflags & TEXF_ALPHA)
3310                 {
3311                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3312                         {
3313                                 if (basepixels[j] < 255)
3314                                 {
3315                                         skinframe->hasalpha = true;
3316                                         break;
3317                                 }
3318                         }
3319                         if (r_loadfog && skinframe->hasalpha)
3320                         {
3321                                 // has transparent pixels
3322                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3323                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3324                                 {
3325                                         pixels[j+0] = 255;
3326                                         pixels[j+1] = 255;
3327                                         pixels[j+2] = 255;
3328                                         pixels[j+3] = basepixels[j+3];
3329                                 }
3330                                 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);
3331                                 Mem_Free(pixels);
3332                         }
3333                 }
3334                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3335                 //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]);
3336                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3337                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3338                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3339                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3340         }
3341
3342         if (r_loaddds)
3343         {
3344                 mymiplevel = savemiplevel;
3345                 if (r_loadnormalmap)
3346                         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);
3347                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3348                 if (r_loadgloss)
3349                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3350                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3351                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3352                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3353         }
3354
3355         // _norm is the name used by tenebrae and has been adopted as standard
3356         if (r_loadnormalmap && skinframe->nmap == NULL)
3357         {
3358                 mymiplevel = savemiplevel;
3359                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3360                 {
3361                         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);
3362                         Mem_Free(pixels);
3363                         pixels = NULL;
3364                 }
3365                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3366                 {
3367                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3368                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3369                         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);
3370                         Mem_Free(pixels);
3371                         Mem_Free(bumppixels);
3372                 }
3373                 else if (r_shadow_bumpscale_basetexture.value > 0)
3374                 {
3375                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3376                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3377                         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);
3378                         Mem_Free(pixels);
3379                 }
3380                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3381                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3382         }
3383
3384         // _luma is supported only for tenebrae compatibility
3385         // _glow is the preferred name
3386         mymiplevel = savemiplevel;
3387         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))))
3388         {
3389                 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);
3390                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3391                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3392                 Mem_Free(pixels);pixels = NULL;
3393         }
3394
3395         mymiplevel = savemiplevel;
3396         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3397         {
3398                 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);
3399                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3400                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3401                 Mem_Free(pixels);
3402                 pixels = NULL;
3403         }
3404
3405         mymiplevel = savemiplevel;
3406         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3407         {
3408                 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);
3409                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3410                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3411                 Mem_Free(pixels);
3412                 pixels = NULL;
3413         }
3414
3415         mymiplevel = savemiplevel;
3416         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3417         {
3418                 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);
3419                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3420                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3421                 Mem_Free(pixels);
3422                 pixels = NULL;
3423         }
3424
3425         mymiplevel = savemiplevel;
3426         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3427         {
3428                 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);
3429                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3430                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3431                 Mem_Free(pixels);
3432                 pixels = NULL;
3433         }
3434
3435         if (basepixels)
3436                 Mem_Free(basepixels);
3437
3438         return skinframe;
3439 }
3440
3441 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3442 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3443 {
3444         int i;
3445         unsigned char *temp1, *temp2;
3446         skinframe_t *skinframe;
3447
3448         if (cls.state == ca_dedicated)
3449                 return NULL;
3450
3451         // if already loaded just return it, otherwise make a new skinframe
3452         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3453         if (skinframe && skinframe->base)
3454                 return skinframe;
3455
3456         skinframe->stain = NULL;
3457         skinframe->merged = NULL;
3458         skinframe->base = NULL;
3459         skinframe->pants = NULL;
3460         skinframe->shirt = NULL;
3461         skinframe->nmap = NULL;
3462         skinframe->gloss = NULL;
3463         skinframe->glow = NULL;
3464         skinframe->fog = NULL;
3465         skinframe->reflect = NULL;
3466         skinframe->hasalpha = false;
3467
3468         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3469         if (!skindata)
3470                 return NULL;
3471
3472         if (developer_loading.integer)
3473                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3474
3475         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3476         {
3477                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3478                 temp2 = temp1 + width * height * 4;
3479                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3480                 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);
3481                 Mem_Free(temp1);
3482         }
3483         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3484         if (textureflags & TEXF_ALPHA)
3485         {
3486                 for (i = 3;i < width * height * 4;i += 4)
3487                 {
3488                         if (skindata[i] < 255)
3489                         {
3490                                 skinframe->hasalpha = true;
3491                                 break;
3492                         }
3493                 }
3494                 if (r_loadfog && skinframe->hasalpha)
3495                 {
3496                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3497                         memcpy(fogpixels, skindata, width * height * 4);
3498                         for (i = 0;i < width * height * 4;i += 4)
3499                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3500                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3501                         Mem_Free(fogpixels);
3502                 }
3503         }
3504
3505         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3506         //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]);
3507
3508         return skinframe;
3509 }
3510
3511 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3512 {
3513         int i;
3514         int featuresmask;
3515         skinframe_t *skinframe;
3516
3517         if (cls.state == ca_dedicated)
3518                 return NULL;
3519
3520         // if already loaded just return it, otherwise make a new skinframe
3521         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3522         if (skinframe && skinframe->base)
3523                 return skinframe;
3524
3525         skinframe->stain = NULL;
3526         skinframe->merged = NULL;
3527         skinframe->base = NULL;
3528         skinframe->pants = NULL;
3529         skinframe->shirt = NULL;
3530         skinframe->nmap = NULL;
3531         skinframe->gloss = NULL;
3532         skinframe->glow = NULL;
3533         skinframe->fog = NULL;
3534         skinframe->reflect = NULL;
3535         skinframe->hasalpha = false;
3536
3537         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3538         if (!skindata)
3539                 return NULL;
3540
3541         if (developer_loading.integer)
3542                 Con_Printf("loading quake skin \"%s\"\n", name);
3543
3544         // 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)
3545         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3546         memcpy(skinframe->qpixels, skindata, width*height);
3547         skinframe->qwidth = width;
3548         skinframe->qheight = height;
3549
3550         featuresmask = 0;
3551         for (i = 0;i < width * height;i++)
3552                 featuresmask |= palette_featureflags[skindata[i]];
3553
3554         skinframe->hasalpha = false;
3555         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3556         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3557         skinframe->qgeneratemerged = true;
3558         skinframe->qgeneratebase = skinframe->qhascolormapping;
3559         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3560
3561         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3562         //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]);
3563
3564         return skinframe;
3565 }
3566
3567 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3568 {
3569         int width;
3570         int height;
3571         unsigned char *skindata;
3572
3573         if (!skinframe->qpixels)
3574                 return;
3575
3576         if (!skinframe->qhascolormapping)
3577                 colormapped = false;
3578
3579         if (colormapped)
3580         {
3581                 if (!skinframe->qgeneratebase)
3582                         return;
3583         }
3584         else
3585         {
3586                 if (!skinframe->qgeneratemerged)
3587                         return;
3588         }
3589
3590         width = skinframe->qwidth;
3591         height = skinframe->qheight;
3592         skindata = skinframe->qpixels;
3593
3594         if (skinframe->qgeneratenmap)
3595         {
3596                 unsigned char *temp1, *temp2;
3597                 skinframe->qgeneratenmap = false;
3598                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3599                 temp2 = temp1 + width * height * 4;
3600                 // use either a custom palette or the quake palette
3601                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3602                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3603                 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);
3604                 Mem_Free(temp1);
3605         }
3606
3607         if (skinframe->qgenerateglow)
3608         {
3609                 skinframe->qgenerateglow = false;
3610                 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
3611         }
3612
3613         if (colormapped)
3614         {
3615                 skinframe->qgeneratebase = false;
3616                 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);
3617                 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);
3618                 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);
3619         }
3620         else
3621         {
3622                 skinframe->qgeneratemerged = false;
3623                 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);
3624         }
3625
3626         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3627         {
3628                 Mem_Free(skinframe->qpixels);
3629                 skinframe->qpixels = NULL;
3630         }
3631 }
3632
3633 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)
3634 {
3635         int i;
3636         skinframe_t *skinframe;
3637
3638         if (cls.state == ca_dedicated)
3639                 return NULL;
3640
3641         // if already loaded just return it, otherwise make a new skinframe
3642         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3643         if (skinframe && skinframe->base)
3644                 return skinframe;
3645
3646         skinframe->stain = NULL;
3647         skinframe->merged = NULL;
3648         skinframe->base = NULL;
3649         skinframe->pants = NULL;
3650         skinframe->shirt = NULL;
3651         skinframe->nmap = NULL;
3652         skinframe->gloss = NULL;
3653         skinframe->glow = NULL;
3654         skinframe->fog = NULL;
3655         skinframe->reflect = NULL;
3656         skinframe->hasalpha = false;
3657
3658         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3659         if (!skindata)
3660                 return NULL;
3661
3662         if (developer_loading.integer)
3663                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3664
3665         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3666         if (textureflags & TEXF_ALPHA)
3667         {
3668                 for (i = 0;i < width * height;i++)
3669                 {
3670                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3671                         {
3672                                 skinframe->hasalpha = true;
3673                                 break;
3674                         }
3675                 }
3676                 if (r_loadfog && skinframe->hasalpha)
3677                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3678         }
3679
3680         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3681         //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]);
3682
3683         return skinframe;
3684 }
3685
3686 skinframe_t *R_SkinFrame_LoadMissing(void)
3687 {
3688         skinframe_t *skinframe;
3689
3690         if (cls.state == ca_dedicated)
3691                 return NULL;
3692
3693         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3694         skinframe->stain = NULL;
3695         skinframe->merged = NULL;
3696         skinframe->base = NULL;
3697         skinframe->pants = NULL;
3698         skinframe->shirt = NULL;
3699         skinframe->nmap = NULL;
3700         skinframe->gloss = NULL;
3701         skinframe->glow = NULL;
3702         skinframe->fog = NULL;
3703         skinframe->reflect = NULL;
3704         skinframe->hasalpha = false;
3705
3706         skinframe->avgcolor[0] = rand() / RAND_MAX;
3707         skinframe->avgcolor[1] = rand() / RAND_MAX;
3708         skinframe->avgcolor[2] = rand() / RAND_MAX;
3709         skinframe->avgcolor[3] = 1;
3710
3711         return skinframe;
3712 }
3713
3714 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3715 typedef struct suffixinfo_s
3716 {
3717         const char *suffix;
3718         qboolean flipx, flipy, flipdiagonal;
3719 }
3720 suffixinfo_t;
3721 static suffixinfo_t suffix[3][6] =
3722 {
3723         {
3724                 {"px",   false, false, false},
3725                 {"nx",   false, false, false},
3726                 {"py",   false, false, false},
3727                 {"ny",   false, false, false},
3728                 {"pz",   false, false, false},
3729                 {"nz",   false, false, false}
3730         },
3731         {
3732                 {"posx", false, false, false},
3733                 {"negx", false, false, false},
3734                 {"posy", false, false, false},
3735                 {"negy", false, false, false},
3736                 {"posz", false, false, false},
3737                 {"negz", false, false, false}
3738         },
3739         {
3740                 {"rt",    true, false,  true},
3741                 {"lf",   false,  true,  true},
3742                 {"ft",    true,  true, false},
3743                 {"bk",   false, false, false},
3744                 {"up",    true, false,  true},
3745                 {"dn",    true, false,  true}
3746         }
3747 };
3748
3749 static int componentorder[4] = {0, 1, 2, 3};
3750
3751 rtexture_t *R_LoadCubemap(const char *basename)
3752 {
3753         int i, j, cubemapsize;
3754         unsigned char *cubemappixels, *image_buffer;
3755         rtexture_t *cubemaptexture;
3756         char name[256];
3757         // must start 0 so the first loadimagepixels has no requested width/height
3758         cubemapsize = 0;
3759         cubemappixels = NULL;
3760         cubemaptexture = NULL;
3761         // keep trying different suffix groups (posx, px, rt) until one loads
3762         for (j = 0;j < 3 && !cubemappixels;j++)
3763         {
3764                 // load the 6 images in the suffix group
3765                 for (i = 0;i < 6;i++)
3766                 {
3767                         // generate an image name based on the base and and suffix
3768                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3769                         // load it
3770                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3771                         {
3772                                 // an image loaded, make sure width and height are equal
3773                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3774                                 {
3775                                         // if this is the first image to load successfully, allocate the cubemap memory
3776                                         if (!cubemappixels && image_width >= 1)
3777                                         {
3778                                                 cubemapsize = image_width;
3779                                                 // note this clears to black, so unavailable sides are black
3780                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3781                                         }
3782                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3783                                         if (cubemappixels)
3784                                                 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);
3785                                 }
3786                                 else
3787                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3788                                 // free the image
3789                                 Mem_Free(image_buffer);
3790                         }
3791                 }
3792         }
3793         // if a cubemap loaded, upload it
3794         if (cubemappixels)
3795         {
3796                 if (developer_loading.integer)
3797                         Con_Printf("loading cubemap \"%s\"\n", basename);
3798
3799                 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);
3800                 Mem_Free(cubemappixels);
3801         }
3802         else
3803         {
3804                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3805                 if (developer_loading.integer)
3806                 {
3807                         Con_Printf("(tried tried images ");
3808                         for (j = 0;j < 3;j++)
3809                                 for (i = 0;i < 6;i++)
3810                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3811                         Con_Print(" and was unable to find any of them).\n");
3812                 }
3813         }
3814         return cubemaptexture;
3815 }
3816
3817 rtexture_t *R_GetCubemap(const char *basename)
3818 {
3819         int i;
3820         for (i = 0;i < r_texture_numcubemaps;i++)
3821                 if (r_texture_cubemaps[i] != NULL)
3822                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3823                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3824         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3825                 return r_texture_whitecube;
3826         r_texture_numcubemaps++;
3827         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3828         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3829         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3830         return r_texture_cubemaps[i]->texture;
3831 }
3832
3833 void R_FreeCubemap(const char *basename)
3834 {
3835         int i;
3836
3837         for (i = 0;i < r_texture_numcubemaps;i++)
3838         {
3839                 if (r_texture_cubemaps[i] != NULL)
3840                 {
3841                         if (r_texture_cubemaps[i]->texture)
3842                         {
3843                                 if (developer_loading.integer)
3844                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3845                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3846                                 Mem_Free(r_texture_cubemaps[i]);
3847                                 r_texture_cubemaps[i] = NULL;
3848                         }
3849                 }
3850         }
3851 }
3852
3853 void R_FreeCubemaps(void)
3854 {
3855         int i;
3856         for (i = 0;i < r_texture_numcubemaps;i++)
3857         {
3858                 if (developer_loading.integer)
3859                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3860                 if (r_texture_cubemaps[i] != NULL)
3861                 {
3862                         if (r_texture_cubemaps[i]->texture)
3863                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3864                         Mem_Free(r_texture_cubemaps[i]);
3865                 }
3866         }
3867         r_texture_numcubemaps = 0;
3868 }
3869
3870 void R_Main_FreeViewCache(void)
3871 {
3872         if (r_refdef.viewcache.entityvisible)
3873                 Mem_Free(r_refdef.viewcache.entityvisible);
3874         if (r_refdef.viewcache.world_pvsbits)
3875                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3876         if (r_refdef.viewcache.world_leafvisible)
3877                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3878         if (r_refdef.viewcache.world_surfacevisible)
3879                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3880         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3881 }
3882
3883 void R_Main_ResizeViewCache(void)
3884 {
3885         int numentities = r_refdef.scene.numentities;
3886         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3887         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3888         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3889         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3890         if (r_refdef.viewcache.maxentities < numentities)
3891         {
3892                 r_refdef.viewcache.maxentities = numentities;
3893                 if (r_refdef.viewcache.entityvisible)
3894                         Mem_Free(r_refdef.viewcache.entityvisible);
3895                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3896         }
3897         if (r_refdef.viewcache.world_numclusters != numclusters)
3898         {
3899                 r_refdef.viewcache.world_numclusters = numclusters;
3900                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3901                 if (r_refdef.viewcache.world_pvsbits)
3902                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3903                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3904         }
3905         if (r_refdef.viewcache.world_numleafs != numleafs)
3906         {
3907                 r_refdef.viewcache.world_numleafs = numleafs;
3908                 if (r_refdef.viewcache.world_leafvisible)
3909                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3910                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3911         }
3912         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3913         {
3914                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3915                 if (r_refdef.viewcache.world_surfacevisible)
3916                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3917                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3918         }
3919 }
3920
3921 extern rtexture_t *loadingscreentexture;
3922 void gl_main_start(void)
3923 {
3924         loadingscreentexture = NULL;
3925         r_texture_blanknormalmap = NULL;
3926         r_texture_white = NULL;
3927         r_texture_grey128 = NULL;
3928         r_texture_black = NULL;
3929         r_texture_whitecube = NULL;
3930         r_texture_normalizationcube = NULL;
3931         r_texture_fogattenuation = NULL;
3932         r_texture_fogheighttexture = NULL;
3933         r_texture_gammaramps = NULL;
3934         r_texture_numcubemaps = 0;
3935
3936         r_loaddds = r_texture_dds_load.integer != 0;
3937         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3938
3939         switch(vid.renderpath)
3940         {
3941         case RENDERPATH_GL20:
3942         case RENDERPATH_D3D9:
3943         case RENDERPATH_D3D10:
3944         case RENDERPATH_D3D11:
3945         case RENDERPATH_SOFT:
3946         case RENDERPATH_GLES2:
3947                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3948                 Cvar_SetValueQuick(&gl_combine, 1);
3949                 Cvar_SetValueQuick(&r_glsl, 1);
3950                 r_loadnormalmap = true;
3951                 r_loadgloss = true;
3952                 r_loadfog = false;
3953                 break;
3954         case RENDERPATH_GL13:
3955         case RENDERPATH_GLES1:
3956                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3957                 Cvar_SetValueQuick(&gl_combine, 1);
3958                 Cvar_SetValueQuick(&r_glsl, 0);
3959                 r_loadnormalmap = false;
3960                 r_loadgloss = false;
3961                 r_loadfog = true;
3962                 break;
3963         case RENDERPATH_GL11:
3964                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3965                 Cvar_SetValueQuick(&gl_combine, 0);
3966                 Cvar_SetValueQuick(&r_glsl, 0);
3967                 r_loadnormalmap = false;
3968                 r_loadgloss = false;
3969                 r_loadfog = true;
3970                 break;
3971         }
3972
3973         R_AnimCache_Free();
3974         R_FrameData_Reset();
3975
3976         r_numqueries = 0;
3977         r_maxqueries = 0;
3978         memset(r_queries, 0, sizeof(r_queries));
3979
3980         r_qwskincache = NULL;
3981         r_qwskincache_size = 0;
3982
3983         // due to caching of texture_t references, the collision cache must be reset
3984         Collision_Cache_Reset(true);
3985
3986         // set up r_skinframe loading system for textures
3987         memset(&r_skinframe, 0, sizeof(r_skinframe));
3988         r_skinframe.loadsequence = 1;
3989         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3990
3991         r_main_texturepool = R_AllocTexturePool();
3992         R_BuildBlankTextures();
3993         R_BuildNoTexture();
3994         if (vid.support.arb_texture_cube_map)
3995         {
3996                 R_BuildWhiteCube();
3997                 R_BuildNormalizationCube();
3998         }
3999         r_texture_fogattenuation = NULL;
4000         r_texture_fogheighttexture = NULL;
4001         r_texture_gammaramps = NULL;
4002         //r_texture_fogintensity = NULL;
4003         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4004         memset(&r_waterstate, 0, sizeof(r_waterstate));
4005         r_glsl_permutation = NULL;
4006         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4007         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4008         glslshaderstring = NULL;
4009 #ifdef SUPPORTD3D
4010         r_hlsl_permutation = NULL;
4011         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4012         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4013 #endif
4014         hlslshaderstring = NULL;
4015         memset(&r_svbsp, 0, sizeof (r_svbsp));
4016
4017         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4018         r_texture_numcubemaps = 0;
4019
4020         r_refdef.fogmasktable_density = 0;
4021 }
4022
4023 void gl_main_shutdown(void)
4024 {
4025         R_AnimCache_Free();
4026         R_FrameData_Reset();
4027
4028         R_Main_FreeViewCache();
4029
4030         switch(vid.renderpath)
4031         {
4032         case RENDERPATH_GL11:
4033         case RENDERPATH_GL13:
4034         case RENDERPATH_GL20:
4035         case RENDERPATH_GLES1:
4036         case RENDERPATH_GLES2:
4037                 if (r_maxqueries)
4038                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4039                 break;
4040         case RENDERPATH_D3D9:
4041                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4042                 break;
4043         case RENDERPATH_D3D10:
4044                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4045                 break;
4046         case RENDERPATH_D3D11:
4047                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4048                 break;
4049         case RENDERPATH_SOFT:
4050                 break;
4051         }
4052
4053         r_numqueries = 0;
4054         r_maxqueries = 0;
4055         memset(r_queries, 0, sizeof(r_queries));
4056
4057         r_qwskincache = NULL;
4058         r_qwskincache_size = 0;
4059
4060         // clear out the r_skinframe state
4061         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4062         memset(&r_skinframe, 0, sizeof(r_skinframe));
4063
4064         if (r_svbsp.nodes)
4065                 Mem_Free(r_svbsp.nodes);
4066         memset(&r_svbsp, 0, sizeof (r_svbsp));
4067         R_FreeTexturePool(&r_main_texturepool);
4068         loadingscreentexture = NULL;
4069         r_texture_blanknormalmap = NULL;
4070         r_texture_white = NULL;
4071         r_texture_grey128 = NULL;
4072         r_texture_black = NULL;
4073         r_texture_whitecube = NULL;
4074         r_texture_normalizationcube = NULL;
4075         r_texture_fogattenuation = NULL;
4076         r_texture_fogheighttexture = NULL;
4077         r_texture_gammaramps = NULL;
4078         r_texture_numcubemaps = 0;
4079         //r_texture_fogintensity = NULL;
4080         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4081         memset(&r_waterstate, 0, sizeof(r_waterstate));
4082         R_GLSL_Restart_f();
4083
4084         r_glsl_permutation = NULL;
4085         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4086         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4087         glslshaderstring = NULL;
4088 #ifdef SUPPORTD3D
4089         r_hlsl_permutation = NULL;
4090         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4091         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4092 #endif
4093         hlslshaderstring = NULL;
4094 }
4095
4096 extern void CL_ParseEntityLump(char *entitystring);
4097 void gl_main_newmap(void)
4098 {
4099         // FIXME: move this code to client
4100         char *entities, entname[MAX_QPATH];
4101         if (r_qwskincache)
4102                 Mem_Free(r_qwskincache);
4103         r_qwskincache = NULL;
4104         r_qwskincache_size = 0;
4105         if (cl.worldmodel)
4106         {
4107                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4108                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4109                 {
4110                         CL_ParseEntityLump(entities);
4111                         Mem_Free(entities);
4112                         return;
4113                 }
4114                 if (cl.worldmodel->brush.entities)
4115                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4116         }
4117         R_Main_FreeViewCache();
4118
4119         R_FrameData_Reset();
4120 }
4121
4122 void GL_Main_Init(void)
4123 {
4124         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4125
4126         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4127         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4128         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4129         if (gamemode == GAME_NEHAHRA)
4130         {
4131                 Cvar_RegisterVariable (&gl_fogenable);
4132                 Cvar_RegisterVariable (&gl_fogdensity);
4133                 Cvar_RegisterVariable (&gl_fogred);
4134                 Cvar_RegisterVariable (&gl_foggreen);
4135                 Cvar_RegisterVariable (&gl_fogblue);
4136                 Cvar_RegisterVariable (&gl_fogstart);
4137                 Cvar_RegisterVariable (&gl_fogend);
4138                 Cvar_RegisterVariable (&gl_skyclip);
4139         }
4140         Cvar_RegisterVariable(&r_motionblur);
4141         Cvar_RegisterVariable(&r_motionblur_maxblur);
4142         Cvar_RegisterVariable(&r_motionblur_bmin);
4143         Cvar_RegisterVariable(&r_motionblur_vmin);
4144         Cvar_RegisterVariable(&r_motionblur_vmax);
4145         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4146         Cvar_RegisterVariable(&r_motionblur_randomize);
4147         Cvar_RegisterVariable(&r_damageblur);
4148         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4149         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4150         Cvar_RegisterVariable(&r_equalize_entities_by);
4151         Cvar_RegisterVariable(&r_equalize_entities_to);
4152         Cvar_RegisterVariable(&r_depthfirst);
4153         Cvar_RegisterVariable(&r_useinfinitefarclip);
4154         Cvar_RegisterVariable(&r_farclip_base);
4155         Cvar_RegisterVariable(&r_farclip_world);
4156         Cvar_RegisterVariable(&r_nearclip);
4157         Cvar_RegisterVariable(&r_deformvertexes);
4158         Cvar_RegisterVariable(&r_transparent);
4159         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4160         Cvar_RegisterVariable(&r_showoverdraw);
4161         Cvar_RegisterVariable(&r_showbboxes);
4162         Cvar_RegisterVariable(&r_showsurfaces);
4163         Cvar_RegisterVariable(&r_showtris);
4164         Cvar_RegisterVariable(&r_shownormals);
4165         Cvar_RegisterVariable(&r_showlighting);
4166         Cvar_RegisterVariable(&r_showshadowvolumes);
4167         Cvar_RegisterVariable(&r_showcollisionbrushes);
4168         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4169         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4170         Cvar_RegisterVariable(&r_showdisabledepthtest);
4171         Cvar_RegisterVariable(&r_drawportals);
4172         Cvar_RegisterVariable(&r_drawentities);
4173         Cvar_RegisterVariable(&r_draw2d);
4174         Cvar_RegisterVariable(&r_drawworld);
4175         Cvar_RegisterVariable(&r_cullentities_trace);
4176         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4177         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4178         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4179         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4180         Cvar_RegisterVariable(&r_drawviewmodel);
4181         Cvar_RegisterVariable(&r_drawexteriormodel);
4182         Cvar_RegisterVariable(&r_speeds);
4183         Cvar_RegisterVariable(&r_fullbrights);
4184         Cvar_RegisterVariable(&r_wateralpha);
4185         Cvar_RegisterVariable(&r_dynamic);
4186         Cvar_RegisterVariable(&r_fakelight);
4187         Cvar_RegisterVariable(&r_fakelight_intensity);
4188         Cvar_RegisterVariable(&r_fullbright);
4189         Cvar_RegisterVariable(&r_shadows);
4190         Cvar_RegisterVariable(&r_shadows_darken);
4191         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4192         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4193         Cvar_RegisterVariable(&r_shadows_throwdistance);
4194         Cvar_RegisterVariable(&r_shadows_throwdirection);
4195         Cvar_RegisterVariable(&r_shadows_focus);
4196         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4197         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4198         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4199         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4200         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4201         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4202         Cvar_RegisterVariable(&r_fog_exp2);
4203         Cvar_RegisterVariable(&r_fog_clear);
4204         Cvar_RegisterVariable(&r_drawfog);
4205         Cvar_RegisterVariable(&r_transparentdepthmasking);
4206         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4207         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4208         Cvar_RegisterVariable(&r_texture_dds_load);
4209         Cvar_RegisterVariable(&r_texture_dds_save);
4210         Cvar_RegisterVariable(&r_textureunits);
4211         Cvar_RegisterVariable(&gl_combine);
4212         Cvar_RegisterVariable(&r_viewfbo);
4213         Cvar_RegisterVariable(&r_viewscale);
4214         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4215         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4216         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4217         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4218         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4219         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4220         Cvar_RegisterVariable(&r_glsl);
4221         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4222         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4223         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4224         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4225         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4226         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4227         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4228         Cvar_RegisterVariable(&r_glsl_postprocess);
4229         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4230         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4231         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4232         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4233         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4234         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4235         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4236         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4237
4238         Cvar_RegisterVariable(&r_water);
4239         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4240         Cvar_RegisterVariable(&r_water_clippingplanebias);
4241         Cvar_RegisterVariable(&r_water_refractdistort);
4242         Cvar_RegisterVariable(&r_water_reflectdistort);
4243         Cvar_RegisterVariable(&r_water_scissormode);
4244         Cvar_RegisterVariable(&r_water_lowquality);
4245
4246         Cvar_RegisterVariable(&r_lerpsprites);
4247         Cvar_RegisterVariable(&r_lerpmodels);
4248         Cvar_RegisterVariable(&r_lerplightstyles);
4249         Cvar_RegisterVariable(&r_waterscroll);
4250         Cvar_RegisterVariable(&r_bloom);
4251         Cvar_RegisterVariable(&r_bloom_colorscale);
4252         Cvar_RegisterVariable(&r_bloom_brighten);
4253         Cvar_RegisterVariable(&r_bloom_blur);
4254         Cvar_RegisterVariable(&r_bloom_resolution);
4255         Cvar_RegisterVariable(&r_bloom_colorexponent);
4256         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4257         Cvar_RegisterVariable(&r_hdr);
4258         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4259         Cvar_RegisterVariable(&r_hdr_glowintensity);
4260         Cvar_RegisterVariable(&r_hdr_range);
4261         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4262         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4263         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4264         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4265         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4266         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4267         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4268         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4269         Cvar_RegisterVariable(&developer_texturelogging);
4270         Cvar_RegisterVariable(&gl_lightmaps);
4271         Cvar_RegisterVariable(&r_test);
4272         Cvar_RegisterVariable(&r_glsl_saturation);
4273         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4274         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4275         Cvar_RegisterVariable(&r_framedatasize);
4276         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4277                 Cvar_SetValue("r_fullbrights", 0);
4278         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4279 }
4280
4281 extern void R_Textures_Init(void);
4282 extern void GL_Draw_Init(void);
4283 extern void GL_Main_Init(void);
4284 extern void R_Shadow_Init(void);
4285 extern void R_Sky_Init(void);
4286 extern void GL_Surf_Init(void);
4287 extern void R_Particles_Init(void);
4288 extern void R_Explosion_Init(void);
4289 extern void gl_backend_init(void);
4290 extern void Sbar_Init(void);
4291 extern void R_LightningBeams_Init(void);
4292 extern void Mod_RenderInit(void);
4293 extern void Font_Init(void);
4294
4295 void Render_Init(void)
4296 {
4297         gl_backend_init();
4298         R_Textures_Init();
4299         GL_Main_Init();
4300         Font_Init();
4301         GL_Draw_Init();
4302         R_Shadow_Init();
4303         R_Sky_Init();
4304         GL_Surf_Init();
4305         Sbar_Init();
4306         R_Particles_Init();
4307         R_Explosion_Init();
4308         R_LightningBeams_Init();
4309         Mod_RenderInit();
4310 }
4311
4312 /*
4313 ===============
4314 GL_Init
4315 ===============
4316 */
4317 extern char *ENGINE_EXTENSIONS;
4318 void GL_Init (void)
4319 {
4320         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4321         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4322         gl_version = (const char *)qglGetString(GL_VERSION);
4323         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4324
4325         if (!gl_extensions)
4326                 gl_extensions = "";
4327         if (!gl_platformextensions)
4328                 gl_platformextensions = "";
4329
4330         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4331         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4332         Con_Printf("GL_VERSION: %s\n", gl_version);
4333         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4334         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4335
4336         VID_CheckExtensions();
4337
4338         // LordHavoc: report supported extensions
4339         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4340
4341         // clear to black (loading plaque will be seen over this)
4342         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4343 }
4344
4345 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4346 {
4347         int i;
4348         mplane_t *p;
4349         if (r_trippy.integer)
4350                 return false;
4351         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4352         {
4353                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4354                 if (i == 4)
4355                         continue;
4356                 p = r_refdef.view.frustum + i;
4357                 switch(p->signbits)
4358                 {
4359                 default:
4360                 case 0:
4361                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4362                                 return true;
4363                         break;
4364                 case 1:
4365                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4366                                 return true;
4367                         break;
4368                 case 2:
4369                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4370                                 return true;
4371                         break;
4372                 case 3:
4373                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4374                                 return true;
4375                         break;
4376                 case 4:
4377                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4378                                 return true;
4379                         break;
4380                 case 5:
4381                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4382                                 return true;
4383                         break;
4384                 case 6:
4385                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4386                                 return true;
4387                         break;
4388                 case 7:
4389                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4390                                 return true;
4391                         break;
4392                 }
4393         }
4394         return false;
4395 }
4396
4397 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4398 {
4399         int i;
4400         const mplane_t *p;
4401         if (r_trippy.integer)
4402                 return false;
4403         for (i = 0;i < numplanes;i++)
4404         {
4405                 p = planes + i;
4406                 switch(p->signbits)
4407                 {
4408                 default:
4409                 case 0:
4410                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4411                                 return true;
4412                         break;
4413                 case 1:
4414                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4415                                 return true;
4416                         break;
4417                 case 2:
4418                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4419                                 return true;
4420                         break;
4421                 case 3:
4422                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4423                                 return true;
4424                         break;
4425                 case 4:
4426                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4427                                 return true;
4428                         break;
4429                 case 5:
4430                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4431                                 return true;
4432                         break;
4433                 case 6:
4434                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 7:
4438                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 }
4442         }
4443         return false;
4444 }
4445
4446 //==================================================================================
4447
4448 // LordHavoc: this stores temporary data used within the same frame
4449
4450 typedef struct r_framedata_mem_s
4451 {
4452         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4453         size_t size; // how much usable space
4454         size_t current; // how much space in use
4455         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4456         size_t wantedsize; // how much space was allocated
4457         unsigned char *data; // start of real data (16byte aligned)
4458 }
4459 r_framedata_mem_t;
4460
4461 static r_framedata_mem_t *r_framedata_mem;
4462
4463 void R_FrameData_Reset(void)
4464 {
4465         while (r_framedata_mem)
4466         {
4467                 r_framedata_mem_t *next = r_framedata_mem->purge;
4468                 Mem_Free(r_framedata_mem);
4469                 r_framedata_mem = next;
4470         }
4471 }
4472
4473 void R_FrameData_Resize(void)
4474 {
4475         size_t wantedsize;
4476         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4477         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4478         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4479         {
4480                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4481                 newmem->wantedsize = wantedsize;
4482                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4483                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4484                 newmem->current = 0;
4485                 newmem->mark = 0;
4486                 newmem->purge = r_framedata_mem;
4487                 r_framedata_mem = newmem;
4488         }
4489 }
4490
4491 void R_FrameData_NewFrame(void)
4492 {
4493         R_FrameData_Resize();
4494         if (!r_framedata_mem)
4495                 return;
4496         // if we ran out of space on the last frame, free the old memory now
4497         while (r_framedata_mem->purge)
4498         {
4499                 // repeatedly remove the second item in the list, leaving only head
4500                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4501                 Mem_Free(r_framedata_mem->purge);
4502                 r_framedata_mem->purge = next;
4503         }
4504         // reset the current mem pointer
4505         r_framedata_mem->current = 0;
4506         r_framedata_mem->mark = 0;
4507 }
4508
4509 void *R_FrameData_Alloc(size_t size)
4510 {
4511         void *data;
4512
4513         // align to 16 byte boundary - the data pointer is already aligned, so we
4514         // only need to ensure the size of every allocation is also aligned
4515         size = (size + 15) & ~15;
4516
4517         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4518         {
4519                 // emergency - we ran out of space, allocate more memory
4520                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4521                 R_FrameData_Resize();
4522         }
4523
4524         data = r_framedata_mem->data + r_framedata_mem->current;
4525         r_framedata_mem->current += size;
4526
4527         // count the usage for stats
4528         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4529         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4530
4531         return (void *)data;
4532 }
4533
4534 void *R_FrameData_Store(size_t size, void *data)
4535 {
4536         void *d = R_FrameData_Alloc(size);
4537         if (d && data)
4538                 memcpy(d, data, size);
4539         return d;
4540 }
4541
4542 void R_FrameData_SetMark(void)
4543 {
4544         if (!r_framedata_mem)
4545                 return;
4546         r_framedata_mem->mark = r_framedata_mem->current;
4547 }
4548
4549 void R_FrameData_ReturnToMark(void)
4550 {
4551         if (!r_framedata_mem)
4552                 return;
4553         r_framedata_mem->current = r_framedata_mem->mark;
4554 }
4555
4556 //==================================================================================
4557
4558 // LordHavoc: animcache originally written by Echon, rewritten since then
4559
4560 /**
4561  * Animation cache prevents re-generating mesh data for an animated model
4562  * multiple times in one frame for lighting, shadowing, reflections, etc.
4563  */
4564
4565 void R_AnimCache_Free(void)
4566 {
4567 }
4568
4569 void R_AnimCache_ClearCache(void)
4570 {
4571         int i;
4572         entity_render_t *ent;
4573
4574         for (i = 0;i < r_refdef.scene.numentities;i++)
4575         {
4576                 ent = r_refdef.scene.entities[i];
4577                 ent->animcache_vertex3f = NULL;
4578                 ent->animcache_normal3f = NULL;
4579                 ent->animcache_svector3f = NULL;
4580                 ent->animcache_tvector3f = NULL;
4581                 ent->animcache_vertexmesh = NULL;
4582                 ent->animcache_vertex3fbuffer = NULL;
4583                 ent->animcache_vertexmeshbuffer = NULL;
4584         }
4585 }
4586
4587 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4588 {
4589         int i;
4590
4591         // check if we need the meshbuffers
4592         if (!vid.useinterleavedarrays)
4593                 return;
4594
4595         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4596                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4597         // TODO: upload vertex3f buffer?
4598         if (ent->animcache_vertexmesh)
4599         {
4600                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4601                 for (i = 0;i < numvertices;i++)
4602                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4603                 if (ent->animcache_svector3f)
4604                         for (i = 0;i < numvertices;i++)
4605                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4606                 if (ent->animcache_tvector3f)
4607                         for (i = 0;i < numvertices;i++)
4608                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4609                 if (ent->animcache_normal3f)
4610                         for (i = 0;i < numvertices;i++)
4611                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4612                 // TODO: upload vertexmeshbuffer?
4613         }
4614 }
4615
4616 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4617 {
4618         dp_model_t *model = ent->model;
4619         int numvertices;
4620         // see if it's already cached this frame
4621         if (ent->animcache_vertex3f)
4622         {
4623                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4624                 if (wantnormals || wanttangents)
4625                 {
4626                         if (ent->animcache_normal3f)
4627                                 wantnormals = false;
4628                         if (ent->animcache_svector3f)
4629                                 wanttangents = false;
4630                         if (wantnormals || wanttangents)
4631                         {
4632                                 numvertices = model->surfmesh.num_vertices;
4633                                 if (wantnormals)
4634                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4635                                 if (wanttangents)
4636                                 {
4637                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4638                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4639                                 }
4640                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4641                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4642                         }
4643                 }
4644         }
4645         else
4646         {
4647                 // see if this ent is worth caching
4648                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4649                         return false;
4650                 // get some memory for this entity and generate mesh data
4651                 numvertices = model->surfmesh.num_vertices;
4652                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4653                 if (wantnormals)
4654                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4655                 if (wanttangents)
4656                 {
4657                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4658                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4659                 }
4660                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4661                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4662         }
4663         return true;
4664 }
4665
4666 void R_AnimCache_CacheVisibleEntities(void)
4667 {
4668         int i;
4669         qboolean wantnormals = true;
4670         qboolean wanttangents = !r_showsurfaces.integer;
4671
4672         switch(vid.renderpath)
4673         {
4674         case RENDERPATH_GL20:
4675         case RENDERPATH_D3D9:
4676         case RENDERPATH_D3D10:
4677         case RENDERPATH_D3D11:
4678         case RENDERPATH_GLES2:
4679                 break;
4680         case RENDERPATH_GL11:
4681         case RENDERPATH_GL13:
4682         case RENDERPATH_GLES1:
4683                 wanttangents = false;
4684                 break;
4685         case RENDERPATH_SOFT:
4686                 break;
4687         }
4688
4689         if (r_shownormals.integer)
4690                 wanttangents = wantnormals = true;
4691
4692         // TODO: thread this
4693         // NOTE: R_PrepareRTLights() also caches entities
4694
4695         for (i = 0;i < r_refdef.scene.numentities;i++)
4696                 if (r_refdef.viewcache.entityvisible[i])
4697                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4698 }
4699
4700 //==================================================================================
4701
4702 extern cvar_t r_overheadsprites_pushback;
4703
4704 static void R_View_UpdateEntityLighting (void)
4705 {
4706         int i;
4707         entity_render_t *ent;
4708         vec3_t tempdiffusenormal, avg;
4709         vec_t f, fa, fd, fdd;
4710         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4711
4712         for (i = 0;i < r_refdef.scene.numentities;i++)
4713         {
4714                 ent = r_refdef.scene.entities[i];
4715
4716                 // skip unseen models
4717                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4718                         continue;
4719
4720                 // skip bsp models
4721                 if (ent->model && ent->model->brush.num_leafs)
4722                 {
4723                         // TODO: use modellight for r_ambient settings on world?
4724                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4725                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4726                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4727                         continue;
4728                 }
4729
4730                 // fetch the lighting from the worldmodel data
4731                 VectorClear(ent->modellight_ambient);
4732                 VectorClear(ent->modellight_diffuse);
4733                 VectorClear(tempdiffusenormal);
4734                 if (ent->flags & RENDER_LIGHT)
4735                 {
4736                         vec3_t org;
4737                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4738
4739                         // complete lightning for lit sprites
4740                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4741                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4742                         {
4743                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4744                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4745                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4746                         }
4747                         else
4748                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4749
4750                         if(ent->flags & RENDER_EQUALIZE)
4751                         {
4752                                 // first fix up ambient lighting...
4753                                 if(r_equalize_entities_minambient.value > 0)
4754                                 {
4755                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4756                                         if(fd > 0)
4757                                         {
4758                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4759                                                 if(fa < r_equalize_entities_minambient.value * fd)
4760                                                 {
4761                                                         // solve:
4762                                                         //   fa'/fd' = minambient
4763                                                         //   fa'+0.25*fd' = fa+0.25*fd
4764                                                         //   ...
4765                                                         //   fa' = fd' * minambient
4766                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4767                                                         //   ...
4768                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4769                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4770                                                         //   ...
4771                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4772                                                         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
4773                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4774                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4775                                                 }
4776                                         }
4777                                 }
4778
4779                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4780                                 {
4781                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4782                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4783                                         f = fa + 0.25 * fd;
4784                                         if(f > 0)
4785                                         {
4786                                                 // adjust brightness and saturation to target
4787                                                 avg[0] = avg[1] = avg[2] = fa / f;
4788                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4789                                                 avg[0] = avg[1] = avg[2] = fd / f;
4790                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4791                                         }
4792                                 }
4793                         }
4794                 }
4795                 else // highly rare
4796                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4797
4798                 // move the light direction into modelspace coordinates for lighting code
4799                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4800                 if(VectorLength2(ent->modellight_lightdir) == 0)
4801                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4802                 VectorNormalize(ent->modellight_lightdir);
4803         }
4804 }
4805
4806 #define MAX_LINEOFSIGHTTRACES 64
4807
4808 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4809 {
4810         int i;
4811         vec3_t boxmins, boxmaxs;
4812         vec3_t start;
4813         vec3_t end;
4814         dp_model_t *model = r_refdef.scene.worldmodel;
4815
4816         if (!model || !model->brush.TraceLineOfSight)
4817                 return true;
4818
4819         // expand the box a little
4820         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4821         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4822         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4823         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4824         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4825         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4826
4827         // return true if eye is inside enlarged box
4828         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4829                 return true;
4830
4831         // try center
4832         VectorCopy(eye, start);
4833         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4834         if (model->brush.TraceLineOfSight(model, start, end))
4835                 return true;
4836
4837         // try various random positions
4838         for (i = 0;i < numsamples;i++)
4839         {
4840                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4841                 if (model->brush.TraceLineOfSight(model, start, end))
4842                         return true;
4843         }
4844
4845         return false;
4846 }
4847
4848
4849 static void R_View_UpdateEntityVisible (void)
4850 {
4851         int i;
4852         int renderimask;
4853         int samples;
4854         entity_render_t *ent;
4855
4856         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4857                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4858                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4859                 :                                                          RENDER_EXTERIORMODEL;
4860         if (!r_drawviewmodel.integer)
4861                 renderimask |= RENDER_VIEWMODEL;
4862         if (!r_drawexteriormodel.integer)
4863                 renderimask |= RENDER_EXTERIORMODEL;
4864         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4865         {
4866                 // worldmodel can check visibility
4867                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4868                 for (i = 0;i < r_refdef.scene.numentities;i++)
4869                 {
4870                         ent = r_refdef.scene.entities[i];
4871                         if (!(ent->flags & renderimask))
4872                         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)))
4873                         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))
4874                                 r_refdef.viewcache.entityvisible[i] = true;
4875                 }
4876         }
4877         else
4878         {
4879                 // no worldmodel or it can't check visibility
4880                 for (i = 0;i < r_refdef.scene.numentities;i++)
4881                 {
4882                         ent = r_refdef.scene.entities[i];
4883                         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));
4884                 }
4885         }
4886         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4887                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4888         {
4889                 for (i = 0;i < r_refdef.scene.numentities;i++)
4890                 {
4891                         if (!r_refdef.viewcache.entityvisible[i])
4892                                 continue;
4893                         ent = r_refdef.scene.entities[i];
4894                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4895                         {
4896                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4897                                 if (samples < 0)
4898                                         continue; // temp entities do pvs only
4899                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4900                                         ent->last_trace_visibility = realtime;
4901                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4902                                         r_refdef.viewcache.entityvisible[i] = 0;
4903                         }
4904                 }
4905         }
4906 }
4907
4908 /// only used if skyrendermasked, and normally returns false
4909 int R_DrawBrushModelsSky (void)
4910 {
4911         int i, sky;
4912         entity_render_t *ent;
4913
4914         sky = false;
4915         for (i = 0;i < r_refdef.scene.numentities;i++)
4916         {
4917                 if (!r_refdef.viewcache.entityvisible[i])
4918                         continue;
4919                 ent = r_refdef.scene.entities[i];
4920                 if (!ent->model || !ent->model->DrawSky)
4921                         continue;
4922                 ent->model->DrawSky(ent);
4923                 sky = true;
4924         }
4925         return sky;
4926 }
4927
4928 static void R_DrawNoModel(entity_render_t *ent);
4929 static void R_DrawModels(void)
4930 {
4931         int i;
4932         entity_render_t *ent;
4933
4934         for (i = 0;i < r_refdef.scene.numentities;i++)
4935         {
4936                 if (!r_refdef.viewcache.entityvisible[i])
4937                         continue;
4938                 ent = r_refdef.scene.entities[i];
4939                 r_refdef.stats.entities++;
4940                 /*
4941                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4942                 {
4943                         vec3_t f, l, u, o;
4944                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4945                         Con_Printf("R_DrawModels\n");
4946                         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]);
4947                         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);
4948                         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);
4949                 }
4950                 */
4951                 if (ent->model && ent->model->Draw != NULL)
4952                         ent->model->Draw(ent);
4953                 else
4954                         R_DrawNoModel(ent);
4955         }
4956 }
4957
4958 static void R_DrawModelsDepth(void)
4959 {
4960         int i;
4961         entity_render_t *ent;
4962
4963         for (i = 0;i < r_refdef.scene.numentities;i++)
4964         {
4965                 if (!r_refdef.viewcache.entityvisible[i])
4966                         continue;
4967                 ent = r_refdef.scene.entities[i];
4968                 if (ent->model && ent->model->DrawDepth != NULL)
4969                         ent->model->DrawDepth(ent);
4970         }
4971 }
4972
4973 static void R_DrawModelsDebug(void)
4974 {
4975         int i;
4976         entity_render_t *ent;
4977
4978         for (i = 0;i < r_refdef.scene.numentities;i++)
4979         {
4980                 if (!r_refdef.viewcache.entityvisible[i])
4981                         continue;
4982                 ent = r_refdef.scene.entities[i];
4983                 if (ent->model && ent->model->DrawDebug != NULL)
4984                         ent->model->DrawDebug(ent);
4985         }
4986 }
4987
4988 static void R_DrawModelsAddWaterPlanes(void)
4989 {
4990         int i;
4991         entity_render_t *ent;
4992
4993         for (i = 0;i < r_refdef.scene.numentities;i++)
4994         {
4995                 if (!r_refdef.viewcache.entityvisible[i])
4996                         continue;
4997                 ent = r_refdef.scene.entities[i];
4998                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4999                         ent->model->DrawAddWaterPlanes(ent);
5000         }
5001 }
5002
5003 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5004 {
5005         if (r_hdr_irisadaptation.integer)
5006         {
5007                 vec3_t ambient;
5008                 vec3_t diffuse;
5009                 vec3_t diffusenormal;
5010                 vec_t brightness;
5011                 vec_t goal;
5012                 vec_t current;
5013                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5014                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5015                 brightness = max(0.0000001f, brightness);
5016                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5017                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5018                 current = r_hdr_irisadaptation_value.value;
5019                 if (current < goal)
5020                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5021                 else if (current > goal)
5022                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, 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 blur_factor, blur_mouseaccel, blur_velocity;
6297                                 static float blur_average; 
6298                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6299
6300                                 blur_velocity = VectorLength(cl.movement_velocity);
6301                                 blur_mouseaccel = fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles));
6302                                 
6303                                 // set a goal for the factoring
6304                                 blur_factor = (blur_velocity + (blur_mouseaccel * 10));
6305                                 
6306                                 // from the goal, pick an averaged value between goal and last value
6307                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6308                                 blur_average *= (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6309
6310                                 blur_factor = bound(0, (blur_average - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value), 1);
6311                                 //blur_factor = blur_factor * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6312
6313                                 // calculate values into a standard alpha
6314                                 cl.motionbluralpha = 1 - exp(-
6315                                                 (
6316                                                  (r_motionblur.value * blur_factor / 80)
6317                                                  +
6318                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6319                                                 )
6320                                                 /
6321                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6322                                           );
6323
6324                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6325                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6326                                 
6327                                 // apply the blur
6328                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6329                                 {
6330                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6331                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6332                                         switch(vid.renderpath)
6333                                         {
6334                                         case RENDERPATH_GL11:
6335                                         case RENDERPATH_GL13:
6336                                         case RENDERPATH_GL20:
6337                                         case RENDERPATH_GLES1:
6338                                         case RENDERPATH_GLES2:
6339                                         case RENDERPATH_SOFT:
6340                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6341                                                 break;
6342                                         case RENDERPATH_D3D9:
6343                                         case RENDERPATH_D3D10:
6344                                         case RENDERPATH_D3D11:
6345                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6346                                                 break;
6347                                         }
6348                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6349                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6350                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6351                                 }
6352                                 
6353                                 // updates old view angles for next pass 
6354                                 VectorCopy(cl.viewangles, blur_oldangles);
6355                         }
6356
6357                         // copy view into the screen texture
6358                         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);
6359                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6360                 }
6361                 else if (!r_bloomstate.texture_bloom)
6362                 {
6363                         // we may still have to do view tint...
6364                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6365                         {
6366                                 // apply a color tint to the whole view
6367                                 R_ResetViewRendering2D();
6368                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6369                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6370                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6371                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6372                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6373                         }
6374                         break; // no screen processing, no bloom, skip it
6375                 }
6376
6377                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6378                 {
6379                         // render simple bloom effect
6380                         // copy the screen and shrink it and darken it for the bloom process
6381                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6382                         // make the bloom texture
6383                         R_Bloom_MakeTexture();
6384                 }
6385
6386 #if _MSC_VER >= 1400
6387 #define sscanf sscanf_s
6388 #endif
6389                 memset(uservecs, 0, sizeof(uservecs));
6390                 if (r_glsl_postprocess_uservec1_enable.integer)
6391                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6392                 if (r_glsl_postprocess_uservec2_enable.integer)
6393                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6394                 if (r_glsl_postprocess_uservec3_enable.integer)
6395                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6396                 if (r_glsl_postprocess_uservec4_enable.integer)
6397                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6398
6399                 R_ResetViewRendering2D();
6400                 GL_Color(1, 1, 1, 1);
6401                 GL_BlendFunc(GL_ONE, GL_ZERO);
6402
6403                 switch(vid.renderpath)
6404                 {
6405                 case RENDERPATH_GL20:
6406                 case RENDERPATH_GLES2:
6407                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6408                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6409                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6410                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6411                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6412                         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]);
6413                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6414                         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]);
6415                         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]);
6416                         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]);
6417                         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]);
6418                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6419                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6420                         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);
6421                         break;
6422                 case RENDERPATH_D3D9:
6423 #ifdef SUPPORTD3D
6424                         // 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...
6425                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6426                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6427                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6428                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6429                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6430                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6431                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6432                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6433                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6434                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6435                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6436                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6437                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6438                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6439 #endif
6440                         break;
6441                 case RENDERPATH_D3D10:
6442                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6443                         break;
6444                 case RENDERPATH_D3D11:
6445                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6446                         break;
6447                 case RENDERPATH_SOFT:
6448                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6449                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6450                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6451                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6452                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6453                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6454                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6455                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6456                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6457                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6458                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6459                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6460                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6461                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6462                         break;
6463                 default:
6464                         break;
6465                 }
6466                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6467                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6468                 break;
6469         case RENDERPATH_GL11:
6470         case RENDERPATH_GL13:
6471         case RENDERPATH_GLES1:
6472                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6473                 {
6474                         // apply a color tint to the whole view
6475                         R_ResetViewRendering2D();
6476                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6477                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6478                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6479                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6480                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6481                 }
6482                 break;
6483         }
6484 }
6485
6486 matrix4x4_t r_waterscrollmatrix;
6487
6488 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6489 {
6490         if (r_refdef.fog_density)
6491         {
6492                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6493                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6494                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6495
6496                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6497                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6498                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6499                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6500
6501                 {
6502                         vec3_t fogvec;
6503                         VectorCopy(r_refdef.fogcolor, fogvec);
6504                         //   color.rgb *= ContrastBoost * SceneBrightness;
6505                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6506                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6507                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6508                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6509                 }
6510         }
6511 }
6512
6513 void R_UpdateVariables(void)
6514 {
6515         R_Textures_Frame();
6516
6517         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6518
6519         r_refdef.farclip = r_farclip_base.value;
6520         if (r_refdef.scene.worldmodel)
6521                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6522         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6523
6524         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6525                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6526         r_refdef.polygonfactor = 0;
6527         r_refdef.polygonoffset = 0;
6528         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6529         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6530
6531         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6532         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6533         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6534         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6535         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6536         if (FAKELIGHT_ENABLED)
6537         {
6538                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6539         }
6540         if (r_showsurfaces.integer)
6541         {
6542                 r_refdef.scene.rtworld = false;
6543                 r_refdef.scene.rtworldshadows = false;
6544                 r_refdef.scene.rtdlight = false;
6545                 r_refdef.scene.rtdlightshadows = false;
6546                 r_refdef.lightmapintensity = 0;
6547         }
6548
6549         if (gamemode == GAME_NEHAHRA)
6550         {
6551                 if (gl_fogenable.integer)
6552                 {
6553                         r_refdef.oldgl_fogenable = true;
6554                         r_refdef.fog_density = gl_fogdensity.value;
6555                         r_refdef.fog_red = gl_fogred.value;
6556                         r_refdef.fog_green = gl_foggreen.value;
6557                         r_refdef.fog_blue = gl_fogblue.value;
6558                         r_refdef.fog_alpha = 1;
6559                         r_refdef.fog_start = 0;
6560                         r_refdef.fog_end = gl_skyclip.value;
6561                         r_refdef.fog_height = 1<<30;
6562                         r_refdef.fog_fadedepth = 128;
6563                 }
6564                 else if (r_refdef.oldgl_fogenable)
6565                 {
6566                         r_refdef.oldgl_fogenable = false;
6567                         r_refdef.fog_density = 0;
6568                         r_refdef.fog_red = 0;
6569                         r_refdef.fog_green = 0;
6570                         r_refdef.fog_blue = 0;
6571                         r_refdef.fog_alpha = 0;
6572                         r_refdef.fog_start = 0;
6573                         r_refdef.fog_end = 0;
6574                         r_refdef.fog_height = 1<<30;
6575                         r_refdef.fog_fadedepth = 128;
6576                 }
6577         }
6578
6579         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6580         r_refdef.fog_start = max(0, r_refdef.fog_start);
6581         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6582
6583         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6584
6585         if (r_refdef.fog_density && r_drawfog.integer)
6586         {
6587                 r_refdef.fogenabled = true;
6588                 // this is the point where the fog reaches 0.9986 alpha, which we
6589                 // consider a good enough cutoff point for the texture
6590                 // (0.9986 * 256 == 255.6)
6591                 if (r_fog_exp2.integer)
6592                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6593                 else
6594                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6595                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6596                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6597                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6598                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6599                         R_BuildFogHeightTexture();
6600                 // fog color was already set
6601                 // update the fog texture
6602                 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)
6603                         R_BuildFogTexture();
6604                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6605                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6606         }
6607         else
6608                 r_refdef.fogenabled = false;
6609
6610         switch(vid.renderpath)
6611         {
6612         case RENDERPATH_GL20:
6613         case RENDERPATH_D3D9:
6614         case RENDERPATH_D3D10:
6615         case RENDERPATH_D3D11:
6616         case RENDERPATH_SOFT:
6617         case RENDERPATH_GLES2:
6618                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6619                 {
6620                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6621                         {
6622                                 // build GLSL gamma texture
6623 #define RAMPWIDTH 256
6624                                 unsigned short ramp[RAMPWIDTH * 3];
6625                                 unsigned char rampbgr[RAMPWIDTH][4];
6626                                 int i;
6627
6628                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6629
6630                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6631                                 for(i = 0; i < RAMPWIDTH; ++i)
6632                                 {
6633                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6634                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6635                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6636                                         rampbgr[i][3] = 0;
6637                                 }
6638                                 if (r_texture_gammaramps)
6639                                 {
6640                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6641                                 }
6642                                 else
6643                                 {
6644                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6645                                 }
6646                         }
6647                 }
6648                 else
6649                 {
6650                         // remove GLSL gamma texture
6651                 }
6652                 break;
6653         case RENDERPATH_GL11:
6654         case RENDERPATH_GL13:
6655         case RENDERPATH_GLES1:
6656                 break;
6657         }
6658 }
6659
6660 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6661 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6662 /*
6663 ================
6664 R_SelectScene
6665 ================
6666 */
6667 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6668         if( scenetype != r_currentscenetype ) {
6669                 // store the old scenetype
6670                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6671                 r_currentscenetype = scenetype;
6672                 // move in the new scene
6673                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6674         }
6675 }
6676
6677 /*
6678 ================
6679 R_GetScenePointer
6680 ================
6681 */
6682 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6683 {
6684         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6685         if( scenetype == r_currentscenetype ) {
6686                 return &r_refdef.scene;
6687         } else {
6688                 return &r_scenes_store[ scenetype ];
6689         }
6690 }
6691
6692 /*
6693 ================
6694 R_RenderView
6695 ================
6696 */
6697 int dpsoftrast_test;
6698 extern void R_Shadow_UpdateBounceGridTexture(void);
6699 extern cvar_t r_shadow_bouncegrid;
6700 void R_RenderView(void)
6701 {
6702         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6703
6704         dpsoftrast_test = r_test.integer;
6705
6706         if (r_timereport_active)
6707                 R_TimeReport("start");
6708         r_textureframe++; // used only by R_GetCurrentTexture
6709         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6710
6711         if(R_CompileShader_CheckStaticParms())
6712                 R_GLSL_Restart_f();
6713
6714         if (!r_drawentities.integer)
6715                 r_refdef.scene.numentities = 0;
6716
6717         R_AnimCache_ClearCache();
6718         R_FrameData_NewFrame();
6719
6720         /* adjust for stereo display */
6721         if(R_Stereo_Active())
6722         {
6723                 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);
6724                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6725         }
6726
6727         if (r_refdef.view.isoverlay)
6728         {
6729                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6730                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6731                 R_TimeReport("depthclear");
6732
6733                 r_refdef.view.showdebug = false;
6734
6735                 r_waterstate.enabled = false;
6736                 r_waterstate.numwaterplanes = 0;
6737
6738                 R_RenderScene();
6739
6740                 r_refdef.view.matrix = originalmatrix;
6741
6742                 CHECKGLERROR
6743                 return;
6744         }
6745
6746         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6747         {
6748                 r_refdef.view.matrix = originalmatrix;
6749                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6750         }
6751
6752         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6753
6754         R_RenderView_UpdateViewVectors();
6755
6756         R_Shadow_UpdateWorldLightSelection();
6757
6758         R_Bloom_StartFrame();
6759         R_Water_StartFrame();
6760
6761         CHECKGLERROR
6762         if (r_timereport_active)
6763                 R_TimeReport("viewsetup");
6764
6765         R_ResetViewRendering3D();
6766
6767         if (r_refdef.view.clear || r_refdef.fogenabled)
6768         {
6769                 R_ClearScreen(r_refdef.fogenabled);
6770                 if (r_timereport_active)
6771                         R_TimeReport("viewclear");
6772         }
6773         r_refdef.view.clear = true;
6774
6775         // this produces a bloom texture to be used in R_BlendView() later
6776         if (r_bloomstate.hdr)
6777         {
6778                 R_HDR_RenderBloomTexture();
6779                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6780                 r_textureframe++; // used only by R_GetCurrentTexture
6781         }
6782
6783         r_refdef.view.showdebug = true;
6784
6785         R_View_Update();
6786         if (r_timereport_active)
6787                 R_TimeReport("visibility");
6788
6789         R_Shadow_UpdateBounceGridTexture();
6790         if (r_timereport_active && r_shadow_bouncegrid.integer)
6791                 R_TimeReport("bouncegrid");
6792
6793         r_waterstate.numwaterplanes = 0;
6794         if (r_waterstate.enabled)
6795                 R_RenderWaterPlanes();
6796
6797         R_RenderScene();
6798         r_waterstate.numwaterplanes = 0;
6799
6800         R_BlendView();
6801         if (r_timereport_active)
6802                 R_TimeReport("blendview");
6803
6804         GL_Scissor(0, 0, vid.width, vid.height);
6805         GL_ScissorTest(false);
6806
6807         r_refdef.view.matrix = originalmatrix;
6808
6809         CHECKGLERROR
6810 }
6811
6812 void R_RenderWaterPlanes(void)
6813 {
6814         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6815         {
6816                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6817                 if (r_timereport_active)
6818                         R_TimeReport("waterworld");
6819         }
6820
6821         // don't let sound skip if going slow
6822         if (r_refdef.scene.extraupdate)
6823                 S_ExtraUpdate ();
6824
6825         R_DrawModelsAddWaterPlanes();
6826         if (r_timereport_active)
6827                 R_TimeReport("watermodels");
6828
6829         if (r_waterstate.numwaterplanes)
6830         {
6831                 R_Water_ProcessPlanes();
6832                 if (r_timereport_active)
6833                         R_TimeReport("waterscenes");
6834         }
6835 }
6836
6837 extern void R_DrawLightningBeams (void);
6838 extern void VM_CL_AddPolygonsToMeshQueue (void);
6839 extern void R_DrawPortals (void);
6840 extern cvar_t cl_locs_show;
6841 static void R_DrawLocs(void);
6842 static void R_DrawEntityBBoxes(void);
6843 static void R_DrawModelDecals(void);
6844 extern void R_DrawModelShadows(void);
6845 extern void R_DrawModelShadowMaps(void);
6846 extern cvar_t cl_decals_newsystem;
6847 extern qboolean r_shadow_usingdeferredprepass;
6848 void R_RenderScene(void)
6849 {
6850         qboolean shadowmapping = false;
6851
6852         if (r_timereport_active)
6853                 R_TimeReport("beginscene");
6854
6855         r_refdef.stats.renders++;
6856
6857         R_UpdateFogColor();
6858
6859         // don't let sound skip if going slow
6860         if (r_refdef.scene.extraupdate)
6861                 S_ExtraUpdate ();
6862
6863         R_MeshQueue_BeginScene();
6864
6865         R_SkyStartFrame();
6866
6867         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);
6868
6869         if (r_timereport_active)
6870                 R_TimeReport("skystartframe");
6871
6872         if (cl.csqc_vidvars.drawworld)
6873         {
6874                 // don't let sound skip if going slow
6875                 if (r_refdef.scene.extraupdate)
6876                         S_ExtraUpdate ();
6877
6878                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6879                 {
6880                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6881                         if (r_timereport_active)
6882                                 R_TimeReport("worldsky");
6883                 }
6884
6885                 if (R_DrawBrushModelsSky() && r_timereport_active)
6886                         R_TimeReport("bmodelsky");
6887
6888                 if (skyrendermasked && skyrenderlater)
6889                 {
6890                         // we have to force off the water clipping plane while rendering sky
6891                         R_SetupView(false);
6892                         R_Sky();
6893                         R_SetupView(true);
6894                         if (r_timereport_active)
6895                                 R_TimeReport("sky");
6896                 }
6897         }
6898
6899         R_AnimCache_CacheVisibleEntities();
6900         if (r_timereport_active)
6901                 R_TimeReport("animation");
6902
6903         R_Shadow_PrepareLights();
6904         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6905                 R_Shadow_PrepareModelShadows();
6906         if (r_timereport_active)
6907                 R_TimeReport("preparelights");
6908
6909         if (R_Shadow_ShadowMappingEnabled())
6910                 shadowmapping = true;
6911
6912         if (r_shadow_usingdeferredprepass)
6913                 R_Shadow_DrawPrepass();
6914
6915         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6916         {
6917                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6918                 if (r_timereport_active)
6919                         R_TimeReport("worlddepth");
6920         }
6921         if (r_depthfirst.integer >= 2)
6922         {
6923                 R_DrawModelsDepth();
6924                 if (r_timereport_active)
6925                         R_TimeReport("modeldepth");
6926         }
6927
6928         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6929         {
6930                 R_DrawModelShadowMaps();
6931                 R_ResetViewRendering3D();
6932                 // don't let sound skip if going slow
6933                 if (r_refdef.scene.extraupdate)
6934                         S_ExtraUpdate ();
6935         }
6936
6937         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6938         {
6939                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6940                 if (r_timereport_active)
6941                         R_TimeReport("world");
6942         }
6943
6944         // don't let sound skip if going slow
6945         if (r_refdef.scene.extraupdate)
6946                 S_ExtraUpdate ();
6947
6948         R_DrawModels();
6949         if (r_timereport_active)
6950                 R_TimeReport("models");
6951
6952         // don't let sound skip if going slow
6953         if (r_refdef.scene.extraupdate)
6954                 S_ExtraUpdate ();
6955
6956         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6957         {
6958                 R_DrawModelShadows();
6959                 R_ResetViewRendering3D();
6960                 // don't let sound skip if going slow
6961                 if (r_refdef.scene.extraupdate)
6962                         S_ExtraUpdate ();
6963         }
6964
6965         if (!r_shadow_usingdeferredprepass)
6966         {
6967                 R_Shadow_DrawLights();
6968                 if (r_timereport_active)
6969                         R_TimeReport("rtlights");
6970         }
6971
6972         // don't let sound skip if going slow
6973         if (r_refdef.scene.extraupdate)
6974                 S_ExtraUpdate ();
6975
6976         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6977         {
6978                 R_DrawModelShadows();
6979                 R_ResetViewRendering3D();
6980                 // don't let sound skip if going slow
6981                 if (r_refdef.scene.extraupdate)
6982                         S_ExtraUpdate ();
6983         }
6984
6985         if (cl.csqc_vidvars.drawworld)
6986         {
6987                 if (cl_decals_newsystem.integer)
6988                 {
6989                         R_DrawModelDecals();
6990                         if (r_timereport_active)
6991                                 R_TimeReport("modeldecals");
6992                 }
6993                 else
6994                 {
6995                         R_DrawDecals();
6996                         if (r_timereport_active)
6997                                 R_TimeReport("decals");
6998                 }
6999
7000                 R_DrawParticles();
7001                 if (r_timereport_active)
7002                         R_TimeReport("particles");
7003
7004                 R_DrawExplosions();
7005                 if (r_timereport_active)
7006                         R_TimeReport("explosions");
7007
7008                 R_DrawLightningBeams();
7009                 if (r_timereport_active)
7010                         R_TimeReport("lightning");
7011         }
7012
7013         VM_CL_AddPolygonsToMeshQueue();
7014
7015         if (r_refdef.view.showdebug)
7016         {
7017                 if (cl_locs_show.integer)
7018                 {
7019                         R_DrawLocs();
7020                         if (r_timereport_active)
7021                                 R_TimeReport("showlocs");
7022                 }
7023
7024                 if (r_drawportals.integer)
7025                 {
7026                         R_DrawPortals();
7027                         if (r_timereport_active)
7028                                 R_TimeReport("portals");
7029                 }
7030
7031                 if (r_showbboxes.value > 0)
7032                 {
7033                         R_DrawEntityBBoxes();
7034                         if (r_timereport_active)
7035                                 R_TimeReport("bboxes");
7036                 }
7037         }
7038
7039         if (r_transparent.integer)
7040         {
7041                 R_MeshQueue_RenderTransparent();
7042                 if (r_timereport_active)
7043                         R_TimeReport("drawtrans");
7044         }
7045
7046         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))
7047         {
7048                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7049                 if (r_timereport_active)
7050                         R_TimeReport("worlddebug");
7051                 R_DrawModelsDebug();
7052                 if (r_timereport_active)
7053                         R_TimeReport("modeldebug");
7054         }
7055
7056         if (cl.csqc_vidvars.drawworld)
7057         {
7058                 R_Shadow_DrawCoronas();
7059                 if (r_timereport_active)
7060                         R_TimeReport("coronas");
7061         }
7062
7063 #if 0
7064         {
7065                 GL_DepthTest(false);
7066                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7067                 GL_Color(1, 1, 1, 1);
7068                 qglBegin(GL_POLYGON);
7069                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7070                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7071                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7072                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7073                 qglEnd();
7074                 qglBegin(GL_POLYGON);
7075                 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]);
7076                 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]);
7077                 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]);
7078                 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]);
7079                 qglEnd();
7080                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7081         }
7082 #endif
7083
7084         // don't let sound skip if going slow
7085         if (r_refdef.scene.extraupdate)
7086                 S_ExtraUpdate ();
7087
7088         R_ResetViewRendering2D();
7089 }
7090
7091 static const unsigned short bboxelements[36] =
7092 {
7093         5, 1, 3, 5, 3, 7,
7094         6, 2, 0, 6, 0, 4,
7095         7, 3, 2, 7, 2, 6,
7096         4, 0, 1, 4, 1, 5,
7097         4, 5, 7, 4, 7, 6,
7098         1, 0, 2, 1, 2, 3,
7099 };
7100
7101 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7102 {
7103         int i;
7104         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7105
7106         RSurf_ActiveWorldEntity();
7107
7108         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7109         GL_DepthMask(false);
7110         GL_DepthRange(0, 1);
7111         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7112 //      R_Mesh_ResetTextureState();
7113
7114         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7115         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7116         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7117         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7118         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7119         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7120         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7121         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7122         R_FillColors(color4f, 8, cr, cg, cb, ca);
7123         if (r_refdef.fogenabled)
7124         {
7125                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7126                 {
7127                         f1 = RSurf_FogVertex(v);
7128                         f2 = 1 - f1;
7129                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7130                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7131                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7132                 }
7133         }
7134         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7135         R_Mesh_ResetTextureState();
7136         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7137         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7138 }
7139
7140 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7141 {
7142         int i;
7143         float color[4];
7144         prvm_edict_t *edict;
7145         prvm_prog_t *prog_save = prog;
7146
7147         // this function draws bounding boxes of server entities
7148         if (!sv.active)
7149                 return;
7150
7151         GL_CullFace(GL_NONE);
7152         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7153
7154         prog = 0;
7155         SV_VM_Begin();
7156         for (i = 0;i < numsurfaces;i++)
7157         {
7158                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7159                 switch ((int)PRVM_serveredictfloat(edict, solid))
7160                 {
7161                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7162                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7163                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7164                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7165                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7166                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7167                 }
7168                 color[3] *= r_showbboxes.value;
7169                 color[3] = bound(0, color[3], 1);
7170                 GL_DepthTest(!r_showdisabledepthtest.integer);
7171                 GL_CullFace(r_refdef.view.cullface_front);
7172                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7173         }
7174         SV_VM_End();
7175         prog = prog_save;
7176 }
7177
7178 static void R_DrawEntityBBoxes(void)
7179 {
7180         int i;
7181         prvm_edict_t *edict;
7182         vec3_t center;
7183         prvm_prog_t *prog_save = prog;
7184
7185         // this function draws bounding boxes of server entities
7186         if (!sv.active)
7187                 return;
7188
7189         prog = 0;
7190         SV_VM_Begin();
7191         for (i = 0;i < prog->num_edicts;i++)
7192         {
7193                 edict = PRVM_EDICT_NUM(i);
7194                 if (edict->priv.server->free)
7195                         continue;
7196                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7197                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7198                         continue;
7199                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7200                         continue;
7201                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7202                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7203         }
7204         SV_VM_End();
7205         prog = prog_save;
7206 }
7207
7208 static const int nomodelelement3i[24] =
7209 {
7210         5, 2, 0,
7211         5, 1, 2,
7212         5, 0, 3,
7213         5, 3, 1,
7214         0, 2, 4,
7215         2, 1, 4,
7216         3, 0, 4,
7217         1, 3, 4
7218 };
7219
7220 static const unsigned short nomodelelement3s[24] =
7221 {
7222         5, 2, 0,
7223         5, 1, 2,
7224         5, 0, 3,
7225         5, 3, 1,
7226         0, 2, 4,
7227         2, 1, 4,
7228         3, 0, 4,
7229         1, 3, 4
7230 };
7231
7232 static const float nomodelvertex3f[6*3] =
7233 {
7234         -16,   0,   0,
7235          16,   0,   0,
7236           0, -16,   0,
7237           0,  16,   0,
7238           0,   0, -16,
7239           0,   0,  16
7240 };
7241
7242 static const float nomodelcolor4f[6*4] =
7243 {
7244         0.0f, 0.0f, 0.5f, 1.0f,
7245         0.0f, 0.0f, 0.5f, 1.0f,
7246         0.0f, 0.5f, 0.0f, 1.0f,
7247         0.0f, 0.5f, 0.0f, 1.0f,
7248         0.5f, 0.0f, 0.0f, 1.0f,
7249         0.5f, 0.0f, 0.0f, 1.0f
7250 };
7251
7252 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7253 {
7254         int i;
7255         float f1, f2, *c;
7256         float color4f[6*4];
7257
7258         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);
7259
7260         // this is only called once per entity so numsurfaces is always 1, and
7261         // surfacelist is always {0}, so this code does not handle batches
7262
7263         if (rsurface.ent_flags & RENDER_ADDITIVE)
7264         {
7265                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7266                 GL_DepthMask(false);
7267         }
7268         else if (rsurface.colormod[3] < 1)
7269         {
7270                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7271                 GL_DepthMask(false);
7272         }
7273         else
7274         {
7275                 GL_BlendFunc(GL_ONE, GL_ZERO);
7276                 GL_DepthMask(true);
7277         }
7278         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7279         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7280         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7281         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7282         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7283         for (i = 0, c = color4f;i < 6;i++, c += 4)
7284         {
7285                 c[0] *= rsurface.colormod[0];
7286                 c[1] *= rsurface.colormod[1];
7287                 c[2] *= rsurface.colormod[2];
7288                 c[3] *= rsurface.colormod[3];
7289         }
7290         if (r_refdef.fogenabled)
7291         {
7292                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7293                 {
7294                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7295                         f2 = 1 - f1;
7296                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7297                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7298                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7299                 }
7300         }
7301 //      R_Mesh_ResetTextureState();
7302         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7303         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7304         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7305 }
7306
7307 void R_DrawNoModel(entity_render_t *ent)
7308 {
7309         vec3_t org;
7310         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7311         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7312                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7313         else
7314                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7315 }
7316
7317 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7318 {
7319         vec3_t right1, right2, diff, normal;
7320
7321         VectorSubtract (org2, org1, normal);
7322
7323         // calculate 'right' vector for start
7324         VectorSubtract (r_refdef.view.origin, org1, diff);
7325         CrossProduct (normal, diff, right1);
7326         VectorNormalize (right1);
7327
7328         // calculate 'right' vector for end
7329         VectorSubtract (r_refdef.view.origin, org2, diff);
7330         CrossProduct (normal, diff, right2);
7331         VectorNormalize (right2);
7332
7333         vert[ 0] = org1[0] + width * right1[0];
7334         vert[ 1] = org1[1] + width * right1[1];
7335         vert[ 2] = org1[2] + width * right1[2];
7336         vert[ 3] = org1[0] - width * right1[0];
7337         vert[ 4] = org1[1] - width * right1[1];
7338         vert[ 5] = org1[2] - width * right1[2];
7339         vert[ 6] = org2[0] - width * right2[0];
7340         vert[ 7] = org2[1] - width * right2[1];
7341         vert[ 8] = org2[2] - width * right2[2];
7342         vert[ 9] = org2[0] + width * right2[0];
7343         vert[10] = org2[1] + width * right2[1];
7344         vert[11] = org2[2] + width * right2[2];
7345 }
7346
7347 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)
7348 {
7349         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7350         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7351         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7352         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7353         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7354         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7355         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7356         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7357         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7358         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7359         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7360         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7361 }
7362
7363 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7364 {
7365         int i;
7366         float *vertex3f;
7367         float v[3];
7368         VectorSet(v, x, y, z);
7369         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7370                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7371                         break;
7372         if (i == mesh->numvertices)
7373         {
7374                 if (mesh->numvertices < mesh->maxvertices)
7375                 {
7376                         VectorCopy(v, vertex3f);
7377                         mesh->numvertices++;
7378                 }
7379                 return mesh->numvertices;
7380         }
7381         else
7382                 return i;
7383 }
7384
7385 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7386 {
7387         int i;
7388         int *e, element[3];
7389         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7390         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7391         e = mesh->element3i + mesh->numtriangles * 3;
7392         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7393         {
7394                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7395                 if (mesh->numtriangles < mesh->maxtriangles)
7396                 {
7397                         *e++ = element[0];
7398                         *e++ = element[1];
7399                         *e++ = element[2];
7400                         mesh->numtriangles++;
7401                 }
7402                 element[1] = element[2];
7403         }
7404 }
7405
7406 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7407 {
7408         int i;
7409         int *e, element[3];
7410         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7411         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7412         e = mesh->element3i + mesh->numtriangles * 3;
7413         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7414         {
7415                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7416                 if (mesh->numtriangles < mesh->maxtriangles)
7417                 {
7418                         *e++ = element[0];
7419                         *e++ = element[1];
7420                         *e++ = element[2];
7421                         mesh->numtriangles++;
7422                 }
7423                 element[1] = element[2];
7424         }
7425 }
7426
7427 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7428 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7429 {
7430         int planenum, planenum2;
7431         int w;
7432         int tempnumpoints;
7433         mplane_t *plane, *plane2;
7434         double maxdist;
7435         double temppoints[2][256*3];
7436         // figure out how large a bounding box we need to properly compute this brush
7437         maxdist = 0;
7438         for (w = 0;w < numplanes;w++)
7439                 maxdist = max(maxdist, fabs(planes[w].dist));
7440         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7441         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7442         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7443         {
7444                 w = 0;
7445                 tempnumpoints = 4;
7446                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7447                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7448                 {
7449                         if (planenum2 == planenum)
7450                                 continue;
7451                         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);
7452                         w = !w;
7453                 }
7454                 if (tempnumpoints < 3)
7455                         continue;
7456                 // generate elements forming a triangle fan for this polygon
7457                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7458         }
7459 }
7460
7461 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)
7462 {
7463         texturelayer_t *layer;
7464         layer = t->currentlayers + t->currentnumlayers++;
7465         layer->type = type;
7466         layer->depthmask = depthmask;
7467         layer->blendfunc1 = blendfunc1;
7468         layer->blendfunc2 = blendfunc2;
7469         layer->texture = texture;
7470         layer->texmatrix = *matrix;
7471         layer->color[0] = r;
7472         layer->color[1] = g;
7473         layer->color[2] = b;
7474         layer->color[3] = a;
7475 }
7476
7477 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7478 {
7479         if(parms[0] == 0 && parms[1] == 0)
7480                 return false;
7481         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7482                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7483                         return false;
7484         return true;
7485 }
7486
7487 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7488 {
7489         double index, f;
7490         index = parms[2] + rsurface.shadertime * parms[3];
7491         index -= floor(index);
7492         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7493         {
7494         default:
7495         case Q3WAVEFUNC_NONE:
7496         case Q3WAVEFUNC_NOISE:
7497         case Q3WAVEFUNC_COUNT:
7498                 f = 0;
7499                 break;
7500         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7501         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7502         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7503         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7504         case Q3WAVEFUNC_TRIANGLE:
7505                 index *= 4;
7506                 f = index - floor(index);
7507                 if (index < 1)
7508                 {
7509                         // f = f;
7510                 }
7511                 else if (index < 2)
7512                         f = 1 - f;
7513                 else if (index < 3)
7514                         f = -f;
7515                 else
7516                         f = -(1 - f);
7517                 break;
7518         }
7519         f = parms[0] + parms[1] * f;
7520         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7521                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7522         return (float) f;
7523 }
7524
7525 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7526 {
7527         int w, h, idx;
7528         double f;
7529         double offsetd[2];
7530         float tcmat[12];
7531         matrix4x4_t matrix, temp;
7532         switch(tcmod->tcmod)
7533         {
7534                 case Q3TCMOD_COUNT:
7535                 case Q3TCMOD_NONE:
7536                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7537                                 matrix = r_waterscrollmatrix;
7538                         else
7539                                 matrix = identitymatrix;
7540                         break;
7541                 case Q3TCMOD_ENTITYTRANSLATE:
7542                         // this is used in Q3 to allow the gamecode to control texcoord
7543                         // scrolling on the entity, which is not supported in darkplaces yet.
7544                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7545                         break;
7546                 case Q3TCMOD_ROTATE:
7547                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7548                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7549                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7550                         break;
7551                 case Q3TCMOD_SCALE:
7552                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7553                         break;
7554                 case Q3TCMOD_SCROLL:
7555                         // extra care is needed because of precision breakdown with large values of time
7556                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7557                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7558                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7559                         break;
7560                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7561                         w = (int) tcmod->parms[0];
7562                         h = (int) tcmod->parms[1];
7563                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7564                         f = f - floor(f);
7565                         idx = (int) floor(f * w * h);
7566                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7567                         break;
7568                 case Q3TCMOD_STRETCH:
7569                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7570                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7571                         break;
7572                 case Q3TCMOD_TRANSFORM:
7573                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7574                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7575                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7576                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7577                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7578                         break;
7579                 case Q3TCMOD_TURBULENT:
7580                         // this is handled in the RSurf_PrepareVertices function
7581                         matrix = identitymatrix;
7582                         break;
7583         }
7584         temp = *texmatrix;
7585         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7586 }
7587
7588 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7589 {
7590         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7591         char name[MAX_QPATH];
7592         skinframe_t *skinframe;
7593         unsigned char pixels[296*194];
7594         strlcpy(cache->name, skinname, sizeof(cache->name));
7595         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7596         if (developer_loading.integer)
7597                 Con_Printf("loading %s\n", name);
7598         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7599         if (!skinframe || !skinframe->base)
7600         {
7601                 unsigned char *f;
7602                 fs_offset_t filesize;
7603                 skinframe = NULL;
7604                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7605                 if (f)
7606                 {
7607                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7608                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7609                         Mem_Free(f);
7610                 }
7611         }
7612         cache->skinframe = skinframe;
7613 }
7614
7615 texture_t *R_GetCurrentTexture(texture_t *t)
7616 {
7617         int i;
7618         const entity_render_t *ent = rsurface.entity;
7619         dp_model_t *model = ent->model;
7620         q3shaderinfo_layer_tcmod_t *tcmod;
7621
7622         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7623                 return t->currentframe;
7624         t->update_lastrenderframe = r_textureframe;
7625         t->update_lastrenderentity = (void *)ent;
7626
7627         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7628                 t->camera_entity = ent->entitynumber;
7629         else
7630                 t->camera_entity = 0;
7631
7632         // switch to an alternate material if this is a q1bsp animated material
7633         {
7634                 texture_t *texture = t;
7635                 int s = rsurface.ent_skinnum;
7636                 if ((unsigned int)s >= (unsigned int)model->numskins)
7637                         s = 0;
7638                 if (model->skinscenes)
7639                 {
7640                         if (model->skinscenes[s].framecount > 1)
7641                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7642                         else
7643                                 s = model->skinscenes[s].firstframe;
7644                 }
7645                 if (s > 0)
7646                         t = t + s * model->num_surfaces;
7647                 if (t->animated)
7648                 {
7649                         // use an alternate animation if the entity's frame is not 0,
7650                         // and only if the texture has an alternate animation
7651                         if (rsurface.ent_alttextures && t->anim_total[1])
7652                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7653                         else
7654                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7655                 }
7656                 texture->currentframe = t;
7657         }
7658
7659         // update currentskinframe to be a qw skin or animation frame
7660         if (rsurface.ent_qwskin >= 0)
7661         {
7662                 i = rsurface.ent_qwskin;
7663                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7664                 {
7665                         r_qwskincache_size = cl.maxclients;
7666                         if (r_qwskincache)
7667                                 Mem_Free(r_qwskincache);
7668                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7669                 }
7670                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7671                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7672                 t->currentskinframe = r_qwskincache[i].skinframe;
7673                 if (t->currentskinframe == NULL)
7674                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7675         }
7676         else if (t->numskinframes >= 2)
7677                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7678         if (t->backgroundnumskinframes >= 2)
7679                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7680
7681         t->currentmaterialflags = t->basematerialflags;
7682         t->currentalpha = rsurface.colormod[3];
7683         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7684                 t->currentalpha *= r_wateralpha.value;
7685         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7686                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7687         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7688                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7689         if (!(rsurface.ent_flags & RENDER_LIGHT))
7690                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7691         else if (FAKELIGHT_ENABLED)
7692         {
7693                 // no modellight if using fakelight for the map
7694         }
7695         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7696         {
7697                 // pick a model lighting mode
7698                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7699                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7700                 else
7701                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7702         }
7703         if (rsurface.ent_flags & RENDER_ADDITIVE)
7704                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7705         else if (t->currentalpha < 1)
7706                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7707         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7708                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7709         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7710                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7711         if (t->backgroundnumskinframes)
7712                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7713         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7714         {
7715                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7716                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7717         }
7718         else
7719                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7720         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7721         {
7722                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7723                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7724         }
7725         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7726                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7727
7728         // there is no tcmod
7729         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7730         {
7731                 t->currenttexmatrix = r_waterscrollmatrix;
7732                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7733         }
7734         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7735         {
7736                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7737                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7738         }
7739
7740         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7741                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7742         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7743                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7744
7745         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7746         if (t->currentskinframe->qpixels)
7747                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7748         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7749         if (!t->basetexture)
7750                 t->basetexture = r_texture_notexture;
7751         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7752         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7753         t->nmaptexture = t->currentskinframe->nmap;
7754         if (!t->nmaptexture)
7755                 t->nmaptexture = r_texture_blanknormalmap;
7756         t->glosstexture = r_texture_black;
7757         t->glowtexture = t->currentskinframe->glow;
7758         t->fogtexture = t->currentskinframe->fog;
7759         t->reflectmasktexture = t->currentskinframe->reflect;
7760         if (t->backgroundnumskinframes)
7761         {
7762                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7763                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7764                 t->backgroundglosstexture = r_texture_black;
7765                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7766                 if (!t->backgroundnmaptexture)
7767                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7768         }
7769         else
7770         {
7771                 t->backgroundbasetexture = r_texture_white;
7772                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7773                 t->backgroundglosstexture = r_texture_black;
7774                 t->backgroundglowtexture = NULL;
7775         }
7776         t->specularpower = r_shadow_glossexponent.value;
7777         // TODO: store reference values for these in the texture?
7778         t->specularscale = 0;
7779         if (r_shadow_gloss.integer > 0)
7780         {
7781                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7782                 {
7783                         if (r_shadow_glossintensity.value > 0)
7784                         {
7785                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7786                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7787                                 t->specularscale = r_shadow_glossintensity.value;
7788                         }
7789                 }
7790                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7791                 {
7792                         t->glosstexture = r_texture_white;
7793                         t->backgroundglosstexture = r_texture_white;
7794                         t->specularscale = r_shadow_gloss2intensity.value;
7795                         t->specularpower = r_shadow_gloss2exponent.value;
7796                 }
7797         }
7798         t->specularscale *= t->specularscalemod;
7799         t->specularpower *= t->specularpowermod;
7800
7801         // lightmaps mode looks bad with dlights using actual texturing, so turn
7802         // off the colormap and glossmap, but leave the normalmap on as it still
7803         // accurately represents the shading involved
7804         if (gl_lightmaps.integer)
7805         {
7806                 t->basetexture = r_texture_grey128;
7807                 t->pantstexture = r_texture_black;
7808                 t->shirttexture = r_texture_black;
7809                 t->nmaptexture = r_texture_blanknormalmap;
7810                 t->glosstexture = r_texture_black;
7811                 t->glowtexture = NULL;
7812                 t->fogtexture = NULL;
7813                 t->reflectmasktexture = NULL;
7814                 t->backgroundbasetexture = NULL;
7815                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7816                 t->backgroundglosstexture = r_texture_black;
7817                 t->backgroundglowtexture = NULL;
7818                 t->specularscale = 0;
7819                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7820         }
7821
7822         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7823         VectorClear(t->dlightcolor);
7824         t->currentnumlayers = 0;
7825         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7826         {
7827                 int blendfunc1, blendfunc2;
7828                 qboolean depthmask;
7829                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7830                 {
7831                         blendfunc1 = GL_SRC_ALPHA;
7832                         blendfunc2 = GL_ONE;
7833                 }
7834                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7835                 {
7836                         blendfunc1 = GL_SRC_ALPHA;
7837                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7838                 }
7839                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7840                 {
7841                         blendfunc1 = t->customblendfunc[0];
7842                         blendfunc2 = t->customblendfunc[1];
7843                 }
7844                 else
7845                 {
7846                         blendfunc1 = GL_ONE;
7847                         blendfunc2 = GL_ZERO;
7848                 }
7849                 // don't colormod evilblend textures
7850                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7851                         VectorSet(t->lightmapcolor, 1, 1, 1);
7852                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7853                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7854                 {
7855                         // fullbright is not affected by r_refdef.lightmapintensity
7856                         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]);
7857                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7858                                 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]);
7859                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7860                                 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]);
7861                 }
7862                 else
7863                 {
7864                         vec3_t ambientcolor;
7865                         float colorscale;
7866                         // set the color tint used for lights affecting this surface
7867                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7868                         colorscale = 2;
7869                         // q3bsp has no lightmap updates, so the lightstylevalue that
7870                         // would normally be baked into the lightmap must be
7871                         // applied to the color
7872                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7873                         if (model->type == mod_brushq3)
7874                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7875                         colorscale *= r_refdef.lightmapintensity;
7876                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7877                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7878                         // basic lit geometry
7879                         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]);
7880                         // add pants/shirt if needed
7881                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7882                                 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]);
7883                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7884                                 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]);
7885                         // now add ambient passes if needed
7886                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7887                         {
7888                                 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]);
7889                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7890                                         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]);
7891                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7892                                         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]);
7893                         }
7894                 }
7895                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7896                         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]);
7897                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7898                 {
7899                         // if this is opaque use alpha blend which will darken the earlier
7900                         // passes cheaply.
7901                         //
7902                         // if this is an alpha blended material, all the earlier passes
7903                         // were darkened by fog already, so we only need to add the fog
7904                         // color ontop through the fog mask texture
7905                         //
7906                         // if this is an additive blended material, all the earlier passes
7907                         // were darkened by fog already, and we should not add fog color
7908                         // (because the background was not darkened, there is no fog color
7909                         // that was lost behind it).
7910                         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]);
7911                 }
7912         }
7913
7914         return t->currentframe;
7915 }
7916
7917 rsurfacestate_t rsurface;
7918
7919 void RSurf_ActiveWorldEntity(void)
7920 {
7921         dp_model_t *model = r_refdef.scene.worldmodel;
7922         //if (rsurface.entity == r_refdef.scene.worldentity)
7923         //      return;
7924         rsurface.entity = r_refdef.scene.worldentity;
7925         rsurface.skeleton = NULL;
7926         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7927         rsurface.ent_skinnum = 0;
7928         rsurface.ent_qwskin = -1;
7929         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7930         rsurface.shadertime = r_refdef.scene.time;
7931         rsurface.matrix = identitymatrix;
7932         rsurface.inversematrix = identitymatrix;
7933         rsurface.matrixscale = 1;
7934         rsurface.inversematrixscale = 1;
7935         R_EntityMatrix(&identitymatrix);
7936         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7937         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7938         rsurface.fograngerecip = r_refdef.fograngerecip;
7939         rsurface.fogheightfade = r_refdef.fogheightfade;
7940         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7941         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7942         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7943         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7944         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7945         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7946         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7947         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7948         rsurface.colormod[3] = 1;
7949         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);
7950         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7951         rsurface.frameblend[0].lerp = 1;
7952         rsurface.ent_alttextures = false;
7953         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7954         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7955         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7956         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7957         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7958         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7959         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7960         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7961         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7962         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7963         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7964         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7965         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7966         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7967         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7968         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7969         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7970         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7971         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7972         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7973         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7974         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7975         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7976         rsurface.modelelement3i = model->surfmesh.data_element3i;
7977         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7978         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7979         rsurface.modelelement3s = model->surfmesh.data_element3s;
7980         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7981         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7982         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7983         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7984         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7985         rsurface.modelsurfaces = model->data_surfaces;
7986         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7987         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7988         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7989         rsurface.modelgeneratedvertex = false;
7990         rsurface.batchgeneratedvertex = false;
7991         rsurface.batchfirstvertex = 0;
7992         rsurface.batchnumvertices = 0;
7993         rsurface.batchfirsttriangle = 0;
7994         rsurface.batchnumtriangles = 0;
7995         rsurface.batchvertex3f  = NULL;
7996         rsurface.batchvertex3f_vertexbuffer = NULL;
7997         rsurface.batchvertex3f_bufferoffset = 0;
7998         rsurface.batchsvector3f = NULL;
7999         rsurface.batchsvector3f_vertexbuffer = NULL;
8000         rsurface.batchsvector3f_bufferoffset = 0;
8001         rsurface.batchtvector3f = NULL;
8002         rsurface.batchtvector3f_vertexbuffer = NULL;
8003         rsurface.batchtvector3f_bufferoffset = 0;
8004         rsurface.batchnormal3f  = NULL;
8005         rsurface.batchnormal3f_vertexbuffer = NULL;
8006         rsurface.batchnormal3f_bufferoffset = 0;
8007         rsurface.batchlightmapcolor4f = NULL;
8008         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8009         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8010         rsurface.batchtexcoordtexture2f = NULL;
8011         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8012         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8013         rsurface.batchtexcoordlightmap2f = NULL;
8014         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8015         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8016         rsurface.batchvertexmesh = NULL;
8017         rsurface.batchvertexmeshbuffer = NULL;
8018         rsurface.batchvertex3fbuffer = NULL;
8019         rsurface.batchelement3i = NULL;
8020         rsurface.batchelement3i_indexbuffer = NULL;
8021         rsurface.batchelement3i_bufferoffset = 0;
8022         rsurface.batchelement3s = NULL;
8023         rsurface.batchelement3s_indexbuffer = NULL;
8024         rsurface.batchelement3s_bufferoffset = 0;
8025         rsurface.passcolor4f = NULL;
8026         rsurface.passcolor4f_vertexbuffer = NULL;
8027         rsurface.passcolor4f_bufferoffset = 0;
8028 }
8029
8030 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8031 {
8032         dp_model_t *model = ent->model;
8033         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8034         //      return;
8035         rsurface.entity = (entity_render_t *)ent;
8036         rsurface.skeleton = ent->skeleton;
8037         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8038         rsurface.ent_skinnum = ent->skinnum;
8039         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;
8040         rsurface.ent_flags = ent->flags;
8041         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8042         rsurface.matrix = ent->matrix;
8043         rsurface.inversematrix = ent->inversematrix;
8044         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8045         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8046         R_EntityMatrix(&rsurface.matrix);
8047         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8048         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8049         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8050         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8051         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8052         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8053         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8054         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8055         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8056         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8057         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8058         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8059         rsurface.colormod[3] = ent->alpha;
8060         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8061         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8062         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8063         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8064         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8065         if (ent->model->brush.submodel && !prepass)
8066         {
8067                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8068                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8069         }
8070         if (model->surfmesh.isanimated && model->AnimateVertices)
8071         {
8072                 if (ent->animcache_vertex3f)
8073                 {
8074                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8075                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8076                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8077                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8078                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8079                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8080                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8081                 }
8082                 else if (wanttangents)
8083                 {
8084                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8085                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8086                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8087                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8088                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8089                         rsurface.modelvertexmesh = NULL;
8090                         rsurface.modelvertexmeshbuffer = NULL;
8091                         rsurface.modelvertex3fbuffer = NULL;
8092                 }
8093                 else if (wantnormals)
8094                 {
8095                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8096                         rsurface.modelsvector3f = NULL;
8097                         rsurface.modeltvector3f = NULL;
8098                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8099                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8100                         rsurface.modelvertexmesh = NULL;
8101                         rsurface.modelvertexmeshbuffer = NULL;
8102                         rsurface.modelvertex3fbuffer = NULL;
8103                 }
8104                 else
8105                 {
8106                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8107                         rsurface.modelsvector3f = NULL;
8108                         rsurface.modeltvector3f = NULL;
8109                         rsurface.modelnormal3f = NULL;
8110                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8111                         rsurface.modelvertexmesh = NULL;
8112                         rsurface.modelvertexmeshbuffer = NULL;
8113                         rsurface.modelvertex3fbuffer = NULL;
8114                 }
8115                 rsurface.modelvertex3f_vertexbuffer = 0;
8116                 rsurface.modelvertex3f_bufferoffset = 0;
8117                 rsurface.modelsvector3f_vertexbuffer = 0;
8118                 rsurface.modelsvector3f_bufferoffset = 0;
8119                 rsurface.modeltvector3f_vertexbuffer = 0;
8120                 rsurface.modeltvector3f_bufferoffset = 0;
8121                 rsurface.modelnormal3f_vertexbuffer = 0;
8122                 rsurface.modelnormal3f_bufferoffset = 0;
8123                 rsurface.modelgeneratedvertex = true;
8124         }
8125         else
8126         {
8127                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8128                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8129                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8130                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8131                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8132                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8133                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8134                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8135                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8136                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8137                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8138                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8139                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8140                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8141                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8142                 rsurface.modelgeneratedvertex = false;
8143         }
8144         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8145         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8146         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8147         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8148         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8149         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8150         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8151         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8152         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8153         rsurface.modelelement3i = model->surfmesh.data_element3i;
8154         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8155         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8156         rsurface.modelelement3s = model->surfmesh.data_element3s;
8157         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8158         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8159         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8160         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8161         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8162         rsurface.modelsurfaces = model->data_surfaces;
8163         rsurface.batchgeneratedvertex = false;
8164         rsurface.batchfirstvertex = 0;
8165         rsurface.batchnumvertices = 0;
8166         rsurface.batchfirsttriangle = 0;
8167         rsurface.batchnumtriangles = 0;
8168         rsurface.batchvertex3f  = NULL;
8169         rsurface.batchvertex3f_vertexbuffer = NULL;
8170         rsurface.batchvertex3f_bufferoffset = 0;
8171         rsurface.batchsvector3f = NULL;
8172         rsurface.batchsvector3f_vertexbuffer = NULL;
8173         rsurface.batchsvector3f_bufferoffset = 0;
8174         rsurface.batchtvector3f = NULL;
8175         rsurface.batchtvector3f_vertexbuffer = NULL;
8176         rsurface.batchtvector3f_bufferoffset = 0;
8177         rsurface.batchnormal3f  = NULL;
8178         rsurface.batchnormal3f_vertexbuffer = NULL;
8179         rsurface.batchnormal3f_bufferoffset = 0;
8180         rsurface.batchlightmapcolor4f = NULL;
8181         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8182         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8183         rsurface.batchtexcoordtexture2f = NULL;
8184         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8185         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8186         rsurface.batchtexcoordlightmap2f = NULL;
8187         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8188         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8189         rsurface.batchvertexmesh = NULL;
8190         rsurface.batchvertexmeshbuffer = NULL;
8191         rsurface.batchvertex3fbuffer = NULL;
8192         rsurface.batchelement3i = NULL;
8193         rsurface.batchelement3i_indexbuffer = NULL;
8194         rsurface.batchelement3i_bufferoffset = 0;
8195         rsurface.batchelement3s = NULL;
8196         rsurface.batchelement3s_indexbuffer = NULL;
8197         rsurface.batchelement3s_bufferoffset = 0;
8198         rsurface.passcolor4f = NULL;
8199         rsurface.passcolor4f_vertexbuffer = NULL;
8200         rsurface.passcolor4f_bufferoffset = 0;
8201 }
8202
8203 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)
8204 {
8205         rsurface.entity = r_refdef.scene.worldentity;
8206         rsurface.skeleton = NULL;
8207         rsurface.ent_skinnum = 0;
8208         rsurface.ent_qwskin = -1;
8209         rsurface.ent_flags = entflags;
8210         rsurface.shadertime = r_refdef.scene.time - shadertime;
8211         rsurface.modelnumvertices = numvertices;
8212         rsurface.modelnumtriangles = numtriangles;
8213         rsurface.matrix = *matrix;
8214         rsurface.inversematrix = *inversematrix;
8215         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8216         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8217         R_EntityMatrix(&rsurface.matrix);
8218         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8219         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8220         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8221         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8222         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8223         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8224         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8225         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8226         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8227         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8228         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8229         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8230         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);
8231         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8232         rsurface.frameblend[0].lerp = 1;
8233         rsurface.ent_alttextures = false;
8234         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8235         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8236         if (wanttangents)
8237         {
8238                 rsurface.modelvertex3f = (float *)vertex3f;
8239                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8240                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8241                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8242         }
8243         else if (wantnormals)
8244         {
8245                 rsurface.modelvertex3f = (float *)vertex3f;
8246                 rsurface.modelsvector3f = NULL;
8247                 rsurface.modeltvector3f = NULL;
8248                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8249         }
8250         else
8251         {
8252                 rsurface.modelvertex3f = (float *)vertex3f;
8253                 rsurface.modelsvector3f = NULL;
8254                 rsurface.modeltvector3f = NULL;
8255                 rsurface.modelnormal3f = NULL;
8256         }
8257         rsurface.modelvertexmesh = NULL;
8258         rsurface.modelvertexmeshbuffer = NULL;
8259         rsurface.modelvertex3fbuffer = NULL;
8260         rsurface.modelvertex3f_vertexbuffer = 0;
8261         rsurface.modelvertex3f_bufferoffset = 0;
8262         rsurface.modelsvector3f_vertexbuffer = 0;
8263         rsurface.modelsvector3f_bufferoffset = 0;
8264         rsurface.modeltvector3f_vertexbuffer = 0;
8265         rsurface.modeltvector3f_bufferoffset = 0;
8266         rsurface.modelnormal3f_vertexbuffer = 0;
8267         rsurface.modelnormal3f_bufferoffset = 0;
8268         rsurface.modelgeneratedvertex = true;
8269         rsurface.modellightmapcolor4f  = (float *)color4f;
8270         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8271         rsurface.modellightmapcolor4f_bufferoffset = 0;
8272         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8273         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8274         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8275         rsurface.modeltexcoordlightmap2f  = NULL;
8276         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8277         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8278         rsurface.modelelement3i = (int *)element3i;
8279         rsurface.modelelement3i_indexbuffer = NULL;
8280         rsurface.modelelement3i_bufferoffset = 0;
8281         rsurface.modelelement3s = (unsigned short *)element3s;
8282         rsurface.modelelement3s_indexbuffer = NULL;
8283         rsurface.modelelement3s_bufferoffset = 0;
8284         rsurface.modellightmapoffsets = NULL;
8285         rsurface.modelsurfaces = NULL;
8286         rsurface.batchgeneratedvertex = false;
8287         rsurface.batchfirstvertex = 0;
8288         rsurface.batchnumvertices = 0;
8289         rsurface.batchfirsttriangle = 0;
8290         rsurface.batchnumtriangles = 0;
8291         rsurface.batchvertex3f  = NULL;
8292         rsurface.batchvertex3f_vertexbuffer = NULL;
8293         rsurface.batchvertex3f_bufferoffset = 0;
8294         rsurface.batchsvector3f = NULL;
8295         rsurface.batchsvector3f_vertexbuffer = NULL;
8296         rsurface.batchsvector3f_bufferoffset = 0;
8297         rsurface.batchtvector3f = NULL;
8298         rsurface.batchtvector3f_vertexbuffer = NULL;
8299         rsurface.batchtvector3f_bufferoffset = 0;
8300         rsurface.batchnormal3f  = NULL;
8301         rsurface.batchnormal3f_vertexbuffer = NULL;
8302         rsurface.batchnormal3f_bufferoffset = 0;
8303         rsurface.batchlightmapcolor4f = NULL;
8304         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8305         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8306         rsurface.batchtexcoordtexture2f = NULL;
8307         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8308         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8309         rsurface.batchtexcoordlightmap2f = NULL;
8310         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8311         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8312         rsurface.batchvertexmesh = NULL;
8313         rsurface.batchvertexmeshbuffer = NULL;
8314         rsurface.batchvertex3fbuffer = NULL;
8315         rsurface.batchelement3i = NULL;
8316         rsurface.batchelement3i_indexbuffer = NULL;
8317         rsurface.batchelement3i_bufferoffset = 0;
8318         rsurface.batchelement3s = NULL;
8319         rsurface.batchelement3s_indexbuffer = NULL;
8320         rsurface.batchelement3s_bufferoffset = 0;
8321         rsurface.passcolor4f = NULL;
8322         rsurface.passcolor4f_vertexbuffer = NULL;
8323         rsurface.passcolor4f_bufferoffset = 0;
8324
8325         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8326         {
8327                 if ((wantnormals || wanttangents) && !normal3f)
8328                 {
8329                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8330                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8331                 }
8332                 if (wanttangents && !svector3f)
8333                 {
8334                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8335                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8336                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8337                 }
8338         }
8339 }
8340
8341 float RSurf_FogPoint(const float *v)
8342 {
8343         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8344         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8345         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8346         float FogHeightFade = r_refdef.fogheightfade;
8347         float fogfrac;
8348         unsigned int fogmasktableindex;
8349         if (r_refdef.fogplaneviewabove)
8350                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8351         else
8352                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8353         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8354         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8355 }
8356
8357 float RSurf_FogVertex(const float *v)
8358 {
8359         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8360         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8361         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8362         float FogHeightFade = rsurface.fogheightfade;
8363         float fogfrac;
8364         unsigned int fogmasktableindex;
8365         if (r_refdef.fogplaneviewabove)
8366                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8367         else
8368                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8369         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8370         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8371 }
8372
8373 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8374 {
8375         int i;
8376         for (i = 0;i < numelements;i++)
8377                 outelement3i[i] = inelement3i[i] + adjust;
8378 }
8379
8380 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8381 extern cvar_t gl_vbo;
8382 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8383 {
8384         int deformindex;
8385         int firsttriangle;
8386         int numtriangles;
8387         int firstvertex;
8388         int endvertex;
8389         int numvertices;
8390         int surfacefirsttriangle;
8391         int surfacenumtriangles;
8392         int surfacefirstvertex;
8393         int surfaceendvertex;
8394         int surfacenumvertices;
8395         int batchnumvertices;
8396         int batchnumtriangles;
8397         int needsupdate;
8398         int i, j;
8399         qboolean gaps;
8400         qboolean dynamicvertex;
8401         float amplitude;
8402         float animpos;
8403         float scale;
8404         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8405         float waveparms[4];
8406         q3shaderinfo_deform_t *deform;
8407         const msurface_t *surface, *firstsurface;
8408         r_vertexmesh_t *vertexmesh;
8409         if (!texturenumsurfaces)
8410                 return;
8411         // find vertex range of this surface batch
8412         gaps = false;
8413         firstsurface = texturesurfacelist[0];
8414         firsttriangle = firstsurface->num_firsttriangle;
8415         batchnumvertices = 0;
8416         batchnumtriangles = 0;
8417         firstvertex = endvertex = firstsurface->num_firstvertex;
8418         for (i = 0;i < texturenumsurfaces;i++)
8419         {
8420                 surface = texturesurfacelist[i];
8421                 if (surface != firstsurface + i)
8422                         gaps = true;
8423                 surfacefirstvertex = surface->num_firstvertex;
8424                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8425                 surfacenumvertices = surface->num_vertices;
8426                 surfacenumtriangles = surface->num_triangles;
8427                 if (firstvertex > surfacefirstvertex)
8428                         firstvertex = surfacefirstvertex;
8429                 if (endvertex < surfaceendvertex)
8430                         endvertex = surfaceendvertex;
8431                 batchnumvertices += surfacenumvertices;
8432                 batchnumtriangles += surfacenumtriangles;
8433         }
8434
8435         // we now know the vertex range used, and if there are any gaps in it
8436         rsurface.batchfirstvertex = firstvertex;
8437         rsurface.batchnumvertices = endvertex - firstvertex;
8438         rsurface.batchfirsttriangle = firsttriangle;
8439         rsurface.batchnumtriangles = batchnumtriangles;
8440
8441         // this variable holds flags for which properties have been updated that
8442         // may require regenerating vertexmesh array...
8443         needsupdate = 0;
8444
8445         // check if any dynamic vertex processing must occur
8446         dynamicvertex = false;
8447
8448         // if there is a chance of animated vertex colors, it's a dynamic batch
8449         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8450         {
8451                 dynamicvertex = true;
8452                 batchneed |= BATCHNEED_NOGAPS;
8453                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8454         }
8455
8456         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8457         {
8458                 switch (deform->deform)
8459                 {
8460                 default:
8461                 case Q3DEFORM_PROJECTIONSHADOW:
8462                 case Q3DEFORM_TEXT0:
8463                 case Q3DEFORM_TEXT1:
8464                 case Q3DEFORM_TEXT2:
8465                 case Q3DEFORM_TEXT3:
8466                 case Q3DEFORM_TEXT4:
8467                 case Q3DEFORM_TEXT5:
8468                 case Q3DEFORM_TEXT6:
8469                 case Q3DEFORM_TEXT7:
8470                 case Q3DEFORM_NONE:
8471                         break;
8472                 case Q3DEFORM_AUTOSPRITE:
8473                         dynamicvertex = true;
8474                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8475                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8476                         break;
8477                 case Q3DEFORM_AUTOSPRITE2:
8478                         dynamicvertex = true;
8479                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8480                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8481                         break;
8482                 case Q3DEFORM_NORMAL:
8483                         dynamicvertex = true;
8484                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8485                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8486                         break;
8487                 case Q3DEFORM_WAVE:
8488                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8489                                 break; // if wavefunc is a nop, ignore this transform
8490                         dynamicvertex = true;
8491                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8492                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8493                         break;
8494                 case Q3DEFORM_BULGE:
8495                         dynamicvertex = true;
8496                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8497                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8498                         break;
8499                 case Q3DEFORM_MOVE:
8500                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8501                                 break; // if wavefunc is a nop, ignore this transform
8502                         dynamicvertex = true;
8503                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8504                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8505                         break;
8506                 }
8507         }
8508         switch(rsurface.texture->tcgen.tcgen)
8509         {
8510         default:
8511         case Q3TCGEN_TEXTURE:
8512                 break;
8513         case Q3TCGEN_LIGHTMAP:
8514                 dynamicvertex = true;
8515                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8516                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8517                 break;
8518         case Q3TCGEN_VECTOR:
8519                 dynamicvertex = true;
8520                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8521                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8522                 break;
8523         case Q3TCGEN_ENVIRONMENT:
8524                 dynamicvertex = true;
8525                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8526                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8527                 break;
8528         }
8529         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8530         {
8531                 dynamicvertex = true;
8532                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8533                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8534         }
8535
8536         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8537         {
8538                 dynamicvertex = true;
8539                 batchneed |= BATCHNEED_NOGAPS;
8540                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8541         }
8542
8543         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8544         {
8545                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8546                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8547                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8548                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8549                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8550                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8551                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8552         }
8553
8554         // when the model data has no vertex buffer (dynamic mesh), we need to
8555         // eliminate gaps
8556         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8557                 batchneed |= BATCHNEED_NOGAPS;
8558
8559         // if needsupdate, we have to do a dynamic vertex batch for sure
8560         if (needsupdate & batchneed)
8561                 dynamicvertex = true;
8562
8563         // see if we need to build vertexmesh from arrays
8564         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8565                 dynamicvertex = true;
8566
8567         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8568         // also some drivers strongly dislike firstvertex
8569         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8570                 dynamicvertex = true;
8571
8572         rsurface.batchvertex3f = rsurface.modelvertex3f;
8573         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8574         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8575         rsurface.batchsvector3f = rsurface.modelsvector3f;
8576         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8577         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8578         rsurface.batchtvector3f = rsurface.modeltvector3f;
8579         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8580         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8581         rsurface.batchnormal3f = rsurface.modelnormal3f;
8582         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8583         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8584         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8585         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8586         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8587         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8588         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8589         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8590         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8591         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8592         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8593         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8594         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8595         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8596         rsurface.batchelement3i = rsurface.modelelement3i;
8597         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8598         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8599         rsurface.batchelement3s = rsurface.modelelement3s;
8600         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8601         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8602
8603         // if any dynamic vertex processing has to occur in software, we copy the
8604         // entire surface list together before processing to rebase the vertices
8605         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8606         //
8607         // if any gaps exist and we do not have a static vertex buffer, we have to
8608         // copy the surface list together to avoid wasting upload bandwidth on the
8609         // vertices in the gaps.
8610         //
8611         // if gaps exist and we have a static vertex buffer, we still have to
8612         // combine the index buffer ranges into one dynamic index buffer.
8613         //
8614         // in all cases we end up with data that can be drawn in one call.
8615
8616         if (!dynamicvertex)
8617         {
8618                 // static vertex data, just set pointers...
8619                 rsurface.batchgeneratedvertex = false;
8620                 // if there are gaps, we want to build a combined index buffer,
8621                 // otherwise use the original static buffer with an appropriate offset
8622                 if (gaps)
8623                 {
8624                         // build a new triangle elements array for this batch
8625                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8626                         rsurface.batchfirsttriangle = 0;
8627                         numtriangles = 0;
8628                         for (i = 0;i < texturenumsurfaces;i++)
8629                         {
8630                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8631                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8632                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8633                                 numtriangles += surfacenumtriangles;
8634                         }
8635                         rsurface.batchelement3i_indexbuffer = NULL;
8636                         rsurface.batchelement3i_bufferoffset = 0;
8637                         rsurface.batchelement3s = NULL;
8638                         rsurface.batchelement3s_indexbuffer = NULL;
8639                         rsurface.batchelement3s_bufferoffset = 0;
8640                         if (endvertex <= 65536)
8641                         {
8642                                 // make a 16bit (unsigned short) index array if possible
8643                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8644                                 for (i = 0;i < numtriangles*3;i++)
8645                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8646                         }
8647                 }
8648                 return;
8649         }
8650
8651         // something needs software processing, do it for real...
8652         // we only directly handle separate array data in this case and then
8653         // generate interleaved data if needed...
8654         rsurface.batchgeneratedvertex = true;
8655
8656         // now copy the vertex data into a combined array and make an index array
8657         // (this is what Quake3 does all the time)
8658         //if (gaps || rsurface.batchfirstvertex)
8659         {
8660                 rsurface.batchvertex3fbuffer = NULL;
8661                 rsurface.batchvertexmesh = NULL;
8662                 rsurface.batchvertexmeshbuffer = NULL;
8663                 rsurface.batchvertex3f = NULL;
8664                 rsurface.batchvertex3f_vertexbuffer = NULL;
8665                 rsurface.batchvertex3f_bufferoffset = 0;
8666                 rsurface.batchsvector3f = NULL;
8667                 rsurface.batchsvector3f_vertexbuffer = NULL;
8668                 rsurface.batchsvector3f_bufferoffset = 0;
8669                 rsurface.batchtvector3f = NULL;
8670                 rsurface.batchtvector3f_vertexbuffer = NULL;
8671                 rsurface.batchtvector3f_bufferoffset = 0;
8672                 rsurface.batchnormal3f = NULL;
8673                 rsurface.batchnormal3f_vertexbuffer = NULL;
8674                 rsurface.batchnormal3f_bufferoffset = 0;
8675                 rsurface.batchlightmapcolor4f = NULL;
8676                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8677                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8678                 rsurface.batchtexcoordtexture2f = NULL;
8679                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8680                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8681                 rsurface.batchtexcoordlightmap2f = NULL;
8682                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8683                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8684                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8685                 rsurface.batchelement3i_indexbuffer = NULL;
8686                 rsurface.batchelement3i_bufferoffset = 0;
8687                 rsurface.batchelement3s = NULL;
8688                 rsurface.batchelement3s_indexbuffer = NULL;
8689                 rsurface.batchelement3s_bufferoffset = 0;
8690                 // we'll only be setting up certain arrays as needed
8691                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8692                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8693                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8694                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8695                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8696                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8697                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8698                 {
8699                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8700                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8701                 }
8702                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8703                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8704                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8705                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8706                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8707                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8708                 numvertices = 0;
8709                 numtriangles = 0;
8710                 for (i = 0;i < texturenumsurfaces;i++)
8711                 {
8712                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8713                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8714                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8715                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8716                         // copy only the data requested
8717                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8718                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8719                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8720                         {
8721                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8722                                 {
8723                                         if (rsurface.batchvertex3f)
8724                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8725                                         else
8726                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8727                                 }
8728                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8729                                 {
8730                                         if (rsurface.modelnormal3f)
8731                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8732                                         else
8733                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8734                                 }
8735                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8736                                 {
8737                                         if (rsurface.modelsvector3f)
8738                                         {
8739                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8740                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8741                                         }
8742                                         else
8743                                         {
8744                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8745                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8746                                         }
8747                                 }
8748                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8749                                 {
8750                                         if (rsurface.modellightmapcolor4f)
8751                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8752                                         else
8753                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8754                                 }
8755                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8756                                 {
8757                                         if (rsurface.modeltexcoordtexture2f)
8758                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8759                                         else
8760                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8761                                 }
8762                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8763                                 {
8764                                         if (rsurface.modeltexcoordlightmap2f)
8765                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8766                                         else
8767                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8768                                 }
8769                         }
8770                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8771                         numvertices += surfacenumvertices;
8772                         numtriangles += surfacenumtriangles;
8773                 }
8774
8775                 // generate a 16bit index array as well if possible
8776                 // (in general, dynamic batches fit)
8777                 if (numvertices <= 65536)
8778                 {
8779                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8780                         for (i = 0;i < numtriangles*3;i++)
8781                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8782                 }
8783
8784                 // since we've copied everything, the batch now starts at 0
8785                 rsurface.batchfirstvertex = 0;
8786                 rsurface.batchnumvertices = batchnumvertices;
8787                 rsurface.batchfirsttriangle = 0;
8788                 rsurface.batchnumtriangles = batchnumtriangles;
8789         }
8790
8791         // q1bsp surfaces rendered in vertex color mode have to have colors
8792         // calculated based on lightstyles
8793         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8794         {
8795                 // generate color arrays for the surfaces in this list
8796                 int c[4];
8797                 int scale;
8798                 int size3;
8799                 const int *offsets;
8800                 const unsigned char *lm;
8801                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8802                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8803                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8804                 numvertices = 0;
8805                 for (i = 0;i < texturenumsurfaces;i++)
8806                 {
8807                         surface = texturesurfacelist[i];
8808                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8809                         surfacenumvertices = surface->num_vertices;
8810                         if (surface->lightmapinfo->samples)
8811                         {
8812                                 for (j = 0;j < surfacenumvertices;j++)
8813                                 {
8814                                         lm = surface->lightmapinfo->samples + offsets[j];
8815                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8816                                         VectorScale(lm, scale, c);
8817                                         if (surface->lightmapinfo->styles[1] != 255)
8818                                         {
8819                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8820                                                 lm += size3;
8821                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8822                                                 VectorMA(c, scale, lm, c);
8823                                                 if (surface->lightmapinfo->styles[2] != 255)
8824                                                 {
8825                                                         lm += size3;
8826                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8827                                                         VectorMA(c, scale, lm, c);
8828                                                         if (surface->lightmapinfo->styles[3] != 255)
8829                                                         {
8830                                                                 lm += size3;
8831                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8832                                                                 VectorMA(c, scale, lm, c);
8833                                                         }
8834                                                 }
8835                                         }
8836                                         c[0] >>= 7;
8837                                         c[1] >>= 7;
8838                                         c[2] >>= 7;
8839                                         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);
8840                                         numvertices++;
8841                                 }
8842                         }
8843                         else
8844                         {
8845                                 for (j = 0;j < surfacenumvertices;j++)
8846                                 {
8847                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8848                                         numvertices++;
8849                                 }
8850                         }
8851                 }
8852         }
8853
8854         // if vertices are deformed (sprite flares and things in maps, possibly
8855         // water waves, bulges and other deformations), modify the copied vertices
8856         // in place
8857         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8858         {
8859                 switch (deform->deform)
8860                 {
8861                 default:
8862                 case Q3DEFORM_PROJECTIONSHADOW:
8863                 case Q3DEFORM_TEXT0:
8864                 case Q3DEFORM_TEXT1:
8865                 case Q3DEFORM_TEXT2:
8866                 case Q3DEFORM_TEXT3:
8867                 case Q3DEFORM_TEXT4:
8868                 case Q3DEFORM_TEXT5:
8869                 case Q3DEFORM_TEXT6:
8870                 case Q3DEFORM_TEXT7:
8871                 case Q3DEFORM_NONE:
8872                         break;
8873                 case Q3DEFORM_AUTOSPRITE:
8874                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8875                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8876                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8877                         VectorNormalize(newforward);
8878                         VectorNormalize(newright);
8879                         VectorNormalize(newup);
8880 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8881 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8882 //                      rsurface.batchvertex3f_bufferoffset = 0;
8883 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8884 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8885 //                      rsurface.batchsvector3f_bufferoffset = 0;
8886 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8887 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8888 //                      rsurface.batchtvector3f_bufferoffset = 0;
8889 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8890 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8891 //                      rsurface.batchnormal3f_bufferoffset = 0;
8892                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8893                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8894                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8895                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8896                                 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);
8897                         // a single autosprite surface can contain multiple sprites...
8898                         for (j = 0;j < batchnumvertices - 3;j += 4)
8899                         {
8900                                 VectorClear(center);
8901                                 for (i = 0;i < 4;i++)
8902                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8903                                 VectorScale(center, 0.25f, center);
8904                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8905                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8906                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8907                                 for (i = 0;i < 4;i++)
8908                                 {
8909                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8910                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8911                                 }
8912                         }
8913                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8914                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8915                         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);
8916                         break;
8917                 case Q3DEFORM_AUTOSPRITE2:
8918                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8919                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8920                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8921                         VectorNormalize(newforward);
8922                         VectorNormalize(newright);
8923                         VectorNormalize(newup);
8924 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8925 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8926 //                      rsurface.batchvertex3f_bufferoffset = 0;
8927                         {
8928                                 const float *v1, *v2;
8929                                 vec3_t start, end;
8930                                 float f, l;
8931                                 struct
8932                                 {
8933                                         float length2;
8934                                         const float *v1;
8935                                         const float *v2;
8936                                 }
8937                                 shortest[2];
8938                                 memset(shortest, 0, sizeof(shortest));
8939                                 // a single autosprite surface can contain multiple sprites...
8940                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8941                                 {
8942                                         VectorClear(center);
8943                                         for (i = 0;i < 4;i++)
8944                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8945                                         VectorScale(center, 0.25f, center);
8946                                         // find the two shortest edges, then use them to define the
8947                                         // axis vectors for rotating around the central axis
8948                                         for (i = 0;i < 6;i++)
8949                                         {
8950                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8951                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8952                                                 l = VectorDistance2(v1, v2);
8953                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8954                                                 if (v1[2] != v2[2])
8955                                                         l += (1.0f / 1024.0f);
8956                                                 if (shortest[0].length2 > l || i == 0)
8957                                                 {
8958                                                         shortest[1] = shortest[0];
8959                                                         shortest[0].length2 = l;
8960                                                         shortest[0].v1 = v1;
8961                                                         shortest[0].v2 = v2;
8962                                                 }
8963                                                 else if (shortest[1].length2 > l || i == 1)
8964                                                 {
8965                                                         shortest[1].length2 = l;
8966                                                         shortest[1].v1 = v1;
8967                                                         shortest[1].v2 = v2;
8968                                                 }
8969                                         }
8970                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8971                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8972                                         // this calculates the right vector from the shortest edge
8973                                         // and the up vector from the edge midpoints
8974                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8975                                         VectorNormalize(right);
8976                                         VectorSubtract(end, start, up);
8977                                         VectorNormalize(up);
8978                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8979                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8980                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8981                                         VectorNegate(forward, forward);
8982                                         VectorReflect(forward, 0, up, forward);
8983                                         VectorNormalize(forward);
8984                                         CrossProduct(up, forward, newright);
8985                                         VectorNormalize(newright);
8986                                         // rotate the quad around the up axis vector, this is made
8987                                         // especially easy by the fact we know the quad is flat,
8988                                         // so we only have to subtract the center position and
8989                                         // measure distance along the right vector, and then
8990                                         // multiply that by the newright vector and add back the
8991                                         // center position
8992                                         // we also need to subtract the old position to undo the
8993                                         // displacement from the center, which we do with a
8994                                         // DotProduct, the subtraction/addition of center is also
8995                                         // optimized into DotProducts here
8996                                         l = DotProduct(right, center);
8997                                         for (i = 0;i < 4;i++)
8998                                         {
8999                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9000                                                 f = DotProduct(right, v1) - l;
9001                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9002                                         }
9003                                 }
9004                         }
9005                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9006                         {
9007 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9008 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9009 //                              rsurface.batchnormal3f_bufferoffset = 0;
9010                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9011                         }
9012                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9013                         {
9014 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9015 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9016 //                              rsurface.batchsvector3f_bufferoffset = 0;
9017 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9018 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9019 //                              rsurface.batchtvector3f_bufferoffset = 0;
9020                                 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);
9021                         }
9022                         break;
9023                 case Q3DEFORM_NORMAL:
9024                         // deform the normals to make reflections wavey
9025                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9026                         rsurface.batchnormal3f_vertexbuffer = NULL;
9027                         rsurface.batchnormal3f_bufferoffset = 0;
9028                         for (j = 0;j < batchnumvertices;j++)
9029                         {
9030                                 float vertex[3];
9031                                 float *normal = rsurface.batchnormal3f + 3*j;
9032                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9033                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9034                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9035                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9036                                 VectorNormalize(normal);
9037                         }
9038                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9039                         {
9040 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9041 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9042 //                              rsurface.batchsvector3f_bufferoffset = 0;
9043 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9044 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9045 //                              rsurface.batchtvector3f_bufferoffset = 0;
9046                                 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);
9047                         }
9048                         break;
9049                 case Q3DEFORM_WAVE:
9050                         // deform vertex array to make wavey water and flags and such
9051                         waveparms[0] = deform->waveparms[0];
9052                         waveparms[1] = deform->waveparms[1];
9053                         waveparms[2] = deform->waveparms[2];
9054                         waveparms[3] = deform->waveparms[3];
9055                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9056                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9057                         // this is how a divisor of vertex influence on deformation
9058                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9059                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9060 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9061 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9062 //                      rsurface.batchvertex3f_bufferoffset = 0;
9063 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9064 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9065 //                      rsurface.batchnormal3f_bufferoffset = 0;
9066                         for (j = 0;j < batchnumvertices;j++)
9067                         {
9068                                 // if the wavefunc depends on time, evaluate it per-vertex
9069                                 if (waveparms[3])
9070                                 {
9071                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9072                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9073                                 }
9074                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9075                         }
9076                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9077                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9078                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9079                         {
9080 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9081 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9082 //                              rsurface.batchsvector3f_bufferoffset = 0;
9083 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9084 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9085 //                              rsurface.batchtvector3f_bufferoffset = 0;
9086                                 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);
9087                         }
9088                         break;
9089                 case Q3DEFORM_BULGE:
9090                         // deform vertex array to make the surface have moving bulges
9091 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9092 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9093 //                      rsurface.batchvertex3f_bufferoffset = 0;
9094 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9095 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9096 //                      rsurface.batchnormal3f_bufferoffset = 0;
9097                         for (j = 0;j < batchnumvertices;j++)
9098                         {
9099                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9100                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9101                         }
9102                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9103                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9104                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9105                         {
9106 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9107 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9108 //                              rsurface.batchsvector3f_bufferoffset = 0;
9109 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9110 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9111 //                              rsurface.batchtvector3f_bufferoffset = 0;
9112                                 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);
9113                         }
9114                         break;
9115                 case Q3DEFORM_MOVE:
9116                         // deform vertex array
9117                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9118                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9119                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9120                         VectorScale(deform->parms, scale, waveparms);
9121 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9122 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9123 //                      rsurface.batchvertex3f_bufferoffset = 0;
9124                         for (j = 0;j < batchnumvertices;j++)
9125                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9126                         break;
9127                 }
9128         }
9129
9130         // generate texcoords based on the chosen texcoord source
9131         switch(rsurface.texture->tcgen.tcgen)
9132         {
9133         default:
9134         case Q3TCGEN_TEXTURE:
9135                 break;
9136         case Q3TCGEN_LIGHTMAP:
9137 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9138 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9139 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9140                 if (rsurface.batchtexcoordlightmap2f)
9141                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9142                 break;
9143         case Q3TCGEN_VECTOR:
9144 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9145 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9146 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9147                 for (j = 0;j < batchnumvertices;j++)
9148                 {
9149                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9150                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9151                 }
9152                 break;
9153         case Q3TCGEN_ENVIRONMENT:
9154                 // make environment reflections using a spheremap
9155                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9156                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9157                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9158                 for (j = 0;j < batchnumvertices;j++)
9159                 {
9160                         // identical to Q3A's method, but executed in worldspace so
9161                         // carried models can be shiny too
9162
9163                         float viewer[3], d, reflected[3], worldreflected[3];
9164
9165                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9166                         // VectorNormalize(viewer);
9167
9168                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9169
9170                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9171                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9172                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9173                         // note: this is proportinal to viewer, so we can normalize later
9174
9175                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9176                         VectorNormalize(worldreflected);
9177
9178                         // note: this sphere map only uses world x and z!
9179                         // so positive and negative y will LOOK THE SAME.
9180                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9181                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9182                 }
9183                 break;
9184         }
9185         // the only tcmod that needs software vertex processing is turbulent, so
9186         // check for it here and apply the changes if needed
9187         // and we only support that as the first one
9188         // (handling a mixture of turbulent and other tcmods would be problematic
9189         //  without punting it entirely to a software path)
9190         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9191         {
9192                 amplitude = rsurface.texture->tcmods[0].parms[1];
9193                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9194 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9195 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9196 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9197                 for (j = 0;j < batchnumvertices;j++)
9198                 {
9199                         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);
9200                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9201                 }
9202         }
9203
9204         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9205         {
9206                 // convert the modified arrays to vertex structs
9207 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9208 //              rsurface.batchvertexmeshbuffer = NULL;
9209                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9210                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9211                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9212                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9213                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9214                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9215                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9216                 {
9217                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9218                         {
9219                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9220                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9221                         }
9222                 }
9223                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9224                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9225                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9226                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9227                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9228                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9229                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9230                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9231                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9232         }
9233 }
9234
9235 void RSurf_DrawBatch(void)
9236 {
9237         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9238         // through the pipeline, killing it earlier in the pipeline would have
9239         // per-surface overhead rather than per-batch overhead, so it's best to
9240         // reject it here, before it hits glDraw.
9241         if (rsurface.batchnumtriangles == 0)
9242                 return;
9243 #if 0
9244         // batch debugging code
9245         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9246         {
9247                 int i;
9248                 int j;
9249                 int c;
9250                 const int *e;
9251                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9252                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9253                 {
9254                         c = e[i];
9255                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9256                         {
9257                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9258                                 {
9259                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9260                                                 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);
9261                                         break;
9262                                 }
9263                         }
9264                 }
9265         }
9266 #endif
9267         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);
9268 }
9269
9270 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9271 {
9272         // pick the closest matching water plane
9273         int planeindex, vertexindex, bestplaneindex = -1;
9274         float d, bestd;
9275         vec3_t vert;
9276         const float *v;
9277         r_waterstate_waterplane_t *p;
9278         qboolean prepared = false;
9279         bestd = 0;
9280         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9281         {
9282                 if(p->camera_entity != rsurface.texture->camera_entity)
9283                         continue;
9284                 d = 0;
9285                 if(!prepared)
9286                 {
9287                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9288                         prepared = true;
9289                         if(rsurface.batchnumvertices == 0)
9290                                 break;
9291                 }
9292                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9293                 {
9294                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9295                         d += fabs(PlaneDiff(vert, &p->plane));
9296                 }
9297                 if (bestd > d || bestplaneindex < 0)
9298                 {
9299                         bestd = d;
9300                         bestplaneindex = planeindex;
9301                 }
9302         }
9303         return bestplaneindex;
9304         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9305         // this situation though, as it might be better to render single larger
9306         // batches with useless stuff (backface culled for example) than to
9307         // render multiple smaller batches
9308 }
9309
9310 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9311 {
9312         int i;
9313         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9314         rsurface.passcolor4f_vertexbuffer = 0;
9315         rsurface.passcolor4f_bufferoffset = 0;
9316         for (i = 0;i < rsurface.batchnumvertices;i++)
9317                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9318 }
9319
9320 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9321 {
9322         int i;
9323         float f;
9324         const float *v;
9325         const float *c;
9326         float *c2;
9327         if (rsurface.passcolor4f)
9328         {
9329                 // generate color arrays
9330                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9331                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9332                 rsurface.passcolor4f_vertexbuffer = 0;
9333                 rsurface.passcolor4f_bufferoffset = 0;
9334                 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)
9335                 {
9336                         f = RSurf_FogVertex(v);
9337                         c2[0] = c[0] * f;
9338                         c2[1] = c[1] * f;
9339                         c2[2] = c[2] * f;
9340                         c2[3] = c[3];
9341                 }
9342         }
9343         else
9344         {
9345                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9346                 rsurface.passcolor4f_vertexbuffer = 0;
9347                 rsurface.passcolor4f_bufferoffset = 0;
9348                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9349                 {
9350                         f = RSurf_FogVertex(v);
9351                         c2[0] = f;
9352                         c2[1] = f;
9353                         c2[2] = f;
9354                         c2[3] = 1;
9355                 }
9356         }
9357 }
9358
9359 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9360 {
9361         int i;
9362         float f;
9363         const float *v;
9364         const float *c;
9365         float *c2;
9366         if (!rsurface.passcolor4f)
9367                 return;
9368         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9369         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9370         rsurface.passcolor4f_vertexbuffer = 0;
9371         rsurface.passcolor4f_bufferoffset = 0;
9372         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)
9373         {
9374                 f = RSurf_FogVertex(v);
9375                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9376                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9377                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9378                 c2[3] = c[3];
9379         }
9380 }
9381
9382 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9383 {
9384         int i;
9385         const float *c;
9386         float *c2;
9387         if (!rsurface.passcolor4f)
9388                 return;
9389         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9390         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9391         rsurface.passcolor4f_vertexbuffer = 0;
9392         rsurface.passcolor4f_bufferoffset = 0;
9393         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9394         {
9395                 c2[0] = c[0] * r;
9396                 c2[1] = c[1] * g;
9397                 c2[2] = c[2] * b;
9398                 c2[3] = c[3] * a;
9399         }
9400 }
9401
9402 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9403 {
9404         int i;
9405         const float *c;
9406         float *c2;
9407         if (!rsurface.passcolor4f)
9408                 return;
9409         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9410         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9411         rsurface.passcolor4f_vertexbuffer = 0;
9412         rsurface.passcolor4f_bufferoffset = 0;
9413         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9414         {
9415                 c2[0] = c[0] + r_refdef.scene.ambient;
9416                 c2[1] = c[1] + r_refdef.scene.ambient;
9417                 c2[2] = c[2] + r_refdef.scene.ambient;
9418                 c2[3] = c[3];
9419         }
9420 }
9421
9422 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9423 {
9424         // TODO: optimize
9425         rsurface.passcolor4f = NULL;
9426         rsurface.passcolor4f_vertexbuffer = 0;
9427         rsurface.passcolor4f_bufferoffset = 0;
9428         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9429         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9430         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9431         GL_Color(r, g, b, a);
9432         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9433         RSurf_DrawBatch();
9434 }
9435
9436 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9437 {
9438         // TODO: optimize applyfog && applycolor case
9439         // just apply fog if necessary, and tint the fog color array if necessary
9440         rsurface.passcolor4f = NULL;
9441         rsurface.passcolor4f_vertexbuffer = 0;
9442         rsurface.passcolor4f_bufferoffset = 0;
9443         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9444         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9445         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9446         GL_Color(r, g, b, a);
9447         RSurf_DrawBatch();
9448 }
9449
9450 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9451 {
9452         // TODO: optimize
9453         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9454         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9455         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9456         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9457         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9458         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9459         GL_Color(r, g, b, a);
9460         RSurf_DrawBatch();
9461 }
9462
9463 static void RSurf_DrawBatch_GL11_ClampColor(void)
9464 {
9465         int i;
9466         const float *c1;
9467         float *c2;
9468         if (!rsurface.passcolor4f)
9469                 return;
9470         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9471         {
9472                 c2[0] = bound(0.0f, c1[0], 1.0f);
9473                 c2[1] = bound(0.0f, c1[1], 1.0f);
9474                 c2[2] = bound(0.0f, c1[2], 1.0f);
9475                 c2[3] = bound(0.0f, c1[3], 1.0f);
9476         }
9477 }
9478
9479 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9480 {
9481         int i;
9482         float f;
9483         const float *v;
9484         const float *n;
9485         float *c;
9486         //vec3_t eyedir;
9487
9488         // fake shading
9489         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9490         rsurface.passcolor4f_vertexbuffer = 0;
9491         rsurface.passcolor4f_bufferoffset = 0;
9492         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)
9493         {
9494                 f = -DotProduct(r_refdef.view.forward, n);
9495                 f = max(0, f);
9496                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9497                 f *= r_refdef.lightmapintensity;
9498                 Vector4Set(c, f, f, f, 1);
9499         }
9500 }
9501
9502 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9503 {
9504         RSurf_DrawBatch_GL11_ApplyFakeLight();
9505         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9506         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9507         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9508         GL_Color(r, g, b, a);
9509         RSurf_DrawBatch();
9510 }
9511
9512 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9513 {
9514         int i;
9515         float f;
9516         float alpha;
9517         const float *v;
9518         const float *n;
9519         float *c;
9520         vec3_t ambientcolor;
9521         vec3_t diffusecolor;
9522         vec3_t lightdir;
9523         // TODO: optimize
9524         // model lighting
9525         VectorCopy(rsurface.modellight_lightdir, lightdir);
9526         f = 0.5f * r_refdef.lightmapintensity;
9527         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9528         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9529         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9530         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9531         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9532         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9533         alpha = *a;
9534         if (VectorLength2(diffusecolor) > 0)
9535         {
9536                 // q3-style directional shading
9537                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9538                 rsurface.passcolor4f_vertexbuffer = 0;
9539                 rsurface.passcolor4f_bufferoffset = 0;
9540                 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)
9541                 {
9542                         if ((f = DotProduct(n, lightdir)) > 0)
9543                                 VectorMA(ambientcolor, f, diffusecolor, c);
9544                         else
9545                                 VectorCopy(ambientcolor, c);
9546                         c[3] = alpha;
9547                 }
9548                 *r = 1;
9549                 *g = 1;
9550                 *b = 1;
9551                 *a = 1;
9552                 *applycolor = false;
9553         }
9554         else
9555         {
9556                 *r = ambientcolor[0];
9557                 *g = ambientcolor[1];
9558                 *b = ambientcolor[2];
9559                 rsurface.passcolor4f = NULL;
9560                 rsurface.passcolor4f_vertexbuffer = 0;
9561                 rsurface.passcolor4f_bufferoffset = 0;
9562         }
9563 }
9564
9565 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9566 {
9567         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9568         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9569         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9570         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9571         GL_Color(r, g, b, a);
9572         RSurf_DrawBatch();
9573 }
9574
9575 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9576 {
9577         int i;
9578         float f;
9579         const float *v;
9580         float *c;
9581
9582         // fake shading
9583         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9584         rsurface.passcolor4f_vertexbuffer = 0;
9585         rsurface.passcolor4f_bufferoffset = 0;
9586
9587         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9588         {
9589                 f = 1 - RSurf_FogVertex(v);
9590                 c[0] = r;
9591                 c[1] = g;
9592                 c[2] = b;
9593                 c[3] = f * a;
9594         }
9595 }
9596
9597 void RSurf_SetupDepthAndCulling(void)
9598 {
9599         // submodels are biased to avoid z-fighting with world surfaces that they
9600         // may be exactly overlapping (avoids z-fighting artifacts on certain
9601         // doors and things in Quake maps)
9602         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9603         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9604         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9605         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9606 }
9607
9608 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9609 {
9610         // transparent sky would be ridiculous
9611         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9612                 return;
9613         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9614         skyrenderlater = true;
9615         RSurf_SetupDepthAndCulling();
9616         GL_DepthMask(true);
9617         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9618         // skymasking on them, and Quake3 never did sky masking (unlike
9619         // software Quake and software Quake2), so disable the sky masking
9620         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9621         // and skymasking also looks very bad when noclipping outside the
9622         // level, so don't use it then either.
9623         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9624         {
9625                 R_Mesh_ResetTextureState();
9626                 if (skyrendermasked)
9627                 {
9628                         R_SetupShader_DepthOrShadow(false);
9629                         // depth-only (masking)
9630                         GL_ColorMask(0,0,0,0);
9631                         // just to make sure that braindead drivers don't draw
9632                         // anything despite that colormask...
9633                         GL_BlendFunc(GL_ZERO, GL_ONE);
9634                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9635                         if (rsurface.batchvertex3fbuffer)
9636                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9637                         else
9638                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9639                 }
9640                 else
9641                 {
9642                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9643                         // fog sky
9644                         GL_BlendFunc(GL_ONE, GL_ZERO);
9645                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9646                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9647                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9648                 }
9649                 RSurf_DrawBatch();
9650                 if (skyrendermasked)
9651                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9652         }
9653         R_Mesh_ResetTextureState();
9654         GL_Color(1, 1, 1, 1);
9655 }
9656
9657 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9658 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9659 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9660 {
9661         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9662                 return;
9663         if (prepass)
9664         {
9665                 // render screenspace normalmap to texture
9666                 GL_DepthMask(true);
9667                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9668                 RSurf_DrawBatch();
9669         }
9670
9671         // bind lightmap texture
9672
9673         // water/refraction/reflection/camera surfaces have to be handled specially
9674         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9675         {
9676                 int start, end, startplaneindex;
9677                 for (start = 0;start < texturenumsurfaces;start = end)
9678                 {
9679                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9680                         if(startplaneindex < 0)
9681                         {
9682                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9683                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9684                                 end = start + 1;
9685                                 continue;
9686                         }
9687                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9688                                 ;
9689                         // now that we have a batch using the same planeindex, render it
9690                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9691                         {
9692                                 // render water or distortion background
9693                                 GL_DepthMask(true);
9694                                 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);
9695                                 RSurf_DrawBatch();
9696                                 // blend surface on top
9697                                 GL_DepthMask(false);
9698                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9699                                 RSurf_DrawBatch();
9700                         }
9701                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9702                         {
9703                                 // render surface with reflection texture as input
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, end-start, texturesurfacelist + start, (void *)(r_waterstate.waterplanes + startplaneindex), false);
9706                                 RSurf_DrawBatch();
9707                         }
9708                 }
9709                 return;
9710         }
9711
9712         // render surface batch normally
9713         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9714         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);
9715         RSurf_DrawBatch();
9716 }
9717
9718 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9719 {
9720         // OpenGL 1.3 path - anything not completely ancient
9721         qboolean applycolor;
9722         qboolean applyfog;
9723         int layerindex;
9724         const texturelayer_t *layer;
9725         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);
9726         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9727
9728         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9729         {
9730                 vec4_t layercolor;
9731                 int layertexrgbscale;
9732                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9733                 {
9734                         if (layerindex == 0)
9735                                 GL_AlphaTest(true);
9736                         else
9737                         {
9738                                 GL_AlphaTest(false);
9739                                 GL_DepthFunc(GL_EQUAL);
9740                         }
9741                 }
9742                 GL_DepthMask(layer->depthmask && writedepth);
9743                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9744                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9745                 {
9746                         layertexrgbscale = 4;
9747                         VectorScale(layer->color, 0.25f, layercolor);
9748                 }
9749                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9750                 {
9751                         layertexrgbscale = 2;
9752                         VectorScale(layer->color, 0.5f, layercolor);
9753                 }
9754                 else
9755                 {
9756                         layertexrgbscale = 1;
9757                         VectorScale(layer->color, 1.0f, layercolor);
9758                 }
9759                 layercolor[3] = layer->color[3];
9760                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9761                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9762                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9763                 switch (layer->type)
9764                 {
9765                 case TEXTURELAYERTYPE_LITTEXTURE:
9766                         // single-pass lightmapped texture with 2x rgbscale
9767                         R_Mesh_TexBind(0, r_texture_white);
9768                         R_Mesh_TexMatrix(0, NULL);
9769                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9770                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9771                         R_Mesh_TexBind(1, layer->texture);
9772                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9773                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9774                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9775                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9776                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9777                         else if (FAKELIGHT_ENABLED)
9778                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9779                         else if (rsurface.uselightmaptexture)
9780                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9781                         else
9782                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9783                         break;
9784                 case TEXTURELAYERTYPE_TEXTURE:
9785                         // singletexture unlit texture with transparency support
9786                         R_Mesh_TexBind(0, layer->texture);
9787                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9788                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9789                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9790                         R_Mesh_TexBind(1, 0);
9791                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9792                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9793                         break;
9794                 case TEXTURELAYERTYPE_FOG:
9795                         // singletexture fogging
9796                         if (layer->texture)
9797                         {
9798                                 R_Mesh_TexBind(0, layer->texture);
9799                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9800                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9801                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9802                         }
9803                         else
9804                         {
9805                                 R_Mesh_TexBind(0, 0);
9806                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9807                         }
9808                         R_Mesh_TexBind(1, 0);
9809                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9810                         // generate a color array for the fog pass
9811                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9812                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9813                         RSurf_DrawBatch();
9814                         break;
9815                 default:
9816                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9817                 }
9818         }
9819         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9820         {
9821                 GL_DepthFunc(GL_LEQUAL);
9822                 GL_AlphaTest(false);
9823         }
9824 }
9825
9826 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9827 {
9828         // OpenGL 1.1 - crusty old voodoo path
9829         qboolean applyfog;
9830         int layerindex;
9831         const texturelayer_t *layer;
9832         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);
9833         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9834
9835         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9836         {
9837                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9838                 {
9839                         if (layerindex == 0)
9840                                 GL_AlphaTest(true);
9841                         else
9842                         {
9843                                 GL_AlphaTest(false);
9844                                 GL_DepthFunc(GL_EQUAL);
9845                         }
9846                 }
9847                 GL_DepthMask(layer->depthmask && writedepth);
9848                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9849                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9850                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9851                 switch (layer->type)
9852                 {
9853                 case TEXTURELAYERTYPE_LITTEXTURE:
9854                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9855                         {
9856                                 // two-pass lit texture with 2x rgbscale
9857                                 // first the lightmap pass
9858                                 R_Mesh_TexBind(0, r_texture_white);
9859                                 R_Mesh_TexMatrix(0, NULL);
9860                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9861                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9862                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9863                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9864                                 else if (FAKELIGHT_ENABLED)
9865                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9866                                 else if (rsurface.uselightmaptexture)
9867                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9868                                 else
9869                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9870                                 // then apply the texture to it
9871                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
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                                 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);
9877                         }
9878                         else
9879                         {
9880                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9881                                 R_Mesh_TexBind(0, layer->texture);
9882                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9883                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9884                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9885                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9886                                         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);
9887                                 else
9888                                         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);
9889                         }
9890                         break;
9891                 case TEXTURELAYERTYPE_TEXTURE:
9892                         // singletexture unlit texture with transparency support
9893                         R_Mesh_TexBind(0, layer->texture);
9894                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9895                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9896                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9897                         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);
9898                         break;
9899                 case TEXTURELAYERTYPE_FOG:
9900                         // singletexture fogging
9901                         if (layer->texture)
9902                         {
9903                                 R_Mesh_TexBind(0, layer->texture);
9904                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9905                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9906                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9907                         }
9908                         else
9909                         {
9910                                 R_Mesh_TexBind(0, 0);
9911                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9912                         }
9913                         // generate a color array for the fog pass
9914                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9915                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9916                         RSurf_DrawBatch();
9917                         break;
9918                 default:
9919                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9920                 }
9921         }
9922         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9923         {
9924                 GL_DepthFunc(GL_LEQUAL);
9925                 GL_AlphaTest(false);
9926         }
9927 }
9928
9929 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9930 {
9931         int vi;
9932         int j;
9933         r_vertexgeneric_t *batchvertex;
9934         float c[4];
9935
9936 //      R_Mesh_ResetTextureState();
9937         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9938
9939         if(rsurface.texture && rsurface.texture->currentskinframe)
9940         {
9941                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9942                 c[3] *= rsurface.texture->currentalpha;
9943         }
9944         else
9945         {
9946                 c[0] = 1;
9947                 c[1] = 0;
9948                 c[2] = 1;
9949                 c[3] = 1;
9950         }
9951
9952         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9953         {
9954                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9955                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9956                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9957         }
9958
9959         // brighten it up (as texture value 127 means "unlit")
9960         c[0] *= 2 * r_refdef.view.colorscale;
9961         c[1] *= 2 * r_refdef.view.colorscale;
9962         c[2] *= 2 * r_refdef.view.colorscale;
9963
9964         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9965                 c[3] *= r_wateralpha.value;
9966
9967         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9968         {
9969                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9970                 GL_DepthMask(false);
9971         }
9972         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9973         {
9974                 GL_BlendFunc(GL_ONE, GL_ONE);
9975                 GL_DepthMask(false);
9976         }
9977         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9978         {
9979                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9980                 GL_DepthMask(false);
9981         }
9982         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9983         {
9984                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9985                 GL_DepthMask(false);
9986         }
9987         else
9988         {
9989                 GL_BlendFunc(GL_ONE, GL_ZERO);
9990                 GL_DepthMask(writedepth);
9991         }
9992
9993         if (r_showsurfaces.integer == 3)
9994         {
9995                 rsurface.passcolor4f = NULL;
9996
9997                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9998                 {
9999                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10000
10001                         rsurface.passcolor4f = NULL;
10002                         rsurface.passcolor4f_vertexbuffer = 0;
10003                         rsurface.passcolor4f_bufferoffset = 0;
10004                 }
10005                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10006                 {
10007                         qboolean applycolor = true;
10008                         float one = 1.0;
10009
10010                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10011
10012                         r_refdef.lightmapintensity = 1;
10013                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10014                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10015                 }
10016                 else if (FAKELIGHT_ENABLED)
10017                 {
10018                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10019
10020                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10021                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10022                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10023                 }
10024                 else
10025                 {
10026                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10027
10028                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10029                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10030                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10031                 }
10032
10033                 if(!rsurface.passcolor4f)
10034                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10035
10036                 RSurf_DrawBatch_GL11_ApplyAmbient();
10037                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10038                 if(r_refdef.fogenabled)
10039                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10040                 RSurf_DrawBatch_GL11_ClampColor();
10041
10042                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10043                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10044                 RSurf_DrawBatch();
10045         }
10046         else if (!r_refdef.view.showdebug)
10047         {
10048                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10049                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10050                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10051                 {
10052                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10053                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10054                 }
10055                 R_Mesh_PrepareVertices_Generic_Unlock();
10056                 RSurf_DrawBatch();
10057         }
10058         else if (r_showsurfaces.integer == 4)
10059         {
10060                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10061                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10062                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10063                 {
10064                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10065                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10066                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10067                 }
10068                 R_Mesh_PrepareVertices_Generic_Unlock();
10069                 RSurf_DrawBatch();
10070         }
10071         else if (r_showsurfaces.integer == 2)
10072         {
10073                 const int *e;
10074                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10075                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10076                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10077                 {
10078                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10079                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10080                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10081                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10082                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10083                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10084                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10085                 }
10086                 R_Mesh_PrepareVertices_Generic_Unlock();
10087                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10088         }
10089         else
10090         {
10091                 int texturesurfaceindex;
10092                 int k;
10093                 const msurface_t *surface;
10094                 float surfacecolor4f[4];
10095                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10096                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10097                 vi = 0;
10098                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10099                 {
10100                         surface = texturesurfacelist[texturesurfaceindex];
10101                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10102                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10103                         for (j = 0;j < surface->num_vertices;j++)
10104                         {
10105                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10106                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10107                                 vi++;
10108                         }
10109                 }
10110                 R_Mesh_PrepareVertices_Generic_Unlock();
10111                 RSurf_DrawBatch();
10112         }
10113 }
10114
10115 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10116 {
10117         CHECKGLERROR
10118         RSurf_SetupDepthAndCulling();
10119         if (r_showsurfaces.integer)
10120         {
10121                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10122                 return;
10123         }
10124         switch (vid.renderpath)
10125         {
10126         case RENDERPATH_GL20:
10127         case RENDERPATH_D3D9:
10128         case RENDERPATH_D3D10:
10129         case RENDERPATH_D3D11:
10130         case RENDERPATH_SOFT:
10131         case RENDERPATH_GLES2:
10132                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10133                 break;
10134         case RENDERPATH_GL13:
10135         case RENDERPATH_GLES1:
10136                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10137                 break;
10138         case RENDERPATH_GL11:
10139                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10140                 break;
10141         }
10142         CHECKGLERROR
10143 }
10144
10145 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10146 {
10147         CHECKGLERROR
10148         RSurf_SetupDepthAndCulling();
10149         if (r_showsurfaces.integer)
10150         {
10151                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10152                 return;
10153         }
10154         switch (vid.renderpath)
10155         {
10156         case RENDERPATH_GL20:
10157         case RENDERPATH_D3D9:
10158         case RENDERPATH_D3D10:
10159         case RENDERPATH_D3D11:
10160         case RENDERPATH_SOFT:
10161         case RENDERPATH_GLES2:
10162                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10163                 break;
10164         case RENDERPATH_GL13:
10165         case RENDERPATH_GLES1:
10166                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10167                 break;
10168         case RENDERPATH_GL11:
10169                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10170                 break;
10171         }
10172         CHECKGLERROR
10173 }
10174
10175 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10176 {
10177         int i, j;
10178         int texturenumsurfaces, endsurface;
10179         texture_t *texture;
10180         const msurface_t *surface;
10181         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10182
10183         // if the model is static it doesn't matter what value we give for
10184         // wantnormals and wanttangents, so this logic uses only rules applicable
10185         // to a model, knowing that they are meaningless otherwise
10186         if (ent == r_refdef.scene.worldentity)
10187                 RSurf_ActiveWorldEntity();
10188         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10189                 RSurf_ActiveModelEntity(ent, false, false, false);
10190         else
10191         {
10192                 switch (vid.renderpath)
10193                 {
10194                 case RENDERPATH_GL20:
10195                 case RENDERPATH_D3D9:
10196                 case RENDERPATH_D3D10:
10197                 case RENDERPATH_D3D11:
10198                 case RENDERPATH_SOFT:
10199                 case RENDERPATH_GLES2:
10200                         RSurf_ActiveModelEntity(ent, true, true, false);
10201                         break;
10202                 case RENDERPATH_GL11:
10203                 case RENDERPATH_GL13:
10204                 case RENDERPATH_GLES1:
10205                         RSurf_ActiveModelEntity(ent, true, false, false);
10206                         break;
10207                 }
10208         }
10209
10210         if (r_transparentdepthmasking.integer)
10211         {
10212                 qboolean setup = false;
10213                 for (i = 0;i < numsurfaces;i = j)
10214                 {
10215                         j = i + 1;
10216                         surface = rsurface.modelsurfaces + surfacelist[i];
10217                         texture = surface->texture;
10218                         rsurface.texture = R_GetCurrentTexture(texture);
10219                         rsurface.lightmaptexture = NULL;
10220                         rsurface.deluxemaptexture = NULL;
10221                         rsurface.uselightmaptexture = false;
10222                         // scan ahead until we find a different texture
10223                         endsurface = min(i + 1024, numsurfaces);
10224                         texturenumsurfaces = 0;
10225                         texturesurfacelist[texturenumsurfaces++] = surface;
10226                         for (;j < endsurface;j++)
10227                         {
10228                                 surface = rsurface.modelsurfaces + surfacelist[j];
10229                                 if (texture != surface->texture)
10230                                         break;
10231                                 texturesurfacelist[texturenumsurfaces++] = surface;
10232                         }
10233                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10234                                 continue;
10235                         // render the range of surfaces as depth
10236                         if (!setup)
10237                         {
10238                                 setup = true;
10239                                 GL_ColorMask(0,0,0,0);
10240                                 GL_Color(1,1,1,1);
10241                                 GL_DepthTest(true);
10242                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10243                                 GL_DepthMask(true);
10244 //                              R_Mesh_ResetTextureState();
10245                                 R_SetupShader_DepthOrShadow(false);
10246                         }
10247                         RSurf_SetupDepthAndCulling();
10248                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10249                         if (rsurface.batchvertex3fbuffer)
10250                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10251                         else
10252                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10253                         RSurf_DrawBatch();
10254                 }
10255                 if (setup)
10256                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10257         }
10258
10259         for (i = 0;i < numsurfaces;i = j)
10260         {
10261                 j = i + 1;
10262                 surface = rsurface.modelsurfaces + surfacelist[i];
10263                 texture = surface->texture;
10264                 rsurface.texture = R_GetCurrentTexture(texture);
10265                 // scan ahead until we find a different texture
10266                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10267                 texturenumsurfaces = 0;
10268                 texturesurfacelist[texturenumsurfaces++] = surface;
10269                 if(FAKELIGHT_ENABLED)
10270                 {
10271                         rsurface.lightmaptexture = NULL;
10272                         rsurface.deluxemaptexture = NULL;
10273                         rsurface.uselightmaptexture = false;
10274                         for (;j < endsurface;j++)
10275                         {
10276                                 surface = rsurface.modelsurfaces + surfacelist[j];
10277                                 if (texture != surface->texture)
10278                                         break;
10279                                 texturesurfacelist[texturenumsurfaces++] = surface;
10280                         }
10281                 }
10282                 else
10283                 {
10284                         rsurface.lightmaptexture = surface->lightmaptexture;
10285                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10286                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10287                         for (;j < endsurface;j++)
10288                         {
10289                                 surface = rsurface.modelsurfaces + surfacelist[j];
10290                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10291                                         break;
10292                                 texturesurfacelist[texturenumsurfaces++] = surface;
10293                         }
10294                 }
10295                 // render the range of surfaces
10296                 if (ent == r_refdef.scene.worldentity)
10297                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10298                 else
10299                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10300         }
10301         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10302 }
10303
10304 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10305 {
10306         // transparent surfaces get pushed off into the transparent queue
10307         int surfacelistindex;
10308         const msurface_t *surface;
10309         vec3_t tempcenter, center;
10310         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10311         {
10312                 surface = texturesurfacelist[surfacelistindex];
10313                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10314                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10315                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10316                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10317                 if (queueentity->transparent_offset) // transparent offset
10318                 {
10319                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10320                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10321                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10322                 }
10323                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10324         }
10325 }
10326
10327 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10328 {
10329         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10330                 return;
10331         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10332                 return;
10333         RSurf_SetupDepthAndCulling();
10334         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10335         if (rsurface.batchvertex3fbuffer)
10336                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10337         else
10338                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10339         RSurf_DrawBatch();
10340 }
10341
10342 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10343 {
10344         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10345         CHECKGLERROR
10346         if (depthonly)
10347                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10348         else if (prepass)
10349         {
10350                 if (!rsurface.texture->currentnumlayers)
10351                         return;
10352                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10353                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10354                 else
10355                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10356         }
10357         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10358                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10359         else if (!rsurface.texture->currentnumlayers)
10360                 return;
10361         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10362         {
10363                 // in the deferred case, transparent surfaces were queued during prepass
10364                 if (!r_shadow_usingdeferredprepass)
10365                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10366         }
10367         else
10368         {
10369                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10370                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10371         }
10372         CHECKGLERROR
10373 }
10374
10375 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10376 {
10377         int i, j;
10378         texture_t *texture;
10379         R_FrameData_SetMark();
10380         // break the surface list down into batches by texture and use of lightmapping
10381         for (i = 0;i < numsurfaces;i = j)
10382         {
10383                 j = i + 1;
10384                 // texture is the base texture pointer, rsurface.texture is the
10385                 // current frame/skin the texture is directing us to use (for example
10386                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10387                 // use skin 1 instead)
10388                 texture = surfacelist[i]->texture;
10389                 rsurface.texture = R_GetCurrentTexture(texture);
10390                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10391                 {
10392                         // if this texture is not the kind we want, skip ahead to the next one
10393                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10394                                 ;
10395                         continue;
10396                 }
10397                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10398                 {
10399                         rsurface.lightmaptexture = NULL;
10400                         rsurface.deluxemaptexture = NULL;
10401                         rsurface.uselightmaptexture = false;
10402                         // simply scan ahead until we find a different texture or lightmap state
10403                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10404                                 ;
10405                 }
10406                 else
10407                 {
10408                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10409                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10410                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10411                         // simply scan ahead until we find a different texture or lightmap state
10412                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10413                                 ;
10414                 }
10415                 // render the range of surfaces
10416                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10417         }
10418         R_FrameData_ReturnToMark();
10419 }
10420
10421 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10422 {
10423         CHECKGLERROR
10424         if (depthonly)
10425                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10426         else if (prepass)
10427         {
10428                 if (!rsurface.texture->currentnumlayers)
10429                         return;
10430                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10431                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10432                 else
10433                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10434         }
10435         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10436                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10437         else if (!rsurface.texture->currentnumlayers)
10438                 return;
10439         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10440         {
10441                 // in the deferred case, transparent surfaces were queued during prepass
10442                 if (!r_shadow_usingdeferredprepass)
10443                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10444         }
10445         else
10446         {
10447                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10448                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10449         }
10450         CHECKGLERROR
10451 }
10452
10453 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10454 {
10455         int i, j;
10456         texture_t *texture;
10457         R_FrameData_SetMark();
10458         // break the surface list down into batches by texture and use of lightmapping
10459         for (i = 0;i < numsurfaces;i = j)
10460         {
10461                 j = i + 1;
10462                 // texture is the base texture pointer, rsurface.texture is the
10463                 // current frame/skin the texture is directing us to use (for example
10464                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10465                 // use skin 1 instead)
10466                 texture = surfacelist[i]->texture;
10467                 rsurface.texture = R_GetCurrentTexture(texture);
10468                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10469                 {
10470                         // if this texture is not the kind we want, skip ahead to the next one
10471                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10472                                 ;
10473                         continue;
10474                 }
10475                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10476                 {
10477                         rsurface.lightmaptexture = NULL;
10478                         rsurface.deluxemaptexture = NULL;
10479                         rsurface.uselightmaptexture = false;
10480                         // simply scan ahead until we find a different texture or lightmap state
10481                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10482                                 ;
10483                 }
10484                 else
10485                 {
10486                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10487                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10488                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10489                         // simply scan ahead until we find a different texture or lightmap state
10490                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10491                                 ;
10492                 }
10493                 // render the range of surfaces
10494                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10495         }
10496         R_FrameData_ReturnToMark();
10497 }
10498
10499 float locboxvertex3f[6*4*3] =
10500 {
10501         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10502         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10503         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10504         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10505         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10506         1,0,0, 0,0,0, 0,1,0, 1,1,0
10507 };
10508
10509 unsigned short locboxelements[6*2*3] =
10510 {
10511          0, 1, 2, 0, 2, 3,
10512          4, 5, 6, 4, 6, 7,
10513          8, 9,10, 8,10,11,
10514         12,13,14, 12,14,15,
10515         16,17,18, 16,18,19,
10516         20,21,22, 20,22,23
10517 };
10518
10519 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10520 {
10521         int i, j;
10522         cl_locnode_t *loc = (cl_locnode_t *)ent;
10523         vec3_t mins, size;
10524         float vertex3f[6*4*3];
10525         CHECKGLERROR
10526         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10527         GL_DepthMask(false);
10528         GL_DepthRange(0, 1);
10529         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10530         GL_DepthTest(true);
10531         GL_CullFace(GL_NONE);
10532         R_EntityMatrix(&identitymatrix);
10533
10534 //      R_Mesh_ResetTextureState();
10535
10536         i = surfacelist[0];
10537         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10538                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10539                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10540                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10541
10542         if (VectorCompare(loc->mins, loc->maxs))
10543         {
10544                 VectorSet(size, 2, 2, 2);
10545                 VectorMA(loc->mins, -0.5f, size, mins);
10546         }
10547         else
10548         {
10549                 VectorCopy(loc->mins, mins);
10550                 VectorSubtract(loc->maxs, loc->mins, size);
10551         }
10552
10553         for (i = 0;i < 6*4*3;)
10554                 for (j = 0;j < 3;j++, i++)
10555                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10556
10557         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10558         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10559         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10560 }
10561
10562 void R_DrawLocs(void)
10563 {
10564         int index;
10565         cl_locnode_t *loc, *nearestloc;
10566         vec3_t center;
10567         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10568         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10569         {
10570                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10571                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10572         }
10573 }
10574
10575 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10576 {
10577         if (decalsystem->decals)
10578                 Mem_Free(decalsystem->decals);
10579         memset(decalsystem, 0, sizeof(*decalsystem));
10580 }
10581
10582 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)
10583 {
10584         tridecal_t *decal;
10585         tridecal_t *decals;
10586         int i;
10587
10588         // expand or initialize the system
10589         if (decalsystem->maxdecals <= decalsystem->numdecals)
10590         {
10591                 decalsystem_t old = *decalsystem;
10592                 qboolean useshortelements;
10593                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10594                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10595                 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)));
10596                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10597                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10598                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10599                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10600                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10601                 if (decalsystem->numdecals)
10602                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10603                 if (old.decals)
10604                         Mem_Free(old.decals);
10605                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10606                         decalsystem->element3i[i] = i;
10607                 if (useshortelements)
10608                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10609                                 decalsystem->element3s[i] = i;
10610         }
10611
10612         // grab a decal and search for another free slot for the next one
10613         decals = decalsystem->decals;
10614         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10615         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10616                 ;
10617         decalsystem->freedecal = i;
10618         if (decalsystem->numdecals <= i)
10619                 decalsystem->numdecals = i + 1;
10620
10621         // initialize the decal
10622         decal->lived = 0;
10623         decal->triangleindex = triangleindex;
10624         decal->surfaceindex = surfaceindex;
10625         decal->decalsequence = decalsequence;
10626         decal->color4f[0][0] = c0[0];
10627         decal->color4f[0][1] = c0[1];
10628         decal->color4f[0][2] = c0[2];
10629         decal->color4f[0][3] = 1;
10630         decal->color4f[1][0] = c1[0];
10631         decal->color4f[1][1] = c1[1];
10632         decal->color4f[1][2] = c1[2];
10633         decal->color4f[1][3] = 1;
10634         decal->color4f[2][0] = c2[0];
10635         decal->color4f[2][1] = c2[1];
10636         decal->color4f[2][2] = c2[2];
10637         decal->color4f[2][3] = 1;
10638         decal->vertex3f[0][0] = v0[0];
10639         decal->vertex3f[0][1] = v0[1];
10640         decal->vertex3f[0][2] = v0[2];
10641         decal->vertex3f[1][0] = v1[0];
10642         decal->vertex3f[1][1] = v1[1];
10643         decal->vertex3f[1][2] = v1[2];
10644         decal->vertex3f[2][0] = v2[0];
10645         decal->vertex3f[2][1] = v2[1];
10646         decal->vertex3f[2][2] = v2[2];
10647         decal->texcoord2f[0][0] = t0[0];
10648         decal->texcoord2f[0][1] = t0[1];
10649         decal->texcoord2f[1][0] = t1[0];
10650         decal->texcoord2f[1][1] = t1[1];
10651         decal->texcoord2f[2][0] = t2[0];
10652         decal->texcoord2f[2][1] = t2[1];
10653         TriangleNormal(v0, v1, v2, decal->plane);
10654         VectorNormalize(decal->plane);
10655         decal->plane[3] = DotProduct(v0, decal->plane);
10656 }
10657
10658 extern cvar_t cl_decals_bias;
10659 extern cvar_t cl_decals_models;
10660 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10661 // baseparms, parms, temps
10662 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)
10663 {
10664         int cornerindex;
10665         int index;
10666         float v[9][3];
10667         const float *vertex3f;
10668         const float *normal3f;
10669         int numpoints;
10670         float points[2][9][3];
10671         float temp[3];
10672         float tc[9][2];
10673         float f;
10674         float c[9][4];
10675         const int *e;
10676
10677         e = rsurface.modelelement3i + 3*triangleindex;
10678
10679         vertex3f = rsurface.modelvertex3f;
10680         normal3f = rsurface.modelnormal3f;
10681
10682         if (normal3f)
10683         {
10684                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10685                 {
10686                         index = 3*e[cornerindex];
10687                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10688                 }
10689         }
10690         else
10691         {
10692                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10693                 {
10694                         index = 3*e[cornerindex];
10695                         VectorCopy(vertex3f + index, v[cornerindex]);
10696                 }
10697         }
10698
10699         // cull backfaces
10700         //TriangleNormal(v[0], v[1], v[2], normal);
10701         //if (DotProduct(normal, localnormal) < 0.0f)
10702         //      continue;
10703         // clip by each of the box planes formed from the projection matrix
10704         // if anything survives, we emit the decal
10705         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]);
10706         if (numpoints < 3)
10707                 return;
10708         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]);
10709         if (numpoints < 3)
10710                 return;
10711         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]);
10712         if (numpoints < 3)
10713                 return;
10714         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]);
10715         if (numpoints < 3)
10716                 return;
10717         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]);
10718         if (numpoints < 3)
10719                 return;
10720         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]);
10721         if (numpoints < 3)
10722                 return;
10723         // some part of the triangle survived, so we have to accept it...
10724         if (dynamic)
10725         {
10726                 // dynamic always uses the original triangle
10727                 numpoints = 3;
10728                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10729                 {
10730                         index = 3*e[cornerindex];
10731                         VectorCopy(vertex3f + index, v[cornerindex]);
10732                 }
10733         }
10734         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10735         {
10736                 // convert vertex positions to texcoords
10737                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10738                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10739                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10740                 // calculate distance fade from the projection origin
10741                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10742                 f = bound(0.0f, f, 1.0f);
10743                 c[cornerindex][0] = r * f;
10744                 c[cornerindex][1] = g * f;
10745                 c[cornerindex][2] = b * f;
10746                 c[cornerindex][3] = 1.0f;
10747                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10748         }
10749         if (dynamic)
10750                 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);
10751         else
10752                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10753                         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);
10754 }
10755 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)
10756 {
10757         matrix4x4_t projection;
10758         decalsystem_t *decalsystem;
10759         qboolean dynamic;
10760         dp_model_t *model;
10761         const msurface_t *surface;
10762         const msurface_t *surfaces;
10763         const int *surfacelist;
10764         const texture_t *texture;
10765         int numtriangles;
10766         int numsurfacelist;
10767         int surfacelistindex;
10768         int surfaceindex;
10769         int triangleindex;
10770         float localorigin[3];
10771         float localnormal[3];
10772         float localmins[3];
10773         float localmaxs[3];
10774         float localsize;
10775         //float normal[3];
10776         float planes[6][4];
10777         float angles[3];
10778         bih_t *bih;
10779         int bih_triangles_count;
10780         int bih_triangles[256];
10781         int bih_surfaces[256];
10782
10783         decalsystem = &ent->decalsystem;
10784         model = ent->model;
10785         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10786         {
10787                 R_DecalSystem_Reset(&ent->decalsystem);
10788                 return;
10789         }
10790
10791         if (!model->brush.data_leafs && !cl_decals_models.integer)
10792         {
10793                 if (decalsystem->model)
10794                         R_DecalSystem_Reset(decalsystem);
10795                 return;
10796         }
10797
10798         if (decalsystem->model != model)
10799                 R_DecalSystem_Reset(decalsystem);
10800         decalsystem->model = model;
10801
10802         RSurf_ActiveModelEntity(ent, true, false, false);
10803
10804         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10805         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10806         VectorNormalize(localnormal);
10807         localsize = worldsize*rsurface.inversematrixscale;
10808         localmins[0] = localorigin[0] - localsize;
10809         localmins[1] = localorigin[1] - localsize;
10810         localmins[2] = localorigin[2] - localsize;
10811         localmaxs[0] = localorigin[0] + localsize;
10812         localmaxs[1] = localorigin[1] + localsize;
10813         localmaxs[2] = localorigin[2] + localsize;
10814
10815         //VectorCopy(localnormal, planes[4]);
10816         //VectorVectors(planes[4], planes[2], planes[0]);
10817         AnglesFromVectors(angles, localnormal, NULL, false);
10818         AngleVectors(angles, planes[0], planes[2], planes[4]);
10819         VectorNegate(planes[0], planes[1]);
10820         VectorNegate(planes[2], planes[3]);
10821         VectorNegate(planes[4], planes[5]);
10822         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10823         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10824         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10825         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10826         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10827         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10828
10829 #if 1
10830 // works
10831 {
10832         matrix4x4_t forwardprojection;
10833         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10834         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10835 }
10836 #else
10837 // broken
10838 {
10839         float projectionvector[4][3];
10840         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10841         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10842         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10843         projectionvector[0][0] = planes[0][0] * ilocalsize;
10844         projectionvector[0][1] = planes[1][0] * ilocalsize;
10845         projectionvector[0][2] = planes[2][0] * ilocalsize;
10846         projectionvector[1][0] = planes[0][1] * ilocalsize;
10847         projectionvector[1][1] = planes[1][1] * ilocalsize;
10848         projectionvector[1][2] = planes[2][1] * ilocalsize;
10849         projectionvector[2][0] = planes[0][2] * ilocalsize;
10850         projectionvector[2][1] = planes[1][2] * ilocalsize;
10851         projectionvector[2][2] = planes[2][2] * ilocalsize;
10852         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10853         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10854         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10855         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10856 }
10857 #endif
10858
10859         dynamic = model->surfmesh.isanimated;
10860         numsurfacelist = model->nummodelsurfaces;
10861         surfacelist = model->sortedmodelsurfaces;
10862         surfaces = model->data_surfaces;
10863
10864         bih = NULL;
10865         bih_triangles_count = -1;
10866         if(!dynamic)
10867         {
10868                 if(model->render_bih.numleafs)
10869                         bih = &model->render_bih;
10870                 else if(model->collision_bih.numleafs)
10871                         bih = &model->collision_bih;
10872         }
10873         if(bih)
10874                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10875         if(bih_triangles_count == 0)
10876                 return;
10877         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10878                 return;
10879         if(bih_triangles_count > 0)
10880         {
10881                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10882                 {
10883                         surfaceindex = bih_surfaces[triangleindex];
10884                         surface = surfaces + surfaceindex;
10885                         texture = surface->texture;
10886                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10887                                 continue;
10888                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10889                                 continue;
10890                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10891                 }
10892         }
10893         else
10894         {
10895                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10896                 {
10897                         surfaceindex = surfacelist[surfacelistindex];
10898                         surface = surfaces + surfaceindex;
10899                         // check cull box first because it rejects more than any other check
10900                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10901                                 continue;
10902                         // skip transparent surfaces
10903                         texture = surface->texture;
10904                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10905                                 continue;
10906                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10907                                 continue;
10908                         numtriangles = surface->num_triangles;
10909                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10910                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10911                 }
10912         }
10913 }
10914
10915 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10916 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)
10917 {
10918         int renderentityindex;
10919         float worldmins[3];
10920         float worldmaxs[3];
10921         entity_render_t *ent;
10922
10923         if (!cl_decals_newsystem.integer)
10924                 return;
10925
10926         worldmins[0] = worldorigin[0] - worldsize;
10927         worldmins[1] = worldorigin[1] - worldsize;
10928         worldmins[2] = worldorigin[2] - worldsize;
10929         worldmaxs[0] = worldorigin[0] + worldsize;
10930         worldmaxs[1] = worldorigin[1] + worldsize;
10931         worldmaxs[2] = worldorigin[2] + worldsize;
10932
10933         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10934
10935         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10936         {
10937                 ent = r_refdef.scene.entities[renderentityindex];
10938                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10939                         continue;
10940
10941                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10942         }
10943 }
10944
10945 typedef struct r_decalsystem_splatqueue_s
10946 {
10947         vec3_t worldorigin;
10948         vec3_t worldnormal;
10949         float color[4];
10950         float tcrange[4];
10951         float worldsize;
10952         int decalsequence;
10953 }
10954 r_decalsystem_splatqueue_t;
10955
10956 int r_decalsystem_numqueued = 0;
10957 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10958
10959 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)
10960 {
10961         r_decalsystem_splatqueue_t *queue;
10962
10963         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10964                 return;
10965
10966         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10967         VectorCopy(worldorigin, queue->worldorigin);
10968         VectorCopy(worldnormal, queue->worldnormal);
10969         Vector4Set(queue->color, r, g, b, a);
10970         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10971         queue->worldsize = worldsize;
10972         queue->decalsequence = cl.decalsequence++;
10973 }
10974
10975 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10976 {
10977         int i;
10978         r_decalsystem_splatqueue_t *queue;
10979
10980         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10981                 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);
10982         r_decalsystem_numqueued = 0;
10983 }
10984
10985 extern cvar_t cl_decals_max;
10986 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10987 {
10988         int i;
10989         decalsystem_t *decalsystem = &ent->decalsystem;
10990         int numdecals;
10991         int killsequence;
10992         tridecal_t *decal;
10993         float frametime;
10994         float lifetime;
10995
10996         if (!decalsystem->numdecals)
10997                 return;
10998
10999         if (r_showsurfaces.integer)
11000                 return;
11001
11002         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11003         {
11004                 R_DecalSystem_Reset(decalsystem);
11005                 return;
11006         }
11007
11008         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11009         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11010
11011         if (decalsystem->lastupdatetime)
11012                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11013         else
11014                 frametime = 0;
11015         decalsystem->lastupdatetime = r_refdef.scene.time;
11016         decal = decalsystem->decals;
11017         numdecals = decalsystem->numdecals;
11018
11019         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11020         {
11021                 if (decal->color4f[0][3])
11022                 {
11023                         decal->lived += frametime;
11024                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11025                         {
11026                                 memset(decal, 0, sizeof(*decal));
11027                                 if (decalsystem->freedecal > i)
11028                                         decalsystem->freedecal = i;
11029                         }
11030                 }
11031         }
11032         decal = decalsystem->decals;
11033         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11034                 numdecals--;
11035
11036         // collapse the array by shuffling the tail decals into the gaps
11037         for (;;)
11038         {
11039                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11040                         decalsystem->freedecal++;
11041                 if (decalsystem->freedecal == numdecals)
11042                         break;
11043                 decal[decalsystem->freedecal] = decal[--numdecals];
11044         }
11045
11046         decalsystem->numdecals = numdecals;
11047
11048         if (numdecals <= 0)
11049         {
11050                 // if there are no decals left, reset decalsystem
11051                 R_DecalSystem_Reset(decalsystem);
11052         }
11053 }
11054
11055 extern skinframe_t *decalskinframe;
11056 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11057 {
11058         int i;
11059         decalsystem_t *decalsystem = &ent->decalsystem;
11060         int numdecals;
11061         tridecal_t *decal;
11062         float faderate;
11063         float alpha;
11064         float *v3f;
11065         float *c4f;
11066         float *t2f;
11067         const int *e;
11068         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11069         int numtris = 0;
11070
11071         numdecals = decalsystem->numdecals;
11072         if (!numdecals)
11073                 return;
11074
11075         if (r_showsurfaces.integer)
11076                 return;
11077
11078         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11079         {
11080                 R_DecalSystem_Reset(decalsystem);
11081                 return;
11082         }
11083
11084         // if the model is static it doesn't matter what value we give for
11085         // wantnormals and wanttangents, so this logic uses only rules applicable
11086         // to a model, knowing that they are meaningless otherwise
11087         if (ent == r_refdef.scene.worldentity)
11088                 RSurf_ActiveWorldEntity();
11089         else
11090                 RSurf_ActiveModelEntity(ent, false, false, false);
11091
11092         decalsystem->lastupdatetime = r_refdef.scene.time;
11093         decal = decalsystem->decals;
11094
11095         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11096
11097         // update vertex positions for animated models
11098         v3f = decalsystem->vertex3f;
11099         c4f = decalsystem->color4f;
11100         t2f = decalsystem->texcoord2f;
11101         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11102         {
11103                 if (!decal->color4f[0][3])
11104                         continue;
11105
11106                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11107                         continue;
11108
11109                 // skip backfaces
11110                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11111                         continue;
11112
11113                 // update color values for fading decals
11114                 if (decal->lived >= cl_decals_time.value)
11115                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11116                 else
11117                         alpha = 1.0f;
11118
11119                 c4f[ 0] = decal->color4f[0][0] * alpha;
11120                 c4f[ 1] = decal->color4f[0][1] * alpha;
11121                 c4f[ 2] = decal->color4f[0][2] * alpha;
11122                 c4f[ 3] = 1;
11123                 c4f[ 4] = decal->color4f[1][0] * alpha;
11124                 c4f[ 5] = decal->color4f[1][1] * alpha;
11125                 c4f[ 6] = decal->color4f[1][2] * alpha;
11126                 c4f[ 7] = 1;
11127                 c4f[ 8] = decal->color4f[2][0] * alpha;
11128                 c4f[ 9] = decal->color4f[2][1] * alpha;
11129                 c4f[10] = decal->color4f[2][2] * alpha;
11130                 c4f[11] = 1;
11131
11132                 t2f[0] = decal->texcoord2f[0][0];
11133                 t2f[1] = decal->texcoord2f[0][1];
11134                 t2f[2] = decal->texcoord2f[1][0];
11135                 t2f[3] = decal->texcoord2f[1][1];
11136                 t2f[4] = decal->texcoord2f[2][0];
11137                 t2f[5] = decal->texcoord2f[2][1];
11138
11139                 // update vertex positions for animated models
11140                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11141                 {
11142                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11143                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11144                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11145                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11146                 }
11147                 else
11148                 {
11149                         VectorCopy(decal->vertex3f[0], v3f);
11150                         VectorCopy(decal->vertex3f[1], v3f + 3);
11151                         VectorCopy(decal->vertex3f[2], v3f + 6);
11152                 }
11153
11154                 if (r_refdef.fogenabled)
11155                 {
11156                         alpha = RSurf_FogVertex(v3f);
11157                         VectorScale(c4f, alpha, c4f);
11158                         alpha = RSurf_FogVertex(v3f + 3);
11159                         VectorScale(c4f + 4, alpha, c4f + 4);
11160                         alpha = RSurf_FogVertex(v3f + 6);
11161                         VectorScale(c4f + 8, alpha, c4f + 8);
11162                 }
11163
11164                 v3f += 9;
11165                 c4f += 12;
11166                 t2f += 6;
11167                 numtris++;
11168         }
11169
11170         if (numtris > 0)
11171         {
11172                 r_refdef.stats.drawndecals += numtris;
11173
11174                 // now render the decals all at once
11175                 // (this assumes they all use one particle font texture!)
11176                 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);
11177 //              R_Mesh_ResetTextureState();
11178                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11179                 GL_DepthMask(false);
11180                 GL_DepthRange(0, 1);
11181                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11182                 GL_DepthTest(true);
11183                 GL_CullFace(GL_NONE);
11184                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11185                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11186                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11187         }
11188 }
11189
11190 static void R_DrawModelDecals(void)
11191 {
11192         int i, numdecals;
11193
11194         // fade faster when there are too many decals
11195         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11196         for (i = 0;i < r_refdef.scene.numentities;i++)
11197                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11198
11199         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11200         for (i = 0;i < r_refdef.scene.numentities;i++)
11201                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11202                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11203
11204         R_DecalSystem_ApplySplatEntitiesQueue();
11205
11206         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11207         for (i = 0;i < r_refdef.scene.numentities;i++)
11208                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11209
11210         r_refdef.stats.totaldecals += numdecals;
11211
11212         if (r_showsurfaces.integer)
11213                 return;
11214
11215         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11216
11217         for (i = 0;i < r_refdef.scene.numentities;i++)
11218         {
11219                 if (!r_refdef.viewcache.entityvisible[i])
11220                         continue;
11221                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11222                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11223         }
11224 }
11225
11226 extern cvar_t mod_collision_bih;
11227 void R_DrawDebugModel(void)
11228 {
11229         entity_render_t *ent = rsurface.entity;
11230         int i, j, k, l, flagsmask;
11231         const msurface_t *surface;
11232         dp_model_t *model = ent->model;
11233         vec3_t v;
11234
11235         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11236                 return;
11237
11238         if (r_showoverdraw.value > 0)
11239         {
11240                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11241                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11242                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11243                 GL_DepthTest(false);
11244                 GL_DepthMask(false);
11245                 GL_DepthRange(0, 1);
11246                 GL_BlendFunc(GL_ONE, GL_ONE);
11247                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11248                 {
11249                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11250                                 continue;
11251                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11252                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11253                         {
11254                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11255                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11256                                 if (!rsurface.texture->currentlayers->depthmask)
11257                                         GL_Color(c, 0, 0, 1.0f);
11258                                 else if (ent == r_refdef.scene.worldentity)
11259                                         GL_Color(c, c, c, 1.0f);
11260                                 else
11261                                         GL_Color(0, c, 0, 1.0f);
11262                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11263                                 RSurf_DrawBatch();
11264                         }
11265                 }
11266                 rsurface.texture = NULL;
11267         }
11268
11269         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11270
11271 //      R_Mesh_ResetTextureState();
11272         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11273         GL_DepthRange(0, 1);
11274         GL_DepthTest(!r_showdisabledepthtest.integer);
11275         GL_DepthMask(false);
11276         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11277
11278         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11279         {
11280                 int triangleindex;
11281                 int bihleafindex;
11282                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11283                 const q3mbrush_t *brush;
11284                 const bih_t *bih = &model->collision_bih;
11285                 const bih_leaf_t *bihleaf;
11286                 float vertex3f[3][3];
11287                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11288                 cullbox = false;
11289                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11290                 {
11291                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11292                                 continue;
11293                         switch (bihleaf->type)
11294                         {
11295                         case BIH_BRUSH:
11296                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11297                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11298                                 {
11299                                         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);
11300                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11301                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11302                                 }
11303                                 break;
11304                         case BIH_COLLISIONTRIANGLE:
11305                                 triangleindex = bihleaf->itemindex;
11306                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11307                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11308                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[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                         case BIH_RENDERTRIANGLE:
11314                                 triangleindex = bihleaf->itemindex;
11315                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11316                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11317                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11318                                 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);
11319                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11320                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11321                                 break;
11322                         }
11323                 }
11324         }
11325
11326         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11327
11328         if (r_showtris.integer && qglPolygonMode)
11329         {
11330                 if (r_showdisabledepthtest.integer)
11331                 {
11332                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11333                         GL_DepthMask(false);
11334                 }
11335                 else
11336                 {
11337                         GL_BlendFunc(GL_ONE, GL_ZERO);
11338                         GL_DepthMask(true);
11339                 }
11340                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11341                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11342                 {
11343                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11344                                 continue;
11345                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11346                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11347                         {
11348                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11349                                 if (!rsurface.texture->currentlayers->depthmask)
11350                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11351                                 else if (ent == r_refdef.scene.worldentity)
11352                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11353                                 else
11354                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11355                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11356                                 RSurf_DrawBatch();
11357                         }
11358                 }
11359                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11360                 rsurface.texture = NULL;
11361         }
11362
11363         if (r_shownormals.value != 0 && qglBegin)
11364         {
11365                 if (r_showdisabledepthtest.integer)
11366                 {
11367                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11368                         GL_DepthMask(false);
11369                 }
11370                 else
11371                 {
11372                         GL_BlendFunc(GL_ONE, GL_ZERO);
11373                         GL_DepthMask(true);
11374                 }
11375                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11376                 {
11377                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11378                                 continue;
11379                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11380                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11381                         {
11382                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11383                                 qglBegin(GL_LINES);
11384                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11385                                 {
11386                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11387                                         {
11388                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11389                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11390                                                 qglVertex3f(v[0], v[1], v[2]);
11391                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11392                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11393                                                 qglVertex3f(v[0], v[1], v[2]);
11394                                         }
11395                                 }
11396                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11397                                 {
11398                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11399                                         {
11400                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11401                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11402                                                 qglVertex3f(v[0], v[1], v[2]);
11403                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11404                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11405                                                 qglVertex3f(v[0], v[1], v[2]);
11406                                         }
11407                                 }
11408                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11409                                 {
11410                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11411                                         {
11412                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11413                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11414                                                 qglVertex3f(v[0], v[1], v[2]);
11415                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11416                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11417                                                 qglVertex3f(v[0], v[1], v[2]);
11418                                         }
11419                                 }
11420                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11421                                 {
11422                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11423                                         {
11424                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11425                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11426                                                 qglVertex3f(v[0], v[1], v[2]);
11427                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11428                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11429                                                 qglVertex3f(v[0], v[1], v[2]);
11430                                         }
11431                                 }
11432                                 qglEnd();
11433                                 CHECKGLERROR
11434                         }
11435                 }
11436                 rsurface.texture = NULL;
11437         }
11438 }
11439
11440 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11441 int r_maxsurfacelist = 0;
11442 const msurface_t **r_surfacelist = NULL;
11443 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11444 {
11445         int i, j, endj, flagsmask;
11446         dp_model_t *model = r_refdef.scene.worldmodel;
11447         msurface_t *surfaces;
11448         unsigned char *update;
11449         int numsurfacelist = 0;
11450         if (model == NULL)
11451                 return;
11452
11453         if (r_maxsurfacelist < model->num_surfaces)
11454         {
11455                 r_maxsurfacelist = model->num_surfaces;
11456                 if (r_surfacelist)
11457                         Mem_Free((msurface_t**)r_surfacelist);
11458                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11459         }
11460
11461         RSurf_ActiveWorldEntity();
11462
11463         surfaces = model->data_surfaces;
11464         update = model->brushq1.lightmapupdateflags;
11465
11466         // update light styles on this submodel
11467         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11468         {
11469                 model_brush_lightstyleinfo_t *style;
11470                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11471                 {
11472                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11473                         {
11474                                 int *list = style->surfacelist;
11475                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11476                                 for (j = 0;j < style->numsurfaces;j++)
11477                                         update[list[j]] = true;
11478                         }
11479                 }
11480         }
11481
11482         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11483
11484         if (debug)
11485         {
11486                 R_DrawDebugModel();
11487                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11488                 return;
11489         }
11490
11491         rsurface.lightmaptexture = NULL;
11492         rsurface.deluxemaptexture = NULL;
11493         rsurface.uselightmaptexture = false;
11494         rsurface.texture = NULL;
11495         rsurface.rtlight = NULL;
11496         numsurfacelist = 0;
11497         // add visible surfaces to draw list
11498         for (i = 0;i < model->nummodelsurfaces;i++)
11499         {
11500                 j = model->sortedmodelsurfaces[i];
11501                 if (r_refdef.viewcache.world_surfacevisible[j])
11502                         r_surfacelist[numsurfacelist++] = surfaces + j;
11503         }
11504         // update lightmaps if needed
11505         if (model->brushq1.firstrender)
11506         {
11507                 model->brushq1.firstrender = false;
11508                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11509                         if (update[j])
11510                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11511         }
11512         else if (update)
11513         {
11514                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11515                         if (r_refdef.viewcache.world_surfacevisible[j])
11516                                 if (update[j])
11517                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11518         }
11519         // don't do anything if there were no surfaces
11520         if (!numsurfacelist)
11521         {
11522                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11523                 return;
11524         }
11525         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11526
11527         // add to stats if desired
11528         if (r_speeds.integer && !skysurfaces && !depthonly)
11529         {
11530                 r_refdef.stats.world_surfaces += numsurfacelist;
11531                 for (j = 0;j < numsurfacelist;j++)
11532                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11533         }
11534
11535         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11536 }
11537
11538 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11539 {
11540         int i, j, endj, flagsmask;
11541         dp_model_t *model = ent->model;
11542         msurface_t *surfaces;
11543         unsigned char *update;
11544         int numsurfacelist = 0;
11545         if (model == NULL)
11546                 return;
11547
11548         if (r_maxsurfacelist < model->num_surfaces)
11549         {
11550                 r_maxsurfacelist = model->num_surfaces;
11551                 if (r_surfacelist)
11552                         Mem_Free((msurface_t **)r_surfacelist);
11553                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11554         }
11555
11556         // if the model is static it doesn't matter what value we give for
11557         // wantnormals and wanttangents, so this logic uses only rules applicable
11558         // to a model, knowing that they are meaningless otherwise
11559         if (ent == r_refdef.scene.worldentity)
11560                 RSurf_ActiveWorldEntity();
11561         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11562                 RSurf_ActiveModelEntity(ent, false, false, false);
11563         else if (prepass)
11564                 RSurf_ActiveModelEntity(ent, true, true, true);
11565         else if (depthonly)
11566         {
11567                 switch (vid.renderpath)
11568                 {
11569                 case RENDERPATH_GL20:
11570                 case RENDERPATH_D3D9:
11571                 case RENDERPATH_D3D10:
11572                 case RENDERPATH_D3D11:
11573                 case RENDERPATH_SOFT:
11574                 case RENDERPATH_GLES2:
11575                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11576                         break;
11577                 case RENDERPATH_GL11:
11578                 case RENDERPATH_GL13:
11579                 case RENDERPATH_GLES1:
11580                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11581                         break;
11582                 }
11583         }
11584         else
11585         {
11586                 switch (vid.renderpath)
11587                 {
11588                 case RENDERPATH_GL20:
11589                 case RENDERPATH_D3D9:
11590                 case RENDERPATH_D3D10:
11591                 case RENDERPATH_D3D11:
11592                 case RENDERPATH_SOFT:
11593                 case RENDERPATH_GLES2:
11594                         RSurf_ActiveModelEntity(ent, true, true, false);
11595                         break;
11596                 case RENDERPATH_GL11:
11597                 case RENDERPATH_GL13:
11598                 case RENDERPATH_GLES1:
11599                         RSurf_ActiveModelEntity(ent, true, false, false);
11600                         break;
11601                 }
11602         }
11603
11604         surfaces = model->data_surfaces;
11605         update = model->brushq1.lightmapupdateflags;
11606
11607         // update light styles
11608         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11609         {
11610                 model_brush_lightstyleinfo_t *style;
11611                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11612                 {
11613                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11614                         {
11615                                 int *list = style->surfacelist;
11616                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11617                                 for (j = 0;j < style->numsurfaces;j++)
11618                                         update[list[j]] = true;
11619                         }
11620                 }
11621         }
11622
11623         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11624
11625         if (debug)
11626         {
11627                 R_DrawDebugModel();
11628                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11629                 return;
11630         }
11631
11632         rsurface.lightmaptexture = NULL;
11633         rsurface.deluxemaptexture = NULL;
11634         rsurface.uselightmaptexture = false;
11635         rsurface.texture = NULL;
11636         rsurface.rtlight = NULL;
11637         numsurfacelist = 0;
11638         // add visible surfaces to draw list
11639         for (i = 0;i < model->nummodelsurfaces;i++)
11640                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11641         // don't do anything if there were no surfaces
11642         if (!numsurfacelist)
11643         {
11644                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11645                 return;
11646         }
11647         // update lightmaps if needed
11648         if (update)
11649         {
11650                 int updated = 0;
11651                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11652                 {
11653                         if (update[j])
11654                         {
11655                                 updated++;
11656                                 R_BuildLightMap(ent, surfaces + j);
11657                         }
11658                 }
11659         }
11660         if (update)
11661                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11662                         if (update[j])
11663                                 R_BuildLightMap(ent, surfaces + j);
11664         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11665
11666         // add to stats if desired
11667         if (r_speeds.integer && !skysurfaces && !depthonly)
11668         {
11669                 r_refdef.stats.entities_surfaces += numsurfacelist;
11670                 for (j = 0;j < numsurfacelist;j++)
11671                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11672         }
11673
11674         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11675 }
11676
11677 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11678 {
11679         static texture_t texture;
11680         static msurface_t surface;
11681         const msurface_t *surfacelist = &surface;
11682
11683         // fake enough texture and surface state to render this geometry
11684
11685         texture.update_lastrenderframe = -1; // regenerate this texture
11686         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11687         texture.currentskinframe = skinframe;
11688         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11689         texture.offsetmapping = OFFSETMAPPING_OFF;
11690         texture.offsetscale = 1;
11691         texture.specularscalemod = 1;
11692         texture.specularpowermod = 1;
11693
11694         surface.texture = &texture;
11695         surface.num_triangles = numtriangles;
11696         surface.num_firsttriangle = firsttriangle;
11697         surface.num_vertices = numvertices;
11698         surface.num_firstvertex = firstvertex;
11699
11700         // now render it
11701         rsurface.texture = R_GetCurrentTexture(surface.texture);
11702         rsurface.lightmaptexture = NULL;
11703         rsurface.deluxemaptexture = NULL;
11704         rsurface.uselightmaptexture = false;
11705         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11706 }
11707
11708 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)
11709 {
11710         static msurface_t surface;
11711         const msurface_t *surfacelist = &surface;
11712
11713         // fake enough texture and surface state to render this geometry
11714         surface.texture = texture;
11715         surface.num_triangles = numtriangles;
11716         surface.num_firsttriangle = firsttriangle;
11717         surface.num_vertices = numvertices;
11718         surface.num_firstvertex = firstvertex;
11719
11720         // now render it
11721         rsurface.texture = R_GetCurrentTexture(surface.texture);
11722         rsurface.lightmaptexture = NULL;
11723         rsurface.deluxemaptexture = NULL;
11724         rsurface.uselightmaptexture = false;
11725         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11726 }