]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
8574aeb2db3c3dc43ed43ee2915348e17d72a800
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
78 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
82 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
85 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
86 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
95 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
118 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
127
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
136
137 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
138 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
152
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
169
170 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
177
178 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
179 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
180 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
181 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
182
183 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
184 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
185 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
186 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
187 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
188 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
189 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
190
191 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
192 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
193 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
194 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
195 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
196 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
197 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
200 cvar_t r_hdr_irisadaptation_fade = {CVAR_SAVE, "r_hdr_irisadaptation_fade", "1", "fade rate at which value adjusts"};
201
202 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
203
204 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
205
206 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
207
208 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
209
210 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
211 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
212
213 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
214
215 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
216
217 extern cvar_t v_glslgamma;
218
219 extern qboolean v_flipped_state;
220
221 static struct r_bloomstate_s
222 {
223         qboolean enabled;
224         qboolean hdr;
225
226         int bloomwidth, bloomheight;
227
228         textype_t texturetype;
229         int viewfbo; // used to check if r_viewfbo cvar has changed
230
231         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
232         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
233         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
234
235         int screentexturewidth, screentextureheight;
236         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
237
238         int bloomtexturewidth, bloomtextureheight;
239         rtexture_t *texture_bloom;
240
241         // arrays for rendering the screen passes
242         float screentexcoord2f[8];
243         float bloomtexcoord2f[8];
244         float offsettexcoord2f[8];
245
246         r_viewport_t viewport;
247 }
248 r_bloomstate;
249
250 r_waterstate_t r_waterstate;
251
252 /// shadow volume bsp struct with automatically growing nodes buffer
253 svbsp_t r_svbsp;
254
255 rtexture_t *r_texture_blanknormalmap;
256 rtexture_t *r_texture_white;
257 rtexture_t *r_texture_grey128;
258 rtexture_t *r_texture_black;
259 rtexture_t *r_texture_notexture;
260 rtexture_t *r_texture_whitecube;
261 rtexture_t *r_texture_normalizationcube;
262 rtexture_t *r_texture_fogattenuation;
263 rtexture_t *r_texture_fogheighttexture;
264 rtexture_t *r_texture_gammaramps;
265 unsigned int r_texture_gammaramps_serial;
266 //rtexture_t *r_texture_fogintensity;
267 rtexture_t *r_texture_reflectcube;
268
269 // TODO: hash lookups?
270 typedef struct cubemapinfo_s
271 {
272         char basename[64];
273         rtexture_t *texture;
274 }
275 cubemapinfo_t;
276
277 int r_texture_numcubemaps;
278 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
279
280 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
281 unsigned int r_numqueries;
282 unsigned int r_maxqueries;
283
284 typedef struct r_qwskincache_s
285 {
286         char name[MAX_QPATH];
287         skinframe_t *skinframe;
288 }
289 r_qwskincache_t;
290
291 static r_qwskincache_t *r_qwskincache;
292 static int r_qwskincache_size;
293
294 /// vertex coordinates for a quad that covers the screen exactly
295 extern const float r_screenvertex3f[12];
296 extern const float r_d3dscreenvertex3f[12];
297 const float r_screenvertex3f[12] =
298 {
299         0, 0, 0,
300         1, 0, 0,
301         1, 1, 0,
302         0, 1, 0
303 };
304 const float r_d3dscreenvertex3f[12] =
305 {
306         0, 1, 0,
307         1, 1, 0,
308         1, 0, 0,
309         0, 0, 0
310 };
311
312 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
313 {
314         int i;
315         for (i = 0;i < verts;i++)
316         {
317                 out[0] = in[0] * r;
318                 out[1] = in[1] * g;
319                 out[2] = in[2] * b;
320                 out[3] = in[3];
321                 in += 4;
322                 out += 4;
323         }
324 }
325
326 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
327 {
328         int i;
329         for (i = 0;i < verts;i++)
330         {
331                 out[0] = r;
332                 out[1] = g;
333                 out[2] = b;
334                 out[3] = a;
335                 out += 4;
336         }
337 }
338
339 // FIXME: move this to client?
340 void FOG_clear(void)
341 {
342         if (gamemode == GAME_NEHAHRA)
343         {
344                 Cvar_Set("gl_fogenable", "0");
345                 Cvar_Set("gl_fogdensity", "0.2");
346                 Cvar_Set("gl_fogred", "0.3");
347                 Cvar_Set("gl_foggreen", "0.3");
348                 Cvar_Set("gl_fogblue", "0.3");
349         }
350         r_refdef.fog_density = 0;
351         r_refdef.fog_red = 0;
352         r_refdef.fog_green = 0;
353         r_refdef.fog_blue = 0;
354         r_refdef.fog_alpha = 1;
355         r_refdef.fog_start = 0;
356         r_refdef.fog_end = 16384;
357         r_refdef.fog_height = 1<<30;
358         r_refdef.fog_fadedepth = 128;
359         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
360 }
361
362 static void R_BuildBlankTextures(void)
363 {
364         unsigned char data[4];
365         data[2] = 128; // normal X
366         data[1] = 128; // normal Y
367         data[0] = 255; // normal Z
368         data[3] = 128; // height
369         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
370         data[0] = 255;
371         data[1] = 255;
372         data[2] = 255;
373         data[3] = 255;
374         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 128;
376         data[1] = 128;
377         data[2] = 128;
378         data[3] = 255;
379         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 0;
381         data[1] = 0;
382         data[2] = 0;
383         data[3] = 255;
384         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385 }
386
387 static void R_BuildNoTexture(void)
388 {
389         int x, y;
390         unsigned char pix[16][16][4];
391         // this makes a light grey/dark grey checkerboard texture
392         for (y = 0;y < 16;y++)
393         {
394                 for (x = 0;x < 16;x++)
395                 {
396                         if ((y < 8) ^ (x < 8))
397                         {
398                                 pix[y][x][0] = 128;
399                                 pix[y][x][1] = 128;
400                                 pix[y][x][2] = 128;
401                                 pix[y][x][3] = 255;
402                         }
403                         else
404                         {
405                                 pix[y][x][0] = 64;
406                                 pix[y][x][1] = 64;
407                                 pix[y][x][2] = 64;
408                                 pix[y][x][3] = 255;
409                         }
410                 }
411         }
412         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
413 }
414
415 static void R_BuildWhiteCube(void)
416 {
417         unsigned char data[6*1*1*4];
418         memset(data, 255, sizeof(data));
419         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
420 }
421
422 static void R_BuildNormalizationCube(void)
423 {
424         int x, y, side;
425         vec3_t v;
426         vec_t s, t, intensity;
427 #define NORMSIZE 64
428         unsigned char *data;
429         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
430         for (side = 0;side < 6;side++)
431         {
432                 for (y = 0;y < NORMSIZE;y++)
433                 {
434                         for (x = 0;x < NORMSIZE;x++)
435                         {
436                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
437                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
438                                 switch(side)
439                                 {
440                                 default:
441                                 case 0:
442                                         v[0] = 1;
443                                         v[1] = -t;
444                                         v[2] = -s;
445                                         break;
446                                 case 1:
447                                         v[0] = -1;
448                                         v[1] = -t;
449                                         v[2] = s;
450                                         break;
451                                 case 2:
452                                         v[0] = s;
453                                         v[1] = 1;
454                                         v[2] = t;
455                                         break;
456                                 case 3:
457                                         v[0] = s;
458                                         v[1] = -1;
459                                         v[2] = -t;
460                                         break;
461                                 case 4:
462                                         v[0] = s;
463                                         v[1] = -t;
464                                         v[2] = 1;
465                                         break;
466                                 case 5:
467                                         v[0] = -s;
468                                         v[1] = -t;
469                                         v[2] = -1;
470                                         break;
471                                 }
472                                 intensity = 127.0f / sqrt(DotProduct(v, v));
473                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
474                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
475                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
476                                 data[((side*64+y)*64+x)*4+3] = 255;
477                         }
478                 }
479         }
480         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
481         Mem_Free(data);
482 }
483
484 static void R_BuildFogTexture(void)
485 {
486         int x, b;
487 #define FOGWIDTH 256
488         unsigned char data1[FOGWIDTH][4];
489         //unsigned char data2[FOGWIDTH][4];
490         double d, r, alpha;
491
492         r_refdef.fogmasktable_start = r_refdef.fog_start;
493         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
494         r_refdef.fogmasktable_range = r_refdef.fogrange;
495         r_refdef.fogmasktable_density = r_refdef.fog_density;
496
497         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
498         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
499         {
500                 d = (x * r - r_refdef.fogmasktable_start);
501                 if(developer_extra.integer)
502                         Con_DPrintf("%f ", d);
503                 d = max(0, d);
504                 if (r_fog_exp2.integer)
505                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
506                 else
507                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
508                 if(developer_extra.integer)
509                         Con_DPrintf(" : %f ", alpha);
510                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
511                 if(developer_extra.integer)
512                         Con_DPrintf(" = %f\n", alpha);
513                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
514         }
515
516         for (x = 0;x < FOGWIDTH;x++)
517         {
518                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
519                 data1[x][0] = b;
520                 data1[x][1] = b;
521                 data1[x][2] = b;
522                 data1[x][3] = 255;
523                 //data2[x][0] = 255 - b;
524                 //data2[x][1] = 255 - b;
525                 //data2[x][2] = 255 - b;
526                 //data2[x][3] = 255;
527         }
528         if (r_texture_fogattenuation)
529         {
530                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
531                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
532         }
533         else
534         {
535                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
536                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
537         }
538 }
539
540 static void R_BuildFogHeightTexture(void)
541 {
542         unsigned char *inpixels;
543         int size;
544         int x;
545         int y;
546         int j;
547         float c[4];
548         float f;
549         inpixels = NULL;
550         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
551         if (r_refdef.fogheighttexturename[0])
552                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
553         if (!inpixels)
554         {
555                 r_refdef.fog_height_tablesize = 0;
556                 if (r_texture_fogheighttexture)
557                         R_FreeTexture(r_texture_fogheighttexture);
558                 r_texture_fogheighttexture = NULL;
559                 if (r_refdef.fog_height_table2d)
560                         Mem_Free(r_refdef.fog_height_table2d);
561                 r_refdef.fog_height_table2d = NULL;
562                 if (r_refdef.fog_height_table1d)
563                         Mem_Free(r_refdef.fog_height_table1d);
564                 r_refdef.fog_height_table1d = NULL;
565                 return;
566         }
567         size = image_width;
568         r_refdef.fog_height_tablesize = size;
569         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
570         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
571         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
572         Mem_Free(inpixels);
573         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
574         // average fog color table accounting for every fog layer between a point
575         // and the camera.  (Note: attenuation is handled separately!)
576         for (y = 0;y < size;y++)
577         {
578                 for (x = 0;x < size;x++)
579                 {
580                         Vector4Clear(c);
581                         f = 0;
582                         if (x < y)
583                         {
584                                 for (j = x;j <= y;j++)
585                                 {
586                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
587                                         f++;
588                                 }
589                         }
590                         else
591                         {
592                                 for (j = x;j >= y;j--)
593                                 {
594                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
595                                         f++;
596                                 }
597                         }
598                         f = 1.0f / f;
599                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
600                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
601                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
602                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
603                 }
604         }
605         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
606 }
607
608 //=======================================================================================================================================================
609
610 static const char *builtinshaderstring =
611 #include "shader_glsl.h"
612 ;
613
614 const char *builtinhlslshaderstring =
615 #include "shader_hlsl.h"
616 ;
617
618 char *glslshaderstring = NULL;
619 char *hlslshaderstring = NULL;
620
621 //=======================================================================================================================================================
622
623 typedef struct shaderpermutationinfo_s
624 {
625         const char *pretext;
626         const char *name;
627 }
628 shaderpermutationinfo_t;
629
630 typedef struct shadermodeinfo_s
631 {
632         const char *vertexfilename;
633         const char *geometryfilename;
634         const char *fragmentfilename;
635         const char *pretext;
636         const char *name;
637 }
638 shadermodeinfo_t;
639
640 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
641 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
642 {
643         {"#define USEDIFFUSE\n", " diffuse"},
644         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
645         {"#define USEVIEWTINT\n", " viewtint"},
646         {"#define USECOLORMAPPING\n", " colormapping"},
647         {"#define USESATURATION\n", " saturation"},
648         {"#define USEFOGINSIDE\n", " foginside"},
649         {"#define USEFOGOUTSIDE\n", " fogoutside"},
650         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
651         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
652         {"#define USEGAMMARAMPS\n", " gammaramps"},
653         {"#define USECUBEFILTER\n", " cubefilter"},
654         {"#define USEGLOW\n", " glow"},
655         {"#define USEBLOOM\n", " bloom"},
656         {"#define USESPECULAR\n", " specular"},
657         {"#define USEPOSTPROCESSING\n", " postprocessing"},
658         {"#define USEREFLECTION\n", " reflection"},
659         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
660         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
661         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
662         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
663         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
664         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
665         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
666         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
667         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
668         {"#define USEALPHAKILL\n", " alphakill"},
669         {"#define USEREFLECTCUBE\n", " reflectcube"},
670         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
671         {"#define USEBOUNCEGRID\n", " bouncegrid"},
672         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
673         {"#define USETRIPPY\n", " trippy"},
674 };
675
676 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
677 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
678 {
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
681         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
695 };
696
697 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
698 {
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
715 };
716
717 struct r_glsl_permutation_s;
718 typedef struct r_glsl_permutation_s
719 {
720         /// hash lookup data
721         struct r_glsl_permutation_s *hashnext;
722         unsigned int mode;
723         unsigned int permutation;
724
725         /// indicates if we have tried compiling this permutation already
726         qboolean compiled;
727         /// 0 if compilation failed
728         int program;
729         // texture units assigned to each detected uniform
730         int tex_Texture_First;
731         int tex_Texture_Second;
732         int tex_Texture_GammaRamps;
733         int tex_Texture_Normal;
734         int tex_Texture_Color;
735         int tex_Texture_Gloss;
736         int tex_Texture_Glow;
737         int tex_Texture_SecondaryNormal;
738         int tex_Texture_SecondaryColor;
739         int tex_Texture_SecondaryGloss;
740         int tex_Texture_SecondaryGlow;
741         int tex_Texture_Pants;
742         int tex_Texture_Shirt;
743         int tex_Texture_FogHeightTexture;
744         int tex_Texture_FogMask;
745         int tex_Texture_Lightmap;
746         int tex_Texture_Deluxemap;
747         int tex_Texture_Attenuation;
748         int tex_Texture_Cube;
749         int tex_Texture_Refraction;
750         int tex_Texture_Reflection;
751         int tex_Texture_ShadowMap2D;
752         int tex_Texture_CubeProjection;
753         int tex_Texture_ScreenDepth;
754         int tex_Texture_ScreenNormalMap;
755         int tex_Texture_ScreenDiffuse;
756         int tex_Texture_ScreenSpecular;
757         int tex_Texture_ReflectMask;
758         int tex_Texture_ReflectCube;
759         int tex_Texture_BounceGrid;
760         /// locations of detected uniforms in program object, or -1 if not found
761         int loc_Texture_First;
762         int loc_Texture_Second;
763         int loc_Texture_GammaRamps;
764         int loc_Texture_Normal;
765         int loc_Texture_Color;
766         int loc_Texture_Gloss;
767         int loc_Texture_Glow;
768         int loc_Texture_SecondaryNormal;
769         int loc_Texture_SecondaryColor;
770         int loc_Texture_SecondaryGloss;
771         int loc_Texture_SecondaryGlow;
772         int loc_Texture_Pants;
773         int loc_Texture_Shirt;
774         int loc_Texture_FogHeightTexture;
775         int loc_Texture_FogMask;
776         int loc_Texture_Lightmap;
777         int loc_Texture_Deluxemap;
778         int loc_Texture_Attenuation;
779         int loc_Texture_Cube;
780         int loc_Texture_Refraction;
781         int loc_Texture_Reflection;
782         int loc_Texture_ShadowMap2D;
783         int loc_Texture_CubeProjection;
784         int loc_Texture_ScreenDepth;
785         int loc_Texture_ScreenNormalMap;
786         int loc_Texture_ScreenDiffuse;
787         int loc_Texture_ScreenSpecular;
788         int loc_Texture_ReflectMask;
789         int loc_Texture_ReflectCube;
790         int loc_Texture_BounceGrid;
791         int loc_Alpha;
792         int loc_BloomBlur_Parameters;
793         int loc_ClientTime;
794         int loc_Color_Ambient;
795         int loc_Color_Diffuse;
796         int loc_Color_Specular;
797         int loc_Color_Glow;
798         int loc_Color_Pants;
799         int loc_Color_Shirt;
800         int loc_DeferredColor_Ambient;
801         int loc_DeferredColor_Diffuse;
802         int loc_DeferredColor_Specular;
803         int loc_DeferredMod_Diffuse;
804         int loc_DeferredMod_Specular;
805         int loc_DistortScaleRefractReflect;
806         int loc_EyePosition;
807         int loc_FogColor;
808         int loc_FogHeightFade;
809         int loc_FogPlane;
810         int loc_FogPlaneViewDist;
811         int loc_FogRangeRecip;
812         int loc_LightColor;
813         int loc_LightDir;
814         int loc_LightPosition;
815         int loc_OffsetMapping_ScaleSteps;
816         int loc_PixelSize;
817         int loc_ReflectColor;
818         int loc_ReflectFactor;
819         int loc_ReflectOffset;
820         int loc_RefractColor;
821         int loc_Saturation;
822         int loc_ScreenCenterRefractReflect;
823         int loc_ScreenScaleRefractReflect;
824         int loc_ScreenToDepth;
825         int loc_ShadowMap_Parameters;
826         int loc_ShadowMap_TextureScale;
827         int loc_SpecularPower;
828         int loc_UserVec1;
829         int loc_UserVec2;
830         int loc_UserVec3;
831         int loc_UserVec4;
832         int loc_ViewTintColor;
833         int loc_ViewToLight;
834         int loc_ModelToLight;
835         int loc_TexMatrix;
836         int loc_BackgroundTexMatrix;
837         int loc_ModelViewProjectionMatrix;
838         int loc_ModelViewMatrix;
839         int loc_PixelToScreenTexCoord;
840         int loc_ModelToReflectCube;
841         int loc_ShadowMapMatrix;
842         int loc_BloomColorSubtract;
843         int loc_NormalmapScrollBlend;
844         int loc_BounceGridMatrix;
845         int loc_BounceGridIntensity;
846 }
847 r_glsl_permutation_t;
848
849 #define SHADERPERMUTATION_HASHSIZE 256
850
851
852 // non-degradable "lightweight" shader parameters to keep the permutations simpler
853 // these can NOT degrade! only use for simple stuff
854 enum
855 {
856         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
857         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
858         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
861         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
862         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
863 };
864 #define SHADERSTATICPARMS_COUNT 7
865
866 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
867 static int shaderstaticparms_count = 0;
868
869 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
870 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
871 qboolean R_CompileShader_CheckStaticParms(void)
872 {
873         static int r_compileshader_staticparms_save[1];
874         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
875         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
876
877         // detect all
878         if (r_glsl_saturation_redcompensate.integer)
879                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
880         if (r_glsl_vertextextureblend_usebothalphas.integer)
881                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
882         if (r_shadow_glossexact.integer)
883                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
884         if (r_glsl_postprocess.integer)
885         {
886                 if (r_glsl_postprocess_uservec1_enable.integer)
887                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
888                 if (r_glsl_postprocess_uservec2_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
890                 if (r_glsl_postprocess_uservec3_enable.integer)
891                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
892                 if (r_glsl_postprocess_uservec4_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
894         }
895         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
896 }
897
898 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
899         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
900                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
901         else \
902                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
903 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
904 {
905         shaderstaticparms_count = 0;
906
907         // emit all
908         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
909         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
910         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
911         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
912         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
915 }
916
917 /// information about each possible shader permutation
918 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
919 /// currently selected permutation
920 r_glsl_permutation_t *r_glsl_permutation;
921 /// storage for permutations linked in the hash table
922 memexpandablearray_t r_glsl_permutationarray;
923
924 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
925 {
926         //unsigned int hashdepth = 0;
927         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
928         r_glsl_permutation_t *p;
929         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
930         {
931                 if (p->mode == mode && p->permutation == permutation)
932                 {
933                         //if (hashdepth > 10)
934                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
935                         return p;
936                 }
937                 //hashdepth++;
938         }
939         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
940         p->mode = mode;
941         p->permutation = permutation;
942         p->hashnext = r_glsl_permutationhash[mode][hashindex];
943         r_glsl_permutationhash[mode][hashindex] = p;
944         //if (hashdepth > 10)
945         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
946         return p;
947 }
948
949 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
950 {
951         char *shaderstring;
952         if (!filename || !filename[0])
953                 return NULL;
954         if (!strcmp(filename, "glsl/default.glsl"))
955         {
956                 if (!glslshaderstring)
957                 {
958                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
959                         if (glslshaderstring)
960                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
961                         else
962                                 glslshaderstring = (char *)builtinshaderstring;
963                 }
964                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
965                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
966                 return shaderstring;
967         }
968         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
969         if (shaderstring)
970         {
971                 if (printfromdisknotice)
972                         Con_DPrintf("from disk %s... ", filename);
973                 return shaderstring;
974         }
975         return shaderstring;
976 }
977
978 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
979 {
980         int i;
981         int sampler;
982         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
983         char *vertexstring, *geometrystring, *fragmentstring;
984         char permutationname[256];
985         int vertstrings_count = 0;
986         int geomstrings_count = 0;
987         int fragstrings_count = 0;
988         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
989         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
990         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
991
992         if (p->compiled)
993                 return;
994         p->compiled = true;
995         p->program = 0;
996
997         permutationname[0] = 0;
998         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
999         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1000         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1001
1002         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1003
1004         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1005         if(vid.support.gl20shaders130)
1006         {
1007                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1008                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1009                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1010                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1011                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1012                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1013         }
1014
1015         // the first pretext is which type of shader to compile as
1016         // (later these will all be bound together as a program object)
1017         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1018         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1019         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1020
1021         // the second pretext is the mode (for example a light source)
1022         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1023         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1024         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1025         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1026
1027         // now add all the permutation pretexts
1028         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1029         {
1030                 if (permutation & (1<<i))
1031                 {
1032                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1033                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1034                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1035                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1036                 }
1037                 else
1038                 {
1039                         // keep line numbers correct
1040                         vertstrings_list[vertstrings_count++] = "\n";
1041                         geomstrings_list[geomstrings_count++] = "\n";
1042                         fragstrings_list[fragstrings_count++] = "\n";
1043                 }
1044         }
1045
1046         // add static parms
1047         R_CompileShader_AddStaticParms(mode, permutation);
1048         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1049         vertstrings_count += shaderstaticparms_count;
1050         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1051         geomstrings_count += shaderstaticparms_count;
1052         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1053         fragstrings_count += shaderstaticparms_count;
1054
1055         // now append the shader text itself
1056         vertstrings_list[vertstrings_count++] = vertexstring;
1057         geomstrings_list[geomstrings_count++] = geometrystring;
1058         fragstrings_list[fragstrings_count++] = fragmentstring;
1059
1060         // if any sources were NULL, clear the respective list
1061         if (!vertexstring)
1062                 vertstrings_count = 0;
1063         if (!geometrystring)
1064                 geomstrings_count = 0;
1065         if (!fragmentstring)
1066                 fragstrings_count = 0;
1067
1068         // compile the shader program
1069         if (vertstrings_count + geomstrings_count + fragstrings_count)
1070                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1071         if (p->program)
1072         {
1073                 CHECKGLERROR
1074                 qglUseProgram(p->program);CHECKGLERROR
1075                 // look up all the uniform variable names we care about, so we don't
1076                 // have to look them up every time we set them
1077
1078                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1079                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1080                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1081                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1082                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1083                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1084                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1085                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1086                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1087                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1088                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1089                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1090                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1091                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1092                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1093                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1094                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1095                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1096                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1097                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1098                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1099                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1100                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1101                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1102                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1103                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1104                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1105                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1106                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1107                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1108                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1109                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1110                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1111                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1112                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1113                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1114                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1115                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1116                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1117                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1118                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1119                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1120                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1121                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1122                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1123                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1124                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1125                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1126                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1127                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1128                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1129                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1130                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1131                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1132                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1133                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1134                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1135                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1136                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1137                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1138                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1139                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1140                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1141                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1142                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1143                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1144                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1145                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1146                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1147                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1148                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1149                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1150                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1151                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1152                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1153                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1154                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1155                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1156                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1157                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1158                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1159                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1160                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1161                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1162                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1163                 // initialize the samplers to refer to the texture units we use
1164                 p->tex_Texture_First = -1;
1165                 p->tex_Texture_Second = -1;
1166                 p->tex_Texture_GammaRamps = -1;
1167                 p->tex_Texture_Normal = -1;
1168                 p->tex_Texture_Color = -1;
1169                 p->tex_Texture_Gloss = -1;
1170                 p->tex_Texture_Glow = -1;
1171                 p->tex_Texture_SecondaryNormal = -1;
1172                 p->tex_Texture_SecondaryColor = -1;
1173                 p->tex_Texture_SecondaryGloss = -1;
1174                 p->tex_Texture_SecondaryGlow = -1;
1175                 p->tex_Texture_Pants = -1;
1176                 p->tex_Texture_Shirt = -1;
1177                 p->tex_Texture_FogHeightTexture = -1;
1178                 p->tex_Texture_FogMask = -1;
1179                 p->tex_Texture_Lightmap = -1;
1180                 p->tex_Texture_Deluxemap = -1;
1181                 p->tex_Texture_Attenuation = -1;
1182                 p->tex_Texture_Cube = -1;
1183                 p->tex_Texture_Refraction = -1;
1184                 p->tex_Texture_Reflection = -1;
1185                 p->tex_Texture_ShadowMap2D = -1;
1186                 p->tex_Texture_CubeProjection = -1;
1187                 p->tex_Texture_ScreenDepth = -1;
1188                 p->tex_Texture_ScreenNormalMap = -1;
1189                 p->tex_Texture_ScreenDiffuse = -1;
1190                 p->tex_Texture_ScreenSpecular = -1;
1191                 p->tex_Texture_ReflectMask = -1;
1192                 p->tex_Texture_ReflectCube = -1;
1193                 p->tex_Texture_BounceGrid = -1;
1194                 sampler = 0;
1195                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1196                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1197                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1198                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1199                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1200                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1201                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1202                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1203                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1204                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1205                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1206                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1207                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1208                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1209                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1210                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1211                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1212                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1213                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1214                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1215                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1216                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1217                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1218                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1219                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1220                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1221                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1222                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1223                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1224                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1225                 CHECKGLERROR
1226                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1227         }
1228         else
1229                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1230
1231         // free the strings
1232         if (vertexstring)
1233                 Mem_Free(vertexstring);
1234         if (geometrystring)
1235                 Mem_Free(geometrystring);
1236         if (fragmentstring)
1237                 Mem_Free(fragmentstring);
1238 }
1239
1240 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1241 {
1242         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1243         if (r_glsl_permutation != perm)
1244         {
1245                 r_glsl_permutation = perm;
1246                 if (!r_glsl_permutation->program)
1247                 {
1248                         if (!r_glsl_permutation->compiled)
1249                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1250                         if (!r_glsl_permutation->program)
1251                         {
1252                                 // remove features until we find a valid permutation
1253                                 int i;
1254                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1255                                 {
1256                                         // reduce i more quickly whenever it would not remove any bits
1257                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1258                                         if (!(permutation & j))
1259                                                 continue;
1260                                         permutation -= j;
1261                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1262                                         if (!r_glsl_permutation->compiled)
1263                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1264                                         if (r_glsl_permutation->program)
1265                                                 break;
1266                                 }
1267                                 if (i >= SHADERPERMUTATION_COUNT)
1268                                 {
1269                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1270                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1271                                         qglUseProgram(0);CHECKGLERROR
1272                                         return; // no bit left to clear, entire mode is broken
1273                                 }
1274                         }
1275                 }
1276                 CHECKGLERROR
1277                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1278         }
1279         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1280         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1281         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1282 }
1283
1284 #ifdef SUPPORTD3D
1285
1286 #ifdef SUPPORTD3D
1287 #include <d3d9.h>
1288 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1289 extern D3DCAPS9 vid_d3d9caps;
1290 #endif
1291
1292 struct r_hlsl_permutation_s;
1293 typedef struct r_hlsl_permutation_s
1294 {
1295         /// hash lookup data
1296         struct r_hlsl_permutation_s *hashnext;
1297         unsigned int mode;
1298         unsigned int permutation;
1299
1300         /// indicates if we have tried compiling this permutation already
1301         qboolean compiled;
1302         /// NULL if compilation failed
1303         IDirect3DVertexShader9 *vertexshader;
1304         IDirect3DPixelShader9 *pixelshader;
1305 }
1306 r_hlsl_permutation_t;
1307
1308 typedef enum D3DVSREGISTER_e
1309 {
1310         D3DVSREGISTER_TexMatrix = 0, // float4x4
1311         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1312         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1313         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1314         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1315         D3DVSREGISTER_ModelToLight = 20, // float4x4
1316         D3DVSREGISTER_EyePosition = 24,
1317         D3DVSREGISTER_FogPlane = 25,
1318         D3DVSREGISTER_LightDir = 26,
1319         D3DVSREGISTER_LightPosition = 27,
1320 }
1321 D3DVSREGISTER_t;
1322
1323 typedef enum D3DPSREGISTER_e
1324 {
1325         D3DPSREGISTER_Alpha = 0,
1326         D3DPSREGISTER_BloomBlur_Parameters = 1,
1327         D3DPSREGISTER_ClientTime = 2,
1328         D3DPSREGISTER_Color_Ambient = 3,
1329         D3DPSREGISTER_Color_Diffuse = 4,
1330         D3DPSREGISTER_Color_Specular = 5,
1331         D3DPSREGISTER_Color_Glow = 6,
1332         D3DPSREGISTER_Color_Pants = 7,
1333         D3DPSREGISTER_Color_Shirt = 8,
1334         D3DPSREGISTER_DeferredColor_Ambient = 9,
1335         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1336         D3DPSREGISTER_DeferredColor_Specular = 11,
1337         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1338         D3DPSREGISTER_DeferredMod_Specular = 13,
1339         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1340         D3DPSREGISTER_EyePosition = 15, // unused
1341         D3DPSREGISTER_FogColor = 16,
1342         D3DPSREGISTER_FogHeightFade = 17,
1343         D3DPSREGISTER_FogPlane = 18,
1344         D3DPSREGISTER_FogPlaneViewDist = 19,
1345         D3DPSREGISTER_FogRangeRecip = 20,
1346         D3DPSREGISTER_LightColor = 21,
1347         D3DPSREGISTER_LightDir = 22, // unused
1348         D3DPSREGISTER_LightPosition = 23,
1349         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1350         D3DPSREGISTER_PixelSize = 25,
1351         D3DPSREGISTER_ReflectColor = 26,
1352         D3DPSREGISTER_ReflectFactor = 27,
1353         D3DPSREGISTER_ReflectOffset = 28,
1354         D3DPSREGISTER_RefractColor = 29,
1355         D3DPSREGISTER_Saturation = 30,
1356         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1357         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1358         D3DPSREGISTER_ScreenToDepth = 33,
1359         D3DPSREGISTER_ShadowMap_Parameters = 34,
1360         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1361         D3DPSREGISTER_SpecularPower = 36,
1362         D3DPSREGISTER_UserVec1 = 37,
1363         D3DPSREGISTER_UserVec2 = 38,
1364         D3DPSREGISTER_UserVec3 = 39,
1365         D3DPSREGISTER_UserVec4 = 40,
1366         D3DPSREGISTER_ViewTintColor = 41,
1367         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1368         D3DPSREGISTER_BloomColorSubtract = 43,
1369         D3DPSREGISTER_ViewToLight = 44, // float4x4
1370         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1371         D3DPSREGISTER_NormalmapScrollBlend = 52,
1372         // next at 53
1373 }
1374 D3DPSREGISTER_t;
1375
1376 /// information about each possible shader permutation
1377 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1378 /// currently selected permutation
1379 r_hlsl_permutation_t *r_hlsl_permutation;
1380 /// storage for permutations linked in the hash table
1381 memexpandablearray_t r_hlsl_permutationarray;
1382
1383 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1384 {
1385         //unsigned int hashdepth = 0;
1386         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1387         r_hlsl_permutation_t *p;
1388         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1389         {
1390                 if (p->mode == mode && p->permutation == permutation)
1391                 {
1392                         //if (hashdepth > 10)
1393                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1394                         return p;
1395                 }
1396                 //hashdepth++;
1397         }
1398         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1399         p->mode = mode;
1400         p->permutation = permutation;
1401         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1402         r_hlsl_permutationhash[mode][hashindex] = p;
1403         //if (hashdepth > 10)
1404         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1405         return p;
1406 }
1407
1408 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1409 {
1410         char *shaderstring;
1411         if (!filename || !filename[0])
1412                 return NULL;
1413         if (!strcmp(filename, "hlsl/default.hlsl"))
1414         {
1415                 if (!hlslshaderstring)
1416                 {
1417                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1418                         if (hlslshaderstring)
1419                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1420                         else
1421                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1422                 }
1423                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1424                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1425                 return shaderstring;
1426         }
1427         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1428         if (shaderstring)
1429         {
1430                 if (printfromdisknotice)
1431                         Con_DPrintf("from disk %s... ", filename);
1432                 return shaderstring;
1433         }
1434         return shaderstring;
1435 }
1436
1437 #include <d3dx9.h>
1438 //#include <d3dx9shader.h>
1439 //#include <d3dx9mesh.h>
1440
1441 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1442 {
1443         DWORD *vsbin = NULL;
1444         DWORD *psbin = NULL;
1445         fs_offset_t vsbinsize;
1446         fs_offset_t psbinsize;
1447 //      IDirect3DVertexShader9 *vs = NULL;
1448 //      IDirect3DPixelShader9 *ps = NULL;
1449         ID3DXBuffer *vslog = NULL;
1450         ID3DXBuffer *vsbuffer = NULL;
1451         ID3DXConstantTable *vsconstanttable = NULL;
1452         ID3DXBuffer *pslog = NULL;
1453         ID3DXBuffer *psbuffer = NULL;
1454         ID3DXConstantTable *psconstanttable = NULL;
1455         int vsresult = 0;
1456         int psresult = 0;
1457         char temp[MAX_INPUTLINE];
1458         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1459         qboolean debugshader = gl_paranoid.integer != 0;
1460         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1461         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1462         if (!debugshader)
1463         {
1464                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1465                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1466         }
1467         if ((!vsbin && vertstring) || (!psbin && fragstring))
1468         {
1469                 const char* dllnames_d3dx9 [] =
1470                 {
1471                         "d3dx9_43.dll",
1472                         "d3dx9_42.dll",
1473                         "d3dx9_41.dll",
1474                         "d3dx9_40.dll",
1475                         "d3dx9_39.dll",
1476                         "d3dx9_38.dll",
1477                         "d3dx9_37.dll",
1478                         "d3dx9_36.dll",
1479                         "d3dx9_35.dll",
1480                         "d3dx9_34.dll",
1481                         "d3dx9_33.dll",
1482                         "d3dx9_32.dll",
1483                         "d3dx9_31.dll",
1484                         "d3dx9_30.dll",
1485                         "d3dx9_29.dll",
1486                         "d3dx9_28.dll",
1487                         "d3dx9_27.dll",
1488                         "d3dx9_26.dll",
1489                         "d3dx9_25.dll",
1490                         "d3dx9_24.dll",
1491                         NULL
1492                 };
1493                 dllhandle_t d3dx9_dll = NULL;
1494                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1495                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1496                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1497                 dllfunction_t d3dx9_dllfuncs[] =
1498                 {
1499                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1500                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1501                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1502                         {NULL, NULL}
1503                 };
1504                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1505                 {
1506                         DWORD shaderflags = 0;
1507                         if (debugshader)
1508                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1509                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1510                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1511                         if (vertstring && vertstring[0])
1512                         {
1513                                 if (debugshader)
1514                                 {
1515 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1516 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1517                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1518                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1519                                 }
1520                                 else
1521                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1522                                 if (vsbuffer)
1523                                 {
1524                                         vsbinsize = vsbuffer->GetBufferSize();
1525                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1526                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1527                                         vsbuffer->Release();
1528                                 }
1529                                 if (vslog)
1530                                 {
1531                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1532                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1533                                         vslog->Release();
1534                                 }
1535                         }
1536                         if (fragstring && fragstring[0])
1537                         {
1538                                 if (debugshader)
1539                                 {
1540 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1541 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1542                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1543                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1544                                 }
1545                                 else
1546                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1547                                 if (psbuffer)
1548                                 {
1549                                         psbinsize = psbuffer->GetBufferSize();
1550                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1551                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1552                                         psbuffer->Release();
1553                                 }
1554                                 if (pslog)
1555                                 {
1556                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1557                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1558                                         pslog->Release();
1559                                 }
1560                         }
1561                         Sys_UnloadLibrary(&d3dx9_dll);
1562                 }
1563                 else
1564                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1565         }
1566         if (vsbin && psbin)
1567         {
1568                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1569                 if (FAILED(vsresult))
1570                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1571                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1572                 if (FAILED(psresult))
1573                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1574         }
1575         // free the shader data
1576         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1577         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1578 }
1579
1580 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1581 {
1582         int i;
1583         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1584         int vertstring_length = 0;
1585         int geomstring_length = 0;
1586         int fragstring_length = 0;
1587         char *t;
1588         char *vertexstring, *geometrystring, *fragmentstring;
1589         char *vertstring, *geomstring, *fragstring;
1590         char permutationname[256];
1591         char cachename[256];
1592         int vertstrings_count = 0;
1593         int geomstrings_count = 0;
1594         int fragstrings_count = 0;
1595         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1596         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1597         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1598
1599         if (p->compiled)
1600                 return;
1601         p->compiled = true;
1602         p->vertexshader = NULL;
1603         p->pixelshader = NULL;
1604
1605         permutationname[0] = 0;
1606         cachename[0] = 0;
1607         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1608         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1609         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1610
1611         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1612         strlcat(cachename, "hlsl/", sizeof(cachename));
1613
1614         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1615         vertstrings_count = 0;
1616         geomstrings_count = 0;
1617         fragstrings_count = 0;
1618         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1619         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1620         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1621
1622         // the first pretext is which type of shader to compile as
1623         // (later these will all be bound together as a program object)
1624         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1625         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1626         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1627
1628         // the second pretext is the mode (for example a light source)
1629         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1630         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1631         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1632         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1633         strlcat(cachename, modeinfo->name, sizeof(cachename));
1634
1635         // now add all the permutation pretexts
1636         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1637         {
1638                 if (permutation & (1<<i))
1639                 {
1640                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1641                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1642                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1643                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1644                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1645                 }
1646                 else
1647                 {
1648                         // keep line numbers correct
1649                         vertstrings_list[vertstrings_count++] = "\n";
1650                         geomstrings_list[geomstrings_count++] = "\n";
1651                         fragstrings_list[fragstrings_count++] = "\n";
1652                 }
1653         }
1654
1655         // add static parms
1656         R_CompileShader_AddStaticParms(mode, permutation);
1657         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1658         vertstrings_count += shaderstaticparms_count;
1659         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1660         geomstrings_count += shaderstaticparms_count;
1661         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1662         fragstrings_count += shaderstaticparms_count;
1663
1664         // replace spaces in the cachename with _ characters
1665         for (i = 0;cachename[i];i++)
1666                 if (cachename[i] == ' ')
1667                         cachename[i] = '_';
1668
1669         // now append the shader text itself
1670         vertstrings_list[vertstrings_count++] = vertexstring;
1671         geomstrings_list[geomstrings_count++] = geometrystring;
1672         fragstrings_list[fragstrings_count++] = fragmentstring;
1673
1674         // if any sources were NULL, clear the respective list
1675         if (!vertexstring)
1676                 vertstrings_count = 0;
1677         if (!geometrystring)
1678                 geomstrings_count = 0;
1679         if (!fragmentstring)
1680                 fragstrings_count = 0;
1681
1682         vertstring_length = 0;
1683         for (i = 0;i < vertstrings_count;i++)
1684                 vertstring_length += strlen(vertstrings_list[i]);
1685         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1686         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1687                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1688
1689         geomstring_length = 0;
1690         for (i = 0;i < geomstrings_count;i++)
1691                 geomstring_length += strlen(geomstrings_list[i]);
1692         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1693         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1694                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1695
1696         fragstring_length = 0;
1697         for (i = 0;i < fragstrings_count;i++)
1698                 fragstring_length += strlen(fragstrings_list[i]);
1699         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1700         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1701                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1702
1703         // try to load the cached shader, or generate one
1704         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1705
1706         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1707                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1708         else
1709                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1710
1711         // free the strings
1712         if (vertstring)
1713                 Mem_Free(vertstring);
1714         if (geomstring)
1715                 Mem_Free(geomstring);
1716         if (fragstring)
1717                 Mem_Free(fragstring);
1718         if (vertexstring)
1719                 Mem_Free(vertexstring);
1720         if (geometrystring)
1721                 Mem_Free(geometrystring);
1722         if (fragmentstring)
1723                 Mem_Free(fragmentstring);
1724 }
1725
1726 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1727 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1728 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1729 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1730 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1731 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1732
1733 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1734 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1735 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1737 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1738 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1739
1740 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1741 {
1742         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1743         if (r_hlsl_permutation != perm)
1744         {
1745                 r_hlsl_permutation = perm;
1746                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1747                 {
1748                         if (!r_hlsl_permutation->compiled)
1749                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1750                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1751                         {
1752                                 // remove features until we find a valid permutation
1753                                 int i;
1754                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1755                                 {
1756                                         // reduce i more quickly whenever it would not remove any bits
1757                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1758                                         if (!(permutation & j))
1759                                                 continue;
1760                                         permutation -= j;
1761                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1762                                         if (!r_hlsl_permutation->compiled)
1763                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1764                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1765                                                 break;
1766                                 }
1767                                 if (i >= SHADERPERMUTATION_COUNT)
1768                                 {
1769                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1770                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1771                                         return; // no bit left to clear, entire mode is broken
1772                                 }
1773                         }
1774                 }
1775                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1776                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1777         }
1778         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1779         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1780         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1781 }
1782 #endif
1783
1784 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1785 {
1786         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1787         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1788         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1789         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1790 }
1791
1792 void R_GLSL_Restart_f(void)
1793 {
1794         unsigned int i, limit;
1795         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1796                 Mem_Free(glslshaderstring);
1797         glslshaderstring = NULL;
1798         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1799                 Mem_Free(hlslshaderstring);
1800         hlslshaderstring = NULL;
1801         switch(vid.renderpath)
1802         {
1803         case RENDERPATH_D3D9:
1804 #ifdef SUPPORTD3D
1805                 {
1806                         r_hlsl_permutation_t *p;
1807                         r_hlsl_permutation = NULL;
1808                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1809                         for (i = 0;i < limit;i++)
1810                         {
1811                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1812                                 {
1813                                         if (p->vertexshader)
1814                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1815                                         if (p->pixelshader)
1816                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1817                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1818                                 }
1819                         }
1820                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1821                 }
1822 #endif
1823                 break;
1824         case RENDERPATH_D3D10:
1825                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1826                 break;
1827         case RENDERPATH_D3D11:
1828                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1829                 break;
1830         case RENDERPATH_GL20:
1831         case RENDERPATH_GLES2:
1832                 {
1833                         r_glsl_permutation_t *p;
1834                         r_glsl_permutation = NULL;
1835                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1836                         for (i = 0;i < limit;i++)
1837                         {
1838                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1839                                 {
1840                                         GL_Backend_FreeProgram(p->program);
1841                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1842                                 }
1843                         }
1844                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1845                 }
1846                 break;
1847         case RENDERPATH_GL11:
1848         case RENDERPATH_GL13:
1849         case RENDERPATH_GLES1:
1850                 break;
1851         case RENDERPATH_SOFT:
1852                 break;
1853         }
1854 }
1855
1856 void R_GLSL_DumpShader_f(void)
1857 {
1858         int i;
1859         qfile_t *file;
1860
1861         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1862         if (file)
1863         {
1864                 FS_Print(file, "/* The engine may define the following macros:\n");
1865                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1866                 for (i = 0;i < SHADERMODE_COUNT;i++)
1867                         FS_Print(file, glslshadermodeinfo[i].pretext);
1868                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1869                         FS_Print(file, shaderpermutationinfo[i].pretext);
1870                 FS_Print(file, "*/\n");
1871                 FS_Print(file, builtinshaderstring);
1872                 FS_Close(file);
1873                 Con_Printf("glsl/default.glsl written\n");
1874         }
1875         else
1876                 Con_Printf("failed to write to glsl/default.glsl\n");
1877
1878         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1879         if (file)
1880         {
1881                 FS_Print(file, "/* The engine may define the following macros:\n");
1882                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1883                 for (i = 0;i < SHADERMODE_COUNT;i++)
1884                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1885                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1886                         FS_Print(file, shaderpermutationinfo[i].pretext);
1887                 FS_Print(file, "*/\n");
1888                 FS_Print(file, builtinhlslshaderstring);
1889                 FS_Close(file);
1890                 Con_Printf("hlsl/default.hlsl written\n");
1891         }
1892         else
1893                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1894 }
1895
1896 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy)
1897 {
1898         unsigned int permutation = 0;
1899         if (r_trippy.integer && !notrippy)
1900                 permutation |= SHADERPERMUTATION_TRIPPY;
1901         permutation |= SHADERPERMUTATION_VIEWTINT;
1902         if (first)
1903                 permutation |= SHADERPERMUTATION_DIFFUSE;
1904         if (second)
1905                 permutation |= SHADERPERMUTATION_SPECULAR;
1906         if (texturemode == GL_MODULATE)
1907                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1908         else if (texturemode == GL_ADD)
1909                 permutation |= SHADERPERMUTATION_GLOW;
1910         else if (texturemode == GL_DECAL)
1911                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1912         if (!second)
1913                 texturemode = GL_MODULATE;
1914         if (vid.allowalphatocoverage)
1915                 GL_AlphaToCoverage(false);
1916         switch (vid.renderpath)
1917         {
1918         case RENDERPATH_D3D9:
1919 #ifdef SUPPORTD3D
1920                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1921                 R_Mesh_TexBind(GL20TU_FIRST , first );
1922                 R_Mesh_TexBind(GL20TU_SECOND, second);
1923 #endif
1924                 break;
1925         case RENDERPATH_D3D10:
1926                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1927                 break;
1928         case RENDERPATH_D3D11:
1929                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1930                 break;
1931         case RENDERPATH_GL20:
1932         case RENDERPATH_GLES2:
1933                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1934                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1935                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1936                 break;
1937         case RENDERPATH_GL13:
1938         case RENDERPATH_GLES1:
1939                 R_Mesh_TexBind(0, first );
1940                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1941                 R_Mesh_TexBind(1, second);
1942                 if (second)
1943                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1944                 break;
1945         case RENDERPATH_GL11:
1946                 R_Mesh_TexBind(0, first );
1947                 break;
1948         case RENDERPATH_SOFT:
1949                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1950                 R_Mesh_TexBind(GL20TU_FIRST , first );
1951                 R_Mesh_TexBind(GL20TU_SECOND, second);
1952                 break;
1953         }
1954 }
1955
1956 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1957 {
1958         unsigned int permutation = 0;
1959         if (r_trippy.integer && !notrippy)
1960                 permutation |= SHADERPERMUTATION_TRIPPY;
1961         if (vid.allowalphatocoverage)
1962                 GL_AlphaToCoverage(false);
1963         switch (vid.renderpath)
1964         {
1965         case RENDERPATH_D3D9:
1966 #ifdef SUPPORTD3D
1967                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1968 #endif
1969                 break;
1970         case RENDERPATH_D3D10:
1971                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1972                 break;
1973         case RENDERPATH_D3D11:
1974                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1975                 break;
1976         case RENDERPATH_GL20:
1977         case RENDERPATH_GLES2:
1978                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1979                 break;
1980         case RENDERPATH_GL13:
1981         case RENDERPATH_GLES1:
1982                 R_Mesh_TexBind(0, 0);
1983                 R_Mesh_TexBind(1, 0);
1984                 break;
1985         case RENDERPATH_GL11:
1986                 R_Mesh_TexBind(0, 0);
1987                 break;
1988         case RENDERPATH_SOFT:
1989                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1990                 break;
1991         }
1992 }
1993
1994 void R_SetupShader_ShowDepth(qboolean notrippy)
1995 {
1996         int permutation = 0;
1997         if (r_trippy.integer && !notrippy)
1998                 permutation |= SHADERPERMUTATION_TRIPPY;
1999         if (r_trippy.integer)
2000                 permutation |= SHADERPERMUTATION_TRIPPY;
2001         if (vid.allowalphatocoverage)
2002                 GL_AlphaToCoverage(false);
2003         switch (vid.renderpath)
2004         {
2005         case RENDERPATH_D3D9:
2006 #ifdef SUPPORTHLSL
2007                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2008 #endif
2009                 break;
2010         case RENDERPATH_D3D10:
2011                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2012                 break;
2013         case RENDERPATH_D3D11:
2014                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2015                 break;
2016         case RENDERPATH_GL20:
2017         case RENDERPATH_GLES2:
2018                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2019                 break;
2020         case RENDERPATH_GL13:
2021         case RENDERPATH_GLES1:
2022                 break;
2023         case RENDERPATH_GL11:
2024                 break;
2025         case RENDERPATH_SOFT:
2026                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2027                 break;
2028         }
2029 }
2030
2031 extern qboolean r_shadow_usingdeferredprepass;
2032 extern cvar_t r_shadow_deferred_8bitrange;
2033 extern rtexture_t *r_shadow_attenuationgradienttexture;
2034 extern rtexture_t *r_shadow_attenuation2dtexture;
2035 extern rtexture_t *r_shadow_attenuation3dtexture;
2036 extern qboolean r_shadow_usingshadowmap2d;
2037 extern qboolean r_shadow_usingshadowmaportho;
2038 extern float r_shadow_shadowmap_texturescale[2];
2039 extern float r_shadow_shadowmap_parameters[4];
2040 extern qboolean r_shadow_shadowmapvsdct;
2041 extern qboolean r_shadow_shadowmapsampler;
2042 extern int r_shadow_shadowmappcf;
2043 extern rtexture_t *r_shadow_shadowmap2dtexture;
2044 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2045 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2046 extern matrix4x4_t r_shadow_shadowmapmatrix;
2047 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2048 extern int r_shadow_prepass_width;
2049 extern int r_shadow_prepass_height;
2050 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2051 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2052 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2053 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2054 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2055
2056 #define BLENDFUNC_ALLOWS_COLORMOD      1
2057 #define BLENDFUNC_ALLOWS_FOG           2
2058 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2059 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2060 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2061 static int R_BlendFuncFlags(int src, int dst)
2062 {
2063         int r = 0;
2064
2065         // a blendfunc allows colormod if:
2066         // a) it can never keep the destination pixel invariant, or
2067         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2068         // this is to prevent unintended side effects from colormod
2069
2070         // a blendfunc allows fog if:
2071         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2072         // this is to prevent unintended side effects from fog
2073
2074         // these checks are the output of fogeval.pl
2075
2076         r |= BLENDFUNC_ALLOWS_COLORMOD;
2077         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2078         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2079         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2080         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2081         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2082         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2084         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2085         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2086         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2087         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2088         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2089         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2090         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2091         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2092         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2093         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2095         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098
2099         return r;
2100 }
2101
2102 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2103 {
2104         // select a permutation of the lighting shader appropriate to this
2105         // combination of texture, entity, light source, and fogging, only use the
2106         // minimum features necessary to avoid wasting rendering time in the
2107         // fragment shader on features that are not being used
2108         unsigned int permutation = 0;
2109         unsigned int mode = 0;
2110         int blendfuncflags;
2111         static float dummy_colormod[3] = {1, 1, 1};
2112         float *colormod = rsurface.colormod;
2113         float m16f[16];
2114         matrix4x4_t tempmatrix;
2115         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2116         if (r_trippy.integer && !notrippy)
2117                 permutation |= SHADERPERMUTATION_TRIPPY;
2118         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2119                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2120         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2121                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2122         if (rsurfacepass == RSURFPASS_BACKGROUND)
2123         {
2124                 // distorted background
2125                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2126                 {
2127                         mode = SHADERMODE_WATER;
2128                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2129                         {
2130                                 // this is the right thing to do for wateralpha
2131                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2132                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2133                         }
2134                         else
2135                         {
2136                                 // this is the right thing to do for entity alpha
2137                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2138                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2139                         }
2140                 }
2141                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2142                 {
2143                         mode = SHADERMODE_REFRACTION;
2144                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2145                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                 }
2147                 else
2148                 {
2149                         mode = SHADERMODE_GENERIC;
2150                         permutation |= SHADERPERMUTATION_DIFFUSE;
2151                         GL_BlendFunc(GL_ONE, GL_ZERO);
2152                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2153                 }
2154                 if (vid.allowalphatocoverage)
2155                         GL_AlphaToCoverage(false);
2156         }
2157         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2158         {
2159                 if (r_glsl_offsetmapping.integer)
2160                 {
2161                         switch(rsurface.texture->offsetmapping)
2162                         {
2163                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2164                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2165                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2166                         case OFFSETMAPPING_OFF: break;
2167                         }
2168                 }
2169                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2170                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2171                 // normalmap (deferred prepass), may use alpha test on diffuse
2172                 mode = SHADERMODE_DEFERREDGEOMETRY;
2173                 GL_BlendFunc(GL_ONE, GL_ZERO);
2174                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2175                 if (vid.allowalphatocoverage)
2176                         GL_AlphaToCoverage(false);
2177         }
2178         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2179         {
2180                 if (r_glsl_offsetmapping.integer)
2181                 {
2182                         switch(rsurface.texture->offsetmapping)
2183                         {
2184                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2185                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2186                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2187                         case OFFSETMAPPING_OFF: break;
2188                         }
2189                 }
2190                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2191                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2192                 // light source
2193                 mode = SHADERMODE_LIGHTSOURCE;
2194                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2195                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2196                 if (diffusescale > 0)
2197                         permutation |= SHADERPERMUTATION_DIFFUSE;
2198                 if (specularscale > 0)
2199                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2200                 if (r_refdef.fogenabled)
2201                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2202                 if (rsurface.texture->colormapping)
2203                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2204                 if (r_shadow_usingshadowmap2d)
2205                 {
2206                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2207                         if(r_shadow_shadowmapvsdct)
2208                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2209
2210                         if (r_shadow_shadowmapsampler)
2211                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2212                         if (r_shadow_shadowmappcf > 1)
2213                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2214                         else if (r_shadow_shadowmappcf)
2215                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2216                 }
2217                 if (rsurface.texture->reflectmasktexture)
2218                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2219                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2220                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2221                 if (vid.allowalphatocoverage)
2222                         GL_AlphaToCoverage(false);
2223         }
2224         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2225         {
2226                 if (r_glsl_offsetmapping.integer)
2227                 {
2228                         switch(rsurface.texture->offsetmapping)
2229                         {
2230                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2231                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2232                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2233                         case OFFSETMAPPING_OFF: break;
2234                         }
2235                 }
2236                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2237                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2238                 // unshaded geometry (fullbright or ambient model lighting)
2239                 mode = SHADERMODE_FLATCOLOR;
2240                 ambientscale = diffusescale = specularscale = 0;
2241                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2242                         permutation |= SHADERPERMUTATION_GLOW;
2243                 if (r_refdef.fogenabled)
2244                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2245                 if (rsurface.texture->colormapping)
2246                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2247                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2248                 {
2249                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2250                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2251
2252                         if (r_shadow_shadowmapsampler)
2253                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2254                         if (r_shadow_shadowmappcf > 1)
2255                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2256                         else if (r_shadow_shadowmappcf)
2257                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2258                 }
2259                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2260                         permutation |= SHADERPERMUTATION_REFLECTION;
2261                 if (rsurface.texture->reflectmasktexture)
2262                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2263                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2264                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2265                 // when using alphatocoverage, we don't need alphakill
2266                 if (vid.allowalphatocoverage)
2267                 {
2268                         if (r_transparent_alphatocoverage.integer)
2269                         {
2270                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2271                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2272                         }
2273                         else
2274                                 GL_AlphaToCoverage(false);
2275                 }
2276         }
2277         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2278         {
2279                 if (r_glsl_offsetmapping.integer)
2280                 {
2281                         switch(rsurface.texture->offsetmapping)
2282                         {
2283                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2284                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2285                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_OFF: break;
2287                         }
2288                 }
2289                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2290                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2291                 // directional model lighting
2292                 mode = SHADERMODE_LIGHTDIRECTION;
2293                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2294                         permutation |= SHADERPERMUTATION_GLOW;
2295                 permutation |= SHADERPERMUTATION_DIFFUSE;
2296                 if (specularscale > 0)
2297                         permutation |= SHADERPERMUTATION_SPECULAR;
2298                 if (r_refdef.fogenabled)
2299                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2300                 if (rsurface.texture->colormapping)
2301                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2302                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2303                 {
2304                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2305                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2306
2307                         if (r_shadow_shadowmapsampler)
2308                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2309                         if (r_shadow_shadowmappcf > 1)
2310                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2311                         else if (r_shadow_shadowmappcf)
2312                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2313                 }
2314                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2315                         permutation |= SHADERPERMUTATION_REFLECTION;
2316                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2317                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2318                 if (rsurface.texture->reflectmasktexture)
2319                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2320                 if (r_shadow_bouncegridtexture)
2321                 {
2322                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2323                         if (r_shadow_bouncegriddirectional)
2324                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2325                 }
2326                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2327                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2328                 // when using alphatocoverage, we don't need alphakill
2329                 if (vid.allowalphatocoverage)
2330                 {
2331                         if (r_transparent_alphatocoverage.integer)
2332                         {
2333                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2334                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2335                         }
2336                         else
2337                                 GL_AlphaToCoverage(false);
2338                 }
2339         }
2340         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2341         {
2342                 if (r_glsl_offsetmapping.integer)
2343                 {
2344                         switch(rsurface.texture->offsetmapping)
2345                         {
2346                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2347                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2348                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_OFF: break;
2350                         }
2351                 }
2352                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2353                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2354                 // ambient model lighting
2355                 mode = SHADERMODE_LIGHTDIRECTION;
2356                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2357                         permutation |= SHADERPERMUTATION_GLOW;
2358                 if (r_refdef.fogenabled)
2359                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2360                 if (rsurface.texture->colormapping)
2361                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2362                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2363                 {
2364                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2365                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2366
2367                         if (r_shadow_shadowmapsampler)
2368                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2369                         if (r_shadow_shadowmappcf > 1)
2370                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2371                         else if (r_shadow_shadowmappcf)
2372                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2373                 }
2374                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2375                         permutation |= SHADERPERMUTATION_REFLECTION;
2376                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2377                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2378                 if (rsurface.texture->reflectmasktexture)
2379                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2380                 if (r_shadow_bouncegridtexture)
2381                 {
2382                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2383                         if (r_shadow_bouncegriddirectional)
2384                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2385                 }
2386                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2387                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2388                 // when using alphatocoverage, we don't need alphakill
2389                 if (vid.allowalphatocoverage)
2390                 {
2391                         if (r_transparent_alphatocoverage.integer)
2392                         {
2393                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2394                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2395                         }
2396                         else
2397                                 GL_AlphaToCoverage(false);
2398                 }
2399         }
2400         else
2401         {
2402                 if (r_glsl_offsetmapping.integer)
2403                 {
2404                         switch(rsurface.texture->offsetmapping)
2405                         {
2406                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2407                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2408                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409                         case OFFSETMAPPING_OFF: break;
2410                         }
2411                 }
2412                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2413                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2414                 // lightmapped wall
2415                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2416                         permutation |= SHADERPERMUTATION_GLOW;
2417                 if (r_refdef.fogenabled)
2418                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2419                 if (rsurface.texture->colormapping)
2420                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2421                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2422                 {
2423                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2424                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2425
2426                         if (r_shadow_shadowmapsampler)
2427                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2428                         if (r_shadow_shadowmappcf > 1)
2429                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2430                         else if (r_shadow_shadowmappcf)
2431                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2432                 }
2433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2434                         permutation |= SHADERPERMUTATION_REFLECTION;
2435                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2436                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2437                 if (rsurface.texture->reflectmasktexture)
2438                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2439                 if (FAKELIGHT_ENABLED)
2440                 {
2441                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2442                         mode = SHADERMODE_FAKELIGHT;
2443                         permutation |= SHADERPERMUTATION_DIFFUSE;
2444                         if (specularscale > 0)
2445                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2446                 }
2447                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2448                 {
2449                         // deluxemapping (light direction texture)
2450                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2451                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2452                         else
2453                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2454                         permutation |= SHADERPERMUTATION_DIFFUSE;
2455                         if (specularscale > 0)
2456                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2457                 }
2458                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2459                 {
2460                         // fake deluxemapping (uniform light direction in tangentspace)
2461                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2462                         permutation |= SHADERPERMUTATION_DIFFUSE;
2463                         if (specularscale > 0)
2464                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2465                 }
2466                 else if (rsurface.uselightmaptexture)
2467                 {
2468                         // ordinary lightmapping (q1bsp, q3bsp)
2469                         mode = SHADERMODE_LIGHTMAP;
2470                 }
2471                 else
2472                 {
2473                         // ordinary vertex coloring (q3bsp)
2474                         mode = SHADERMODE_VERTEXCOLOR;
2475                 }
2476                 if (r_shadow_bouncegridtexture)
2477                 {
2478                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2479                         if (r_shadow_bouncegriddirectional)
2480                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2481                 }
2482                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2483                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2484                 // when using alphatocoverage, we don't need alphakill
2485                 if (vid.allowalphatocoverage)
2486                 {
2487                         if (r_transparent_alphatocoverage.integer)
2488                         {
2489                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2490                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2491                         }
2492                         else
2493                                 GL_AlphaToCoverage(false);
2494                 }
2495         }
2496         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2497                 colormod = dummy_colormod;
2498         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2499                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2500         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2501                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2502         switch(vid.renderpath)
2503         {
2504         case RENDERPATH_D3D9:
2505 #ifdef SUPPORTD3D
2506                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2507                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2508                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2509                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2510                 if (mode == SHADERMODE_LIGHTSOURCE)
2511                 {
2512                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2513                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2514                 }
2515                 else
2516                 {
2517                         if (mode == SHADERMODE_LIGHTDIRECTION)
2518                         {
2519                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2520                         }
2521                 }
2522                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2523                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2524                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2525                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2526                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2527
2528                 if (mode == SHADERMODE_LIGHTSOURCE)
2529                 {
2530                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2531                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2532                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2533                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2535
2536                         // additive passes are only darkened by fog, not tinted
2537                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2538                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2539                 }
2540                 else
2541                 {
2542                         if (mode == SHADERMODE_FLATCOLOR)
2543                         {
2544                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2545                         }
2546                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2547                         {
2548                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2549                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2550                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2551                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2555                         }
2556                         else
2557                         {
2558                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2559                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2563                         }
2564                         // additive passes are only darkened by fog, not tinted
2565                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2566                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2567                         else
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2569                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2570                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2571                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2572                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2574                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2575                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2576                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2577                         if (mode == SHADERMODE_WATER)
2578                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2579                 }
2580                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2581                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2582                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2583                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2584                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2585                 if (rsurface.texture->pantstexture)
2586                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2587                 else
2588                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2589                 if (rsurface.texture->shirttexture)
2590                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2591                 else
2592                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2593                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2594                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2595                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2596                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2597                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2598                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2599                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2600                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2601                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2602                         );
2603                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2604                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2605
2606                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2607                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2608                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2609                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2610                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2611                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2612                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2613                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2614                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2615                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2616                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2617                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2618                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2619                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2620                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2621                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2622                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2623                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2624                 {
2625                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2626                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2627                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2628                 }
2629                 else
2630                 {
2631                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2632                 }
2633 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2634 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2635                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2636                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2637                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2638                 {
2639                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2640                         if (rsurface.rtlight)
2641                         {
2642                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2643                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2644                         }
2645                 }
2646 #endif
2647                 break;
2648         case RENDERPATH_D3D10:
2649                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2650                 break;
2651         case RENDERPATH_D3D11:
2652                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2653                 break;
2654         case RENDERPATH_GL20:
2655         case RENDERPATH_GLES2:
2656                 if (!vid.useinterleavedarrays)
2657                 {
2658                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2659                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2660                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2661                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2662                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2663                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2664                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2665                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2666                 }
2667                 else
2668                 {
2669                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2670                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2671                 }
2672                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2673                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2674                 if (mode == SHADERMODE_LIGHTSOURCE)
2675                 {
2676                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2677                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2678                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2679                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2680                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2681                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2682         
2683                         // additive passes are only darkened by fog, not tinted
2684                         if (r_glsl_permutation->loc_FogColor >= 0)
2685                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2686                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2687                 }
2688                 else
2689                 {
2690                         if (mode == SHADERMODE_FLATCOLOR)
2691                         {
2692                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2693                         }
2694                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2695                         {
2696                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2697                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2698                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2699                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2700                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2701                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2702                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2703                         }
2704                         else
2705                         {
2706                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2707                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2708                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2709                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2710                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2711                         }
2712                         // additive passes are only darkened by fog, not tinted
2713                         if (r_glsl_permutation->loc_FogColor >= 0)
2714                         {
2715                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2716                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2717                                 else
2718                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2719                         }
2720                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2721                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2722                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2723                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2724                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2725                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2726                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2727                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2728                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2729                 }
2730                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2731                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2732                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2733                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2734                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2735
2736                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2737                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2738                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2739                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2740                 {
2741                         if (rsurface.texture->pantstexture)
2742                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2743                         else
2744                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2745                 }
2746                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2747                 {
2748                         if (rsurface.texture->shirttexture)
2749                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2750                         else
2751                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2752                 }
2753                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2754                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2755                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2756                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2757                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2758                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2759                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2760                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2761                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2762                         );
2763                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2764                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2765                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2766                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2767
2768                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2769                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2770                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2771                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2772                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2773                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2774                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2775                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2776                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2777                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2778                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2779                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2780                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2781                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2782                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2783                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2784                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2785                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2786                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2787                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2788                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2789                 {
2790                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2791                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2792                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2793                 }
2794                 else
2795                 {
2796                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2797                 }
2798                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2799                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2800                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2801                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2802                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2803                 {
2804                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2805                         if (rsurface.rtlight)
2806                         {
2807                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2808                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2809                         }
2810                 }
2811                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2812                 CHECKGLERROR
2813                 break;
2814         case RENDERPATH_GL11:
2815         case RENDERPATH_GL13:
2816         case RENDERPATH_GLES1:
2817                 break;
2818         case RENDERPATH_SOFT:
2819                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2820                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2821                 R_SetupShader_SetPermutationSoft(mode, permutation);
2822                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2823                 if (mode == SHADERMODE_LIGHTSOURCE)
2824                 {
2825                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2826                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2827                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2828                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2829                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2830                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2831         
2832                         // additive passes are only darkened by fog, not tinted
2833                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2834                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2835                 }
2836                 else
2837                 {
2838                         if (mode == SHADERMODE_FLATCOLOR)
2839                         {
2840                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2841                         }
2842                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2843                         {
2844                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2845                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2846                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2847                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2848                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2849                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2850                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2851                         }
2852                         else
2853                         {
2854                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2856                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2858                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2859                         }
2860                         // additive passes are only darkened by fog, not tinted
2861                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2862                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2863                         else
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2865                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2866                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2867                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2868                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2869                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2870                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2871                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2872                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2873                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2874                 }
2875                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2876                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2877                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2878                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2879                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2880
2881                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2882                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2883                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2884                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2885                 {
2886                         if (rsurface.texture->pantstexture)
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2888                         else
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2890                 }
2891                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2892                 {
2893                         if (rsurface.texture->shirttexture)
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2895                         else
2896                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2897                 }
2898                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2899                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2900                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2901                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2902                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2903                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2904                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2905                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2906                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2907                         );
2908                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2909                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2910
2911                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2912                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2913                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2914                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2915                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2916                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2917                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2918                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2919                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2920                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2921                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2922                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2923                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2924                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2925                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2926                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2927                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2928                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2929                 {
2930                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2931                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2932                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2933                 }
2934                 else
2935                 {
2936                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2937                 }
2938 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2939 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2940                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2941                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2942                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2943                 {
2944                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2945                         if (rsurface.rtlight)
2946                         {
2947                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2948                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2949                         }
2950                 }
2951                 break;
2952         }
2953 }
2954
2955 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2956 {
2957         // select a permutation of the lighting shader appropriate to this
2958         // combination of texture, entity, light source, and fogging, only use the
2959         // minimum features necessary to avoid wasting rendering time in the
2960         // fragment shader on features that are not being used
2961         unsigned int permutation = 0;
2962         unsigned int mode = 0;
2963         const float *lightcolorbase = rtlight->currentcolor;
2964         float ambientscale = rtlight->ambientscale;
2965         float diffusescale = rtlight->diffusescale;
2966         float specularscale = rtlight->specularscale;
2967         // this is the location of the light in view space
2968         vec3_t viewlightorigin;
2969         // this transforms from view space (camera) to light space (cubemap)
2970         matrix4x4_t viewtolight;
2971         matrix4x4_t lighttoview;
2972         float viewtolight16f[16];
2973         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2974         // light source
2975         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2976         if (rtlight->currentcubemap != r_texture_whitecube)
2977                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2978         if (diffusescale > 0)
2979                 permutation |= SHADERPERMUTATION_DIFFUSE;
2980         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2981                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2982         if (r_shadow_usingshadowmap2d)
2983         {
2984                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2985                 if (r_shadow_shadowmapvsdct)
2986                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2987
2988                 if (r_shadow_shadowmapsampler)
2989                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2990                 if (r_shadow_shadowmappcf > 1)
2991                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2992                 else if (r_shadow_shadowmappcf)
2993                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2994         }
2995         if (vid.allowalphatocoverage)
2996                 GL_AlphaToCoverage(false);
2997         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2998         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
2999         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3000         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3001         switch(vid.renderpath)
3002         {
3003         case RENDERPATH_D3D9:
3004 #ifdef SUPPORTD3D
3005                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3006                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3007                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3008                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3009                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3010                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3011                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3012                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3013                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3014                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3015                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3016
3017                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3018                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3019                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3020                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3021                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3022                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3023 #endif
3024                 break;
3025         case RENDERPATH_D3D10:
3026                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3027                 break;
3028         case RENDERPATH_D3D11:
3029                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3030                 break;
3031         case RENDERPATH_GL20:
3032         case RENDERPATH_GLES2:
3033                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3034                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3035                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3036                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3037                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3038                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3039                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3040                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3041                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3042                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3043                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3044
3045                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3046                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3047                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3048                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3049                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3050                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3051                 break;
3052         case RENDERPATH_GL11:
3053         case RENDERPATH_GL13:
3054         case RENDERPATH_GLES1:
3055                 break;
3056         case RENDERPATH_SOFT:
3057                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3058                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3059                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3060                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3061                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3062                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3063                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3064                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3065                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3066                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3067                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3068
3069                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3070                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3071                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3072                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3073                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3074                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3075                 break;
3076         }
3077 }
3078
3079 #define SKINFRAME_HASH 1024
3080
3081 typedef struct
3082 {
3083         int loadsequence; // incremented each level change
3084         memexpandablearray_t array;
3085         skinframe_t *hash[SKINFRAME_HASH];
3086 }
3087 r_skinframe_t;
3088 r_skinframe_t r_skinframe;
3089
3090 void R_SkinFrame_PrepareForPurge(void)
3091 {
3092         r_skinframe.loadsequence++;
3093         // wrap it without hitting zero
3094         if (r_skinframe.loadsequence >= 200)
3095                 r_skinframe.loadsequence = 1;
3096 }
3097
3098 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3099 {
3100         if (!skinframe)
3101                 return;
3102         // mark the skinframe as used for the purging code
3103         skinframe->loadsequence = r_skinframe.loadsequence;
3104 }
3105
3106 void R_SkinFrame_Purge(void)
3107 {
3108         int i;
3109         skinframe_t *s;
3110         for (i = 0;i < SKINFRAME_HASH;i++)
3111         {
3112                 for (s = r_skinframe.hash[i];s;s = s->next)
3113                 {
3114                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3115                         {
3116                                 if (s->merged == s->base)
3117                                         s->merged = NULL;
3118                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3119                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3120                                 R_PurgeTexture(s->merged);s->merged = NULL;
3121                                 R_PurgeTexture(s->base  );s->base   = NULL;
3122                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3123                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3124                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3125                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3126                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3127                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3128                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3129                                 s->loadsequence = 0;
3130                         }
3131                 }
3132         }
3133 }
3134
3135 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3136         skinframe_t *item;
3137         char basename[MAX_QPATH];
3138
3139         Image_StripImageExtension(name, basename, sizeof(basename));
3140
3141         if( last == NULL ) {
3142                 int hashindex;
3143                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3144                 item = r_skinframe.hash[hashindex];
3145         } else {
3146                 item = last->next;
3147         }
3148
3149         // linearly search through the hash bucket
3150         for( ; item ; item = item->next ) {
3151                 if( !strcmp( item->basename, basename ) ) {
3152                         return item;
3153                 }
3154         }
3155         return NULL;
3156 }
3157
3158 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3159 {
3160         skinframe_t *item;
3161         int hashindex;
3162         char basename[MAX_QPATH];
3163
3164         Image_StripImageExtension(name, basename, sizeof(basename));
3165
3166         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3167         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3168                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3169                         break;
3170
3171         if (!item) {
3172                 rtexture_t *dyntexture;
3173                 // check whether its a dynamic texture
3174                 dyntexture = CL_GetDynTexture( basename );
3175                 if (!add && !dyntexture)
3176                         return NULL;
3177                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3178                 memset(item, 0, sizeof(*item));
3179                 strlcpy(item->basename, basename, sizeof(item->basename));
3180                 item->base = dyntexture; // either NULL or dyntexture handle
3181                 item->textureflags = textureflags;
3182                 item->comparewidth = comparewidth;
3183                 item->compareheight = compareheight;
3184                 item->comparecrc = comparecrc;
3185                 item->next = r_skinframe.hash[hashindex];
3186                 r_skinframe.hash[hashindex] = item;
3187         }
3188         else if( item->base == NULL )
3189         {
3190                 rtexture_t *dyntexture;
3191                 // check whether its a dynamic texture
3192                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3193                 dyntexture = CL_GetDynTexture( basename );
3194                 item->base = dyntexture; // either NULL or dyntexture handle
3195         }
3196
3197         R_SkinFrame_MarkUsed(item);
3198         return item;
3199 }
3200
3201 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3202         { \
3203                 unsigned long long avgcolor[5], wsum; \
3204                 int pix, comp, w; \
3205                 avgcolor[0] = 0; \
3206                 avgcolor[1] = 0; \
3207                 avgcolor[2] = 0; \
3208                 avgcolor[3] = 0; \
3209                 avgcolor[4] = 0; \
3210                 wsum = 0; \
3211                 for(pix = 0; pix < cnt; ++pix) \
3212                 { \
3213                         w = 0; \
3214                         for(comp = 0; comp < 3; ++comp) \
3215                                 w += getpixel; \
3216                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3217                         { \
3218                                 ++wsum; \
3219                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3220                                 w = getpixel; \
3221                                 for(comp = 0; comp < 3; ++comp) \
3222                                         avgcolor[comp] += getpixel * w; \
3223                                 avgcolor[3] += w; \
3224                         } \
3225                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3226                         avgcolor[4] += getpixel; \
3227                 } \
3228                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3229                         avgcolor[3] = 1; \
3230                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3231                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3232                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3233                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3234         }
3235
3236 extern cvar_t gl_picmip;
3237 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3238 {
3239         int j;
3240         unsigned char *pixels;
3241         unsigned char *bumppixels;
3242         unsigned char *basepixels = NULL;
3243         int basepixels_width = 0;
3244         int basepixels_height = 0;
3245         skinframe_t *skinframe;
3246         rtexture_t *ddsbase = NULL;
3247         qboolean ddshasalpha = false;
3248         float ddsavgcolor[4];
3249         char basename[MAX_QPATH];
3250         int miplevel = R_PicmipForFlags(textureflags);
3251         int savemiplevel = miplevel;
3252         int mymiplevel;
3253
3254         if (cls.state == ca_dedicated)
3255                 return NULL;
3256
3257         // return an existing skinframe if already loaded
3258         // if loading of the first image fails, don't make a new skinframe as it
3259         // would cause all future lookups of this to be missing
3260         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3261         if (skinframe && skinframe->base)
3262                 return skinframe;
3263
3264         Image_StripImageExtension(name, basename, sizeof(basename));
3265
3266         // check for DDS texture file first
3267         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3268         {
3269                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3270                 if (basepixels == NULL)
3271                         return NULL;
3272         }
3273
3274         // FIXME handle miplevel
3275
3276         if (developer_loading.integer)
3277                 Con_Printf("loading skin \"%s\"\n", name);
3278
3279         // we've got some pixels to store, so really allocate this new texture now
3280         if (!skinframe)
3281                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3282         skinframe->stain = NULL;
3283         skinframe->merged = NULL;
3284         skinframe->base = NULL;
3285         skinframe->pants = NULL;
3286         skinframe->shirt = NULL;
3287         skinframe->nmap = NULL;
3288         skinframe->gloss = NULL;
3289         skinframe->glow = NULL;
3290         skinframe->fog = NULL;
3291         skinframe->reflect = NULL;
3292         skinframe->hasalpha = false;
3293
3294         if (ddsbase)
3295         {
3296                 skinframe->base = ddsbase;
3297                 skinframe->hasalpha = ddshasalpha;
3298                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3299                 if (r_loadfog && skinframe->hasalpha)
3300                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3301                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3302         }
3303         else
3304         {
3305                 basepixels_width = image_width;
3306                 basepixels_height = image_height;
3307                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3308                 if (textureflags & TEXF_ALPHA)
3309                 {
3310                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3311                         {
3312                                 if (basepixels[j] < 255)
3313                                 {
3314                                         skinframe->hasalpha = true;
3315                                         break;
3316                                 }
3317                         }
3318                         if (r_loadfog && skinframe->hasalpha)
3319                         {
3320                                 // has transparent pixels
3321                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3322                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3323                                 {
3324                                         pixels[j+0] = 255;
3325                                         pixels[j+1] = 255;
3326                                         pixels[j+2] = 255;
3327                                         pixels[j+3] = basepixels[j+3];
3328                                 }
3329                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3330                                 Mem_Free(pixels);
3331                         }
3332                 }
3333                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3334                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3335                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3336                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3337                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3338                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3339         }
3340
3341         if (r_loaddds)
3342         {
3343                 mymiplevel = savemiplevel;
3344                 if (r_loadnormalmap)
3345                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3346                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3347                 if (r_loadgloss)
3348                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3349                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3350                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3351                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3352         }
3353
3354         // _norm is the name used by tenebrae and has been adopted as standard
3355         if (r_loadnormalmap && skinframe->nmap == NULL)
3356         {
3357                 mymiplevel = savemiplevel;
3358                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3359                 {
3360                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3361                         Mem_Free(pixels);
3362                         pixels = NULL;
3363                 }
3364                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3365                 {
3366                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3367                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3368                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3369                         Mem_Free(pixels);
3370                         Mem_Free(bumppixels);
3371                 }
3372                 else if (r_shadow_bumpscale_basetexture.value > 0)
3373                 {
3374                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3375                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3376                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3377                         Mem_Free(pixels);
3378                 }
3379                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3380                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3381         }
3382
3383         // _luma is supported only for tenebrae compatibility
3384         // _glow is the preferred name
3385         mymiplevel = savemiplevel;
3386         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3387         {
3388                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3389                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3390                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3391                 Mem_Free(pixels);pixels = NULL;
3392         }
3393
3394         mymiplevel = savemiplevel;
3395         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3396         {
3397                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3398                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3399                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3400                 Mem_Free(pixels);
3401                 pixels = NULL;
3402         }
3403
3404         mymiplevel = savemiplevel;
3405         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3406         {
3407                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3408                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3409                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3410                 Mem_Free(pixels);
3411                 pixels = NULL;
3412         }
3413
3414         mymiplevel = savemiplevel;
3415         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3416         {
3417                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3418                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3419                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3420                 Mem_Free(pixels);
3421                 pixels = NULL;
3422         }
3423
3424         mymiplevel = savemiplevel;
3425         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3426         {
3427                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3428                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3429                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3430                 Mem_Free(pixels);
3431                 pixels = NULL;
3432         }
3433
3434         if (basepixels)
3435                 Mem_Free(basepixels);
3436
3437         return skinframe;
3438 }
3439
3440 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3441 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3442 {
3443         int i;
3444         unsigned char *temp1, *temp2;
3445         skinframe_t *skinframe;
3446
3447         if (cls.state == ca_dedicated)
3448                 return NULL;
3449
3450         // if already loaded just return it, otherwise make a new skinframe
3451         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3452         if (skinframe && skinframe->base)
3453                 return skinframe;
3454
3455         skinframe->stain = NULL;
3456         skinframe->merged = NULL;
3457         skinframe->base = NULL;
3458         skinframe->pants = NULL;
3459         skinframe->shirt = NULL;
3460         skinframe->nmap = NULL;
3461         skinframe->gloss = NULL;
3462         skinframe->glow = NULL;
3463         skinframe->fog = NULL;
3464         skinframe->reflect = NULL;
3465         skinframe->hasalpha = false;
3466
3467         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3468         if (!skindata)
3469                 return NULL;
3470
3471         if (developer_loading.integer)
3472                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3473
3474         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3475         {
3476                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3477                 temp2 = temp1 + width * height * 4;
3478                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3479                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3480                 Mem_Free(temp1);
3481         }
3482         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3483         if (textureflags & TEXF_ALPHA)
3484         {
3485                 for (i = 3;i < width * height * 4;i += 4)
3486                 {
3487                         if (skindata[i] < 255)
3488                         {
3489                                 skinframe->hasalpha = true;
3490                                 break;
3491                         }
3492                 }
3493                 if (r_loadfog && skinframe->hasalpha)
3494                 {
3495                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3496                         memcpy(fogpixels, skindata, width * height * 4);
3497                         for (i = 0;i < width * height * 4;i += 4)
3498                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3499                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3500                         Mem_Free(fogpixels);
3501                 }
3502         }
3503
3504         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3505         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3506
3507         return skinframe;
3508 }
3509
3510 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3511 {
3512         int i;
3513         int featuresmask;
3514         skinframe_t *skinframe;
3515
3516         if (cls.state == ca_dedicated)
3517                 return NULL;
3518
3519         // if already loaded just return it, otherwise make a new skinframe
3520         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3521         if (skinframe && skinframe->base)
3522                 return skinframe;
3523
3524         skinframe->stain = NULL;
3525         skinframe->merged = NULL;
3526         skinframe->base = NULL;
3527         skinframe->pants = NULL;
3528         skinframe->shirt = NULL;
3529         skinframe->nmap = NULL;
3530         skinframe->gloss = NULL;
3531         skinframe->glow = NULL;
3532         skinframe->fog = NULL;
3533         skinframe->reflect = NULL;
3534         skinframe->hasalpha = false;
3535
3536         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3537         if (!skindata)
3538                 return NULL;
3539
3540         if (developer_loading.integer)
3541                 Con_Printf("loading quake skin \"%s\"\n", name);
3542
3543         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3544         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3545         memcpy(skinframe->qpixels, skindata, width*height);
3546         skinframe->qwidth = width;
3547         skinframe->qheight = height;
3548
3549         featuresmask = 0;
3550         for (i = 0;i < width * height;i++)
3551                 featuresmask |= palette_featureflags[skindata[i]];
3552
3553         skinframe->hasalpha = false;
3554         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3555         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3556         skinframe->qgeneratemerged = true;
3557         skinframe->qgeneratebase = skinframe->qhascolormapping;
3558         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3559
3560         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3561         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3562
3563         return skinframe;
3564 }
3565
3566 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3567 {
3568         int width;
3569         int height;
3570         unsigned char *skindata;
3571
3572         if (!skinframe->qpixels)
3573                 return;
3574
3575         if (!skinframe->qhascolormapping)
3576                 colormapped = false;
3577
3578         if (colormapped)
3579         {
3580                 if (!skinframe->qgeneratebase)
3581                         return;
3582         }
3583         else
3584         {
3585                 if (!skinframe->qgeneratemerged)
3586                         return;
3587         }
3588
3589         width = skinframe->qwidth;
3590         height = skinframe->qheight;
3591         skindata = skinframe->qpixels;
3592
3593         if (skinframe->qgeneratenmap)
3594         {
3595                 unsigned char *temp1, *temp2;
3596                 skinframe->qgeneratenmap = false;
3597                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3598                 temp2 = temp1 + width * height * 4;
3599                 // use either a custom palette or the quake palette
3600                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3601                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3602                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3603                 Mem_Free(temp1);
3604         }
3605
3606         if (skinframe->qgenerateglow)
3607         {
3608                 skinframe->qgenerateglow = false;
3609                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3610         }
3611
3612         if (colormapped)
3613         {
3614                 skinframe->qgeneratebase = false;
3615                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3616                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3617                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3618         }
3619         else
3620         {
3621                 skinframe->qgeneratemerged = false;
3622                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3623         }
3624
3625         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3626         {
3627                 Mem_Free(skinframe->qpixels);
3628                 skinframe->qpixels = NULL;
3629         }
3630 }
3631
3632 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3633 {
3634         int i;
3635         skinframe_t *skinframe;
3636
3637         if (cls.state == ca_dedicated)
3638                 return NULL;
3639
3640         // if already loaded just return it, otherwise make a new skinframe
3641         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3642         if (skinframe && skinframe->base)
3643                 return skinframe;
3644
3645         skinframe->stain = NULL;
3646         skinframe->merged = NULL;
3647         skinframe->base = NULL;
3648         skinframe->pants = NULL;
3649         skinframe->shirt = NULL;
3650         skinframe->nmap = NULL;
3651         skinframe->gloss = NULL;
3652         skinframe->glow = NULL;
3653         skinframe->fog = NULL;
3654         skinframe->reflect = NULL;
3655         skinframe->hasalpha = false;
3656
3657         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3658         if (!skindata)
3659                 return NULL;
3660
3661         if (developer_loading.integer)
3662                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3663
3664         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3665         if (textureflags & TEXF_ALPHA)
3666         {
3667                 for (i = 0;i < width * height;i++)
3668                 {
3669                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3670                         {
3671                                 skinframe->hasalpha = true;
3672                                 break;
3673                         }
3674                 }
3675                 if (r_loadfog && skinframe->hasalpha)
3676                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3677         }
3678
3679         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3680         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3681
3682         return skinframe;
3683 }
3684
3685 skinframe_t *R_SkinFrame_LoadMissing(void)
3686 {
3687         skinframe_t *skinframe;
3688
3689         if (cls.state == ca_dedicated)
3690                 return NULL;
3691
3692         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3693         skinframe->stain = NULL;
3694         skinframe->merged = NULL;
3695         skinframe->base = NULL;
3696         skinframe->pants = NULL;
3697         skinframe->shirt = NULL;
3698         skinframe->nmap = NULL;
3699         skinframe->gloss = NULL;
3700         skinframe->glow = NULL;
3701         skinframe->fog = NULL;
3702         skinframe->reflect = NULL;
3703         skinframe->hasalpha = false;
3704
3705         skinframe->avgcolor[0] = rand() / RAND_MAX;
3706         skinframe->avgcolor[1] = rand() / RAND_MAX;
3707         skinframe->avgcolor[2] = rand() / RAND_MAX;
3708         skinframe->avgcolor[3] = 1;
3709
3710         return skinframe;
3711 }
3712
3713 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3714 typedef struct suffixinfo_s
3715 {
3716         const char *suffix;
3717         qboolean flipx, flipy, flipdiagonal;
3718 }
3719 suffixinfo_t;
3720 static suffixinfo_t suffix[3][6] =
3721 {
3722         {
3723                 {"px",   false, false, false},
3724                 {"nx",   false, false, false},
3725                 {"py",   false, false, false},
3726                 {"ny",   false, false, false},
3727                 {"pz",   false, false, false},
3728                 {"nz",   false, false, false}
3729         },
3730         {
3731                 {"posx", false, false, false},
3732                 {"negx", false, false, false},
3733                 {"posy", false, false, false},
3734                 {"negy", false, false, false},
3735                 {"posz", false, false, false},
3736                 {"negz", false, false, false}
3737         },
3738         {
3739                 {"rt",    true, false,  true},
3740                 {"lf",   false,  true,  true},
3741                 {"ft",    true,  true, false},
3742                 {"bk",   false, false, false},
3743                 {"up",    true, false,  true},
3744                 {"dn",    true, false,  true}
3745         }
3746 };
3747
3748 static int componentorder[4] = {0, 1, 2, 3};
3749
3750 rtexture_t *R_LoadCubemap(const char *basename)
3751 {
3752         int i, j, cubemapsize;
3753         unsigned char *cubemappixels, *image_buffer;
3754         rtexture_t *cubemaptexture;
3755         char name[256];
3756         // must start 0 so the first loadimagepixels has no requested width/height
3757         cubemapsize = 0;
3758         cubemappixels = NULL;
3759         cubemaptexture = NULL;
3760         // keep trying different suffix groups (posx, px, rt) until one loads
3761         for (j = 0;j < 3 && !cubemappixels;j++)
3762         {
3763                 // load the 6 images in the suffix group
3764                 for (i = 0;i < 6;i++)
3765                 {
3766                         // generate an image name based on the base and and suffix
3767                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3768                         // load it
3769                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3770                         {
3771                                 // an image loaded, make sure width and height are equal
3772                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3773                                 {
3774                                         // if this is the first image to load successfully, allocate the cubemap memory
3775                                         if (!cubemappixels && image_width >= 1)
3776                                         {
3777                                                 cubemapsize = image_width;
3778                                                 // note this clears to black, so unavailable sides are black
3779                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3780                                         }
3781                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3782                                         if (cubemappixels)
3783                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3784                                 }
3785                                 else
3786                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3787                                 // free the image
3788                                 Mem_Free(image_buffer);
3789                         }
3790                 }
3791         }
3792         // if a cubemap loaded, upload it
3793         if (cubemappixels)
3794         {
3795                 if (developer_loading.integer)
3796                         Con_Printf("loading cubemap \"%s\"\n", basename);
3797
3798                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3799                 Mem_Free(cubemappixels);
3800         }
3801         else
3802         {
3803                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3804                 if (developer_loading.integer)
3805                 {
3806                         Con_Printf("(tried tried images ");
3807                         for (j = 0;j < 3;j++)
3808                                 for (i = 0;i < 6;i++)
3809                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3810                         Con_Print(" and was unable to find any of them).\n");
3811                 }
3812         }
3813         return cubemaptexture;
3814 }
3815
3816 rtexture_t *R_GetCubemap(const char *basename)
3817 {
3818         int i;
3819         for (i = 0;i < r_texture_numcubemaps;i++)
3820                 if (r_texture_cubemaps[i] != NULL)
3821                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3822                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3823         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3824                 return r_texture_whitecube;
3825         r_texture_numcubemaps++;
3826         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3827         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3828         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3829         return r_texture_cubemaps[i]->texture;
3830 }
3831
3832 void R_FreeCubemap(const char *basename)
3833 {
3834         int i;
3835
3836         for (i = 0;i < r_texture_numcubemaps;i++)
3837         {
3838                 if (r_texture_cubemaps[i] != NULL)
3839                 {
3840                         if (r_texture_cubemaps[i]->texture)
3841                         {
3842                                 if (developer_loading.integer)
3843                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3844                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3845                                 Mem_Free(r_texture_cubemaps[i]);
3846                                 r_texture_cubemaps[i] = NULL;
3847                         }
3848                 }
3849         }
3850 }
3851
3852 void R_FreeCubemaps(void)
3853 {
3854         int i;
3855         for (i = 0;i < r_texture_numcubemaps;i++)
3856         {
3857                 if (developer_loading.integer)
3858                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3859                 if (r_texture_cubemaps[i] != NULL)
3860                 {
3861                         if (r_texture_cubemaps[i]->texture)
3862                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3863                         Mem_Free(r_texture_cubemaps[i]);
3864                 }
3865         }
3866         r_texture_numcubemaps = 0;
3867 }
3868
3869 void R_Main_FreeViewCache(void)
3870 {
3871         if (r_refdef.viewcache.entityvisible)
3872                 Mem_Free(r_refdef.viewcache.entityvisible);
3873         if (r_refdef.viewcache.world_pvsbits)
3874                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3875         if (r_refdef.viewcache.world_leafvisible)
3876                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3877         if (r_refdef.viewcache.world_surfacevisible)
3878                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3879         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3880 }
3881
3882 void R_Main_ResizeViewCache(void)
3883 {
3884         int numentities = r_refdef.scene.numentities;
3885         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3886         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3887         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3888         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3889         if (r_refdef.viewcache.maxentities < numentities)
3890         {
3891                 r_refdef.viewcache.maxentities = numentities;
3892                 if (r_refdef.viewcache.entityvisible)
3893                         Mem_Free(r_refdef.viewcache.entityvisible);
3894                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3895         }
3896         if (r_refdef.viewcache.world_numclusters != numclusters)
3897         {
3898                 r_refdef.viewcache.world_numclusters = numclusters;
3899                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3900                 if (r_refdef.viewcache.world_pvsbits)
3901                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3902                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3903         }
3904         if (r_refdef.viewcache.world_numleafs != numleafs)
3905         {
3906                 r_refdef.viewcache.world_numleafs = numleafs;
3907                 if (r_refdef.viewcache.world_leafvisible)
3908                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3909                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3910         }
3911         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3912         {
3913                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3914                 if (r_refdef.viewcache.world_surfacevisible)
3915                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3916                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3917         }
3918 }
3919
3920 extern rtexture_t *loadingscreentexture;
3921 void gl_main_start(void)
3922 {
3923         loadingscreentexture = NULL;
3924         r_texture_blanknormalmap = NULL;
3925         r_texture_white = NULL;
3926         r_texture_grey128 = NULL;
3927         r_texture_black = NULL;
3928         r_texture_whitecube = NULL;
3929         r_texture_normalizationcube = NULL;
3930         r_texture_fogattenuation = NULL;
3931         r_texture_fogheighttexture = NULL;
3932         r_texture_gammaramps = NULL;
3933         r_texture_numcubemaps = 0;
3934
3935         r_loaddds = r_texture_dds_load.integer != 0;
3936         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3937
3938         switch(vid.renderpath)
3939         {
3940         case RENDERPATH_GL20:
3941         case RENDERPATH_D3D9:
3942         case RENDERPATH_D3D10:
3943         case RENDERPATH_D3D11:
3944         case RENDERPATH_SOFT:
3945         case RENDERPATH_GLES2:
3946                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3947                 Cvar_SetValueQuick(&gl_combine, 1);
3948                 Cvar_SetValueQuick(&r_glsl, 1);
3949                 r_loadnormalmap = true;
3950                 r_loadgloss = true;
3951                 r_loadfog = false;
3952                 break;
3953         case RENDERPATH_GL13:
3954         case RENDERPATH_GLES1:
3955                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3956                 Cvar_SetValueQuick(&gl_combine, 1);
3957                 Cvar_SetValueQuick(&r_glsl, 0);
3958                 r_loadnormalmap = false;
3959                 r_loadgloss = false;
3960                 r_loadfog = true;
3961                 break;
3962         case RENDERPATH_GL11:
3963                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3964                 Cvar_SetValueQuick(&gl_combine, 0);
3965                 Cvar_SetValueQuick(&r_glsl, 0);
3966                 r_loadnormalmap = false;
3967                 r_loadgloss = false;
3968                 r_loadfog = true;
3969                 break;
3970         }
3971
3972         R_AnimCache_Free();
3973         R_FrameData_Reset();
3974
3975         r_numqueries = 0;
3976         r_maxqueries = 0;
3977         memset(r_queries, 0, sizeof(r_queries));
3978
3979         r_qwskincache = NULL;
3980         r_qwskincache_size = 0;
3981
3982         // due to caching of texture_t references, the collision cache must be reset
3983         Collision_Cache_Reset(true);
3984
3985         // set up r_skinframe loading system for textures
3986         memset(&r_skinframe, 0, sizeof(r_skinframe));
3987         r_skinframe.loadsequence = 1;
3988         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3989
3990         r_main_texturepool = R_AllocTexturePool();
3991         R_BuildBlankTextures();
3992         R_BuildNoTexture();
3993         if (vid.support.arb_texture_cube_map)
3994         {
3995                 R_BuildWhiteCube();
3996                 R_BuildNormalizationCube();
3997         }
3998         r_texture_fogattenuation = NULL;
3999         r_texture_fogheighttexture = NULL;
4000         r_texture_gammaramps = NULL;
4001         //r_texture_fogintensity = NULL;
4002         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4003         memset(&r_waterstate, 0, sizeof(r_waterstate));
4004         r_glsl_permutation = NULL;
4005         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4006         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4007         glslshaderstring = NULL;
4008 #ifdef SUPPORTD3D
4009         r_hlsl_permutation = NULL;
4010         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4011         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4012 #endif
4013         hlslshaderstring = NULL;
4014         memset(&r_svbsp, 0, sizeof (r_svbsp));
4015
4016         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4017         r_texture_numcubemaps = 0;
4018
4019         r_refdef.fogmasktable_density = 0;
4020 }
4021
4022 void gl_main_shutdown(void)
4023 {
4024         R_AnimCache_Free();
4025         R_FrameData_Reset();
4026
4027         R_Main_FreeViewCache();
4028
4029         switch(vid.renderpath)
4030         {
4031         case RENDERPATH_GL11:
4032         case RENDERPATH_GL13:
4033         case RENDERPATH_GL20:
4034         case RENDERPATH_GLES1:
4035         case RENDERPATH_GLES2:
4036                 if (r_maxqueries)
4037                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4038                 break;
4039         case RENDERPATH_D3D9:
4040                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4041                 break;
4042         case RENDERPATH_D3D10:
4043                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4044                 break;
4045         case RENDERPATH_D3D11:
4046                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4047                 break;
4048         case RENDERPATH_SOFT:
4049                 break;
4050         }
4051
4052         r_numqueries = 0;
4053         r_maxqueries = 0;
4054         memset(r_queries, 0, sizeof(r_queries));
4055
4056         r_qwskincache = NULL;
4057         r_qwskincache_size = 0;
4058
4059         // clear out the r_skinframe state
4060         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4061         memset(&r_skinframe, 0, sizeof(r_skinframe));
4062
4063         if (r_svbsp.nodes)
4064                 Mem_Free(r_svbsp.nodes);
4065         memset(&r_svbsp, 0, sizeof (r_svbsp));
4066         R_FreeTexturePool(&r_main_texturepool);
4067         loadingscreentexture = NULL;
4068         r_texture_blanknormalmap = NULL;
4069         r_texture_white = NULL;
4070         r_texture_grey128 = NULL;
4071         r_texture_black = NULL;
4072         r_texture_whitecube = NULL;
4073         r_texture_normalizationcube = NULL;
4074         r_texture_fogattenuation = NULL;
4075         r_texture_fogheighttexture = NULL;
4076         r_texture_gammaramps = NULL;
4077         r_texture_numcubemaps = 0;
4078         //r_texture_fogintensity = NULL;
4079         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4080         memset(&r_waterstate, 0, sizeof(r_waterstate));
4081         R_GLSL_Restart_f();
4082
4083         r_glsl_permutation = NULL;
4084         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4085         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4086         glslshaderstring = NULL;
4087 #ifdef SUPPORTD3D
4088         r_hlsl_permutation = NULL;
4089         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4090         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4091 #endif
4092         hlslshaderstring = NULL;
4093 }
4094
4095 extern void CL_ParseEntityLump(char *entitystring);
4096 void gl_main_newmap(void)
4097 {
4098         // FIXME: move this code to client
4099         char *entities, entname[MAX_QPATH];
4100         if (r_qwskincache)
4101                 Mem_Free(r_qwskincache);
4102         r_qwskincache = NULL;
4103         r_qwskincache_size = 0;
4104         if (cl.worldmodel)
4105         {
4106                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4107                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4108                 {
4109                         CL_ParseEntityLump(entities);
4110                         Mem_Free(entities);
4111                         return;
4112                 }
4113                 if (cl.worldmodel->brush.entities)
4114                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4115         }
4116         R_Main_FreeViewCache();
4117
4118         R_FrameData_Reset();
4119 }
4120
4121 void GL_Main_Init(void)
4122 {
4123         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4124
4125         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4126         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4127         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4128         if (gamemode == GAME_NEHAHRA)
4129         {
4130                 Cvar_RegisterVariable (&gl_fogenable);
4131                 Cvar_RegisterVariable (&gl_fogdensity);
4132                 Cvar_RegisterVariable (&gl_fogred);
4133                 Cvar_RegisterVariable (&gl_foggreen);
4134                 Cvar_RegisterVariable (&gl_fogblue);
4135                 Cvar_RegisterVariable (&gl_fogstart);
4136                 Cvar_RegisterVariable (&gl_fogend);
4137                 Cvar_RegisterVariable (&gl_skyclip);
4138         }
4139         Cvar_RegisterVariable(&r_motionblur);
4140         Cvar_RegisterVariable(&r_motionblur_maxblur);
4141         Cvar_RegisterVariable(&r_motionblur_bmin);
4142         Cvar_RegisterVariable(&r_motionblur_vmin);
4143         Cvar_RegisterVariable(&r_motionblur_vmax);
4144         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4145         Cvar_RegisterVariable(&r_motionblur_randomize);
4146         Cvar_RegisterVariable(&r_damageblur);
4147         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4148         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4149         Cvar_RegisterVariable(&r_equalize_entities_by);
4150         Cvar_RegisterVariable(&r_equalize_entities_to);
4151         Cvar_RegisterVariable(&r_depthfirst);
4152         Cvar_RegisterVariable(&r_useinfinitefarclip);
4153         Cvar_RegisterVariable(&r_farclip_base);
4154         Cvar_RegisterVariable(&r_farclip_world);
4155         Cvar_RegisterVariable(&r_nearclip);
4156         Cvar_RegisterVariable(&r_deformvertexes);
4157         Cvar_RegisterVariable(&r_transparent);
4158         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4159         Cvar_RegisterVariable(&r_showoverdraw);
4160         Cvar_RegisterVariable(&r_showbboxes);
4161         Cvar_RegisterVariable(&r_showsurfaces);
4162         Cvar_RegisterVariable(&r_showtris);
4163         Cvar_RegisterVariable(&r_shownormals);
4164         Cvar_RegisterVariable(&r_showlighting);
4165         Cvar_RegisterVariable(&r_showshadowvolumes);
4166         Cvar_RegisterVariable(&r_showcollisionbrushes);
4167         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4168         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4169         Cvar_RegisterVariable(&r_showdisabledepthtest);
4170         Cvar_RegisterVariable(&r_drawportals);
4171         Cvar_RegisterVariable(&r_drawentities);
4172         Cvar_RegisterVariable(&r_draw2d);
4173         Cvar_RegisterVariable(&r_drawworld);
4174         Cvar_RegisterVariable(&r_cullentities_trace);
4175         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4176         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4177         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4178         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4179         Cvar_RegisterVariable(&r_drawviewmodel);
4180         Cvar_RegisterVariable(&r_drawexteriormodel);
4181         Cvar_RegisterVariable(&r_speeds);
4182         Cvar_RegisterVariable(&r_fullbrights);
4183         Cvar_RegisterVariable(&r_wateralpha);
4184         Cvar_RegisterVariable(&r_dynamic);
4185         Cvar_RegisterVariable(&r_fakelight);
4186         Cvar_RegisterVariable(&r_fakelight_intensity);
4187         Cvar_RegisterVariable(&r_fullbright);
4188         Cvar_RegisterVariable(&r_shadows);
4189         Cvar_RegisterVariable(&r_shadows_darken);
4190         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4191         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4192         Cvar_RegisterVariable(&r_shadows_throwdistance);
4193         Cvar_RegisterVariable(&r_shadows_throwdirection);
4194         Cvar_RegisterVariable(&r_shadows_focus);
4195         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4196         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4197         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4198         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4199         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4200         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4201         Cvar_RegisterVariable(&r_fog_exp2);
4202         Cvar_RegisterVariable(&r_fog_clear);
4203         Cvar_RegisterVariable(&r_drawfog);
4204         Cvar_RegisterVariable(&r_transparentdepthmasking);
4205         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4206         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4207         Cvar_RegisterVariable(&r_texture_dds_load);
4208         Cvar_RegisterVariable(&r_texture_dds_save);
4209         Cvar_RegisterVariable(&r_textureunits);
4210         Cvar_RegisterVariable(&gl_combine);
4211         Cvar_RegisterVariable(&r_viewfbo);
4212         Cvar_RegisterVariable(&r_viewscale);
4213         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4214         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4215         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4216         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4217         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4218         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4219         Cvar_RegisterVariable(&r_glsl);
4220         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4221         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4222         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4223         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4224         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4225         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4226         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4227         Cvar_RegisterVariable(&r_glsl_postprocess);
4228         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4229         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4230         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4231         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4232         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4233         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4234         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4235         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4236
4237         Cvar_RegisterVariable(&r_water);
4238         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4239         Cvar_RegisterVariable(&r_water_clippingplanebias);
4240         Cvar_RegisterVariable(&r_water_refractdistort);
4241         Cvar_RegisterVariable(&r_water_reflectdistort);
4242         Cvar_RegisterVariable(&r_water_scissormode);
4243         Cvar_RegisterVariable(&r_water_lowquality);
4244
4245         Cvar_RegisterVariable(&r_lerpsprites);
4246         Cvar_RegisterVariable(&r_lerpmodels);
4247         Cvar_RegisterVariable(&r_lerplightstyles);
4248         Cvar_RegisterVariable(&r_waterscroll);
4249         Cvar_RegisterVariable(&r_bloom);
4250         Cvar_RegisterVariable(&r_bloom_colorscale);
4251         Cvar_RegisterVariable(&r_bloom_brighten);
4252         Cvar_RegisterVariable(&r_bloom_blur);
4253         Cvar_RegisterVariable(&r_bloom_resolution);
4254         Cvar_RegisterVariable(&r_bloom_colorexponent);
4255         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4256         Cvar_RegisterVariable(&r_hdr);
4257         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4258         Cvar_RegisterVariable(&r_hdr_glowintensity);
4259         Cvar_RegisterVariable(&r_hdr_range);
4260         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4261         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4262         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4263         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4264         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4265         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade);
4266         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4267         Cvar_RegisterVariable(&developer_texturelogging);
4268         Cvar_RegisterVariable(&gl_lightmaps);
4269         Cvar_RegisterVariable(&r_test);
4270         Cvar_RegisterVariable(&r_glsl_saturation);
4271         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4272         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4273         Cvar_RegisterVariable(&r_framedatasize);
4274         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4275                 Cvar_SetValue("r_fullbrights", 0);
4276         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4277 }
4278
4279 extern void R_Textures_Init(void);
4280 extern void GL_Draw_Init(void);
4281 extern void GL_Main_Init(void);
4282 extern void R_Shadow_Init(void);
4283 extern void R_Sky_Init(void);
4284 extern void GL_Surf_Init(void);
4285 extern void R_Particles_Init(void);
4286 extern void R_Explosion_Init(void);
4287 extern void gl_backend_init(void);
4288 extern void Sbar_Init(void);
4289 extern void R_LightningBeams_Init(void);
4290 extern void Mod_RenderInit(void);
4291 extern void Font_Init(void);
4292
4293 void Render_Init(void)
4294 {
4295         gl_backend_init();
4296         R_Textures_Init();
4297         GL_Main_Init();
4298         Font_Init();
4299         GL_Draw_Init();
4300         R_Shadow_Init();
4301         R_Sky_Init();
4302         GL_Surf_Init();
4303         Sbar_Init();
4304         R_Particles_Init();
4305         R_Explosion_Init();
4306         R_LightningBeams_Init();
4307         Mod_RenderInit();
4308 }
4309
4310 /*
4311 ===============
4312 GL_Init
4313 ===============
4314 */
4315 extern char *ENGINE_EXTENSIONS;
4316 void GL_Init (void)
4317 {
4318         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4319         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4320         gl_version = (const char *)qglGetString(GL_VERSION);
4321         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4322
4323         if (!gl_extensions)
4324                 gl_extensions = "";
4325         if (!gl_platformextensions)
4326                 gl_platformextensions = "";
4327
4328         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4329         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4330         Con_Printf("GL_VERSION: %s\n", gl_version);
4331         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4332         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4333
4334         VID_CheckExtensions();
4335
4336         // LordHavoc: report supported extensions
4337         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4338
4339         // clear to black (loading plaque will be seen over this)
4340         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4341 }
4342
4343 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4344 {
4345         int i;
4346         mplane_t *p;
4347         if (r_trippy.integer)
4348                 return false;
4349         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4350         {
4351                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4352                 if (i == 4)
4353                         continue;
4354                 p = r_refdef.view.frustum + i;
4355                 switch(p->signbits)
4356                 {
4357                 default:
4358                 case 0:
4359                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4360                                 return true;
4361                         break;
4362                 case 1:
4363                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4364                                 return true;
4365                         break;
4366                 case 2:
4367                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4368                                 return true;
4369                         break;
4370                 case 3:
4371                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4372                                 return true;
4373                         break;
4374                 case 4:
4375                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4376                                 return true;
4377                         break;
4378                 case 5:
4379                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4380                                 return true;
4381                         break;
4382                 case 6:
4383                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4384                                 return true;
4385                         break;
4386                 case 7:
4387                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4388                                 return true;
4389                         break;
4390                 }
4391         }
4392         return false;
4393 }
4394
4395 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4396 {
4397         int i;
4398         const mplane_t *p;
4399         if (r_trippy.integer)
4400                 return false;
4401         for (i = 0;i < numplanes;i++)
4402         {
4403                 p = planes + i;
4404                 switch(p->signbits)
4405                 {
4406                 default:
4407                 case 0:
4408                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4409                                 return true;
4410                         break;
4411                 case 1:
4412                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4413                                 return true;
4414                         break;
4415                 case 2:
4416                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4417                                 return true;
4418                         break;
4419                 case 3:
4420                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4421                                 return true;
4422                         break;
4423                 case 4:
4424                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4425                                 return true;
4426                         break;
4427                 case 5:
4428                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 6:
4432                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 7:
4436                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 }
4440         }
4441         return false;
4442 }
4443
4444 //==================================================================================
4445
4446 // LordHavoc: this stores temporary data used within the same frame
4447
4448 typedef struct r_framedata_mem_s
4449 {
4450         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4451         size_t size; // how much usable space
4452         size_t current; // how much space in use
4453         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4454         size_t wantedsize; // how much space was allocated
4455         unsigned char *data; // start of real data (16byte aligned)
4456 }
4457 r_framedata_mem_t;
4458
4459 static r_framedata_mem_t *r_framedata_mem;
4460
4461 void R_FrameData_Reset(void)
4462 {
4463         while (r_framedata_mem)
4464         {
4465                 r_framedata_mem_t *next = r_framedata_mem->purge;
4466                 Mem_Free(r_framedata_mem);
4467                 r_framedata_mem = next;
4468         }
4469 }
4470
4471 void R_FrameData_Resize(void)
4472 {
4473         size_t wantedsize;
4474         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4475         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4476         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4477         {
4478                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4479                 newmem->wantedsize = wantedsize;
4480                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4481                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4482                 newmem->current = 0;
4483                 newmem->mark = 0;
4484                 newmem->purge = r_framedata_mem;
4485                 r_framedata_mem = newmem;
4486         }
4487 }
4488
4489 void R_FrameData_NewFrame(void)
4490 {
4491         R_FrameData_Resize();
4492         if (!r_framedata_mem)
4493                 return;
4494         // if we ran out of space on the last frame, free the old memory now
4495         while (r_framedata_mem->purge)
4496         {
4497                 // repeatedly remove the second item in the list, leaving only head
4498                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4499                 Mem_Free(r_framedata_mem->purge);
4500                 r_framedata_mem->purge = next;
4501         }
4502         // reset the current mem pointer
4503         r_framedata_mem->current = 0;
4504         r_framedata_mem->mark = 0;
4505 }
4506
4507 void *R_FrameData_Alloc(size_t size)
4508 {
4509         void *data;
4510
4511         // align to 16 byte boundary - the data pointer is already aligned, so we
4512         // only need to ensure the size of every allocation is also aligned
4513         size = (size + 15) & ~15;
4514
4515         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4516         {
4517                 // emergency - we ran out of space, allocate more memory
4518                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4519                 R_FrameData_Resize();
4520         }
4521
4522         data = r_framedata_mem->data + r_framedata_mem->current;
4523         r_framedata_mem->current += size;
4524
4525         // count the usage for stats
4526         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4527         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4528
4529         return (void *)data;
4530 }
4531
4532 void *R_FrameData_Store(size_t size, void *data)
4533 {
4534         void *d = R_FrameData_Alloc(size);
4535         if (d && data)
4536                 memcpy(d, data, size);
4537         return d;
4538 }
4539
4540 void R_FrameData_SetMark(void)
4541 {
4542         if (!r_framedata_mem)
4543                 return;
4544         r_framedata_mem->mark = r_framedata_mem->current;
4545 }
4546
4547 void R_FrameData_ReturnToMark(void)
4548 {
4549         if (!r_framedata_mem)
4550                 return;
4551         r_framedata_mem->current = r_framedata_mem->mark;
4552 }
4553
4554 //==================================================================================
4555
4556 // LordHavoc: animcache originally written by Echon, rewritten since then
4557
4558 /**
4559  * Animation cache prevents re-generating mesh data for an animated model
4560  * multiple times in one frame for lighting, shadowing, reflections, etc.
4561  */
4562
4563 void R_AnimCache_Free(void)
4564 {
4565 }
4566
4567 void R_AnimCache_ClearCache(void)
4568 {
4569         int i;
4570         entity_render_t *ent;
4571
4572         for (i = 0;i < r_refdef.scene.numentities;i++)
4573         {
4574                 ent = r_refdef.scene.entities[i];
4575                 ent->animcache_vertex3f = NULL;
4576                 ent->animcache_normal3f = NULL;
4577                 ent->animcache_svector3f = NULL;
4578                 ent->animcache_tvector3f = NULL;
4579                 ent->animcache_vertexmesh = NULL;
4580                 ent->animcache_vertex3fbuffer = NULL;
4581                 ent->animcache_vertexmeshbuffer = NULL;
4582         }
4583 }
4584
4585 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4586 {
4587         int i;
4588
4589         // check if we need the meshbuffers
4590         if (!vid.useinterleavedarrays)
4591                 return;
4592
4593         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4594                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4595         // TODO: upload vertex3f buffer?
4596         if (ent->animcache_vertexmesh)
4597         {
4598                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4599                 for (i = 0;i < numvertices;i++)
4600                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4601                 if (ent->animcache_svector3f)
4602                         for (i = 0;i < numvertices;i++)
4603                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4604                 if (ent->animcache_tvector3f)
4605                         for (i = 0;i < numvertices;i++)
4606                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4607                 if (ent->animcache_normal3f)
4608                         for (i = 0;i < numvertices;i++)
4609                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4610                 // TODO: upload vertexmeshbuffer?
4611         }
4612 }
4613
4614 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4615 {
4616         dp_model_t *model = ent->model;
4617         int numvertices;
4618         // see if it's already cached this frame
4619         if (ent->animcache_vertex3f)
4620         {
4621                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4622                 if (wantnormals || wanttangents)
4623                 {
4624                         if (ent->animcache_normal3f)
4625                                 wantnormals = false;
4626                         if (ent->animcache_svector3f)
4627                                 wanttangents = false;
4628                         if (wantnormals || wanttangents)
4629                         {
4630                                 numvertices = model->surfmesh.num_vertices;
4631                                 if (wantnormals)
4632                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4633                                 if (wanttangents)
4634                                 {
4635                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4636                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4637                                 }
4638                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4639                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4640                         }
4641                 }
4642         }
4643         else
4644         {
4645                 // see if this ent is worth caching
4646                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4647                         return false;
4648                 // get some memory for this entity and generate mesh data
4649                 numvertices = model->surfmesh.num_vertices;
4650                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4651                 if (wantnormals)
4652                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4653                 if (wanttangents)
4654                 {
4655                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4656                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4657                 }
4658                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4659                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4660         }
4661         return true;
4662 }
4663
4664 void R_AnimCache_CacheVisibleEntities(void)
4665 {
4666         int i;
4667         qboolean wantnormals = true;
4668         qboolean wanttangents = !r_showsurfaces.integer;
4669
4670         switch(vid.renderpath)
4671         {
4672         case RENDERPATH_GL20:
4673         case RENDERPATH_D3D9:
4674         case RENDERPATH_D3D10:
4675         case RENDERPATH_D3D11:
4676         case RENDERPATH_GLES2:
4677                 break;
4678         case RENDERPATH_GL11:
4679         case RENDERPATH_GL13:
4680         case RENDERPATH_GLES1:
4681                 wanttangents = false;
4682                 break;
4683         case RENDERPATH_SOFT:
4684                 break;
4685         }
4686
4687         if (r_shownormals.integer)
4688                 wanttangents = wantnormals = true;
4689
4690         // TODO: thread this
4691         // NOTE: R_PrepareRTLights() also caches entities
4692
4693         for (i = 0;i < r_refdef.scene.numentities;i++)
4694                 if (r_refdef.viewcache.entityvisible[i])
4695                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4696 }
4697
4698 //==================================================================================
4699
4700 extern cvar_t r_overheadsprites_pushback;
4701
4702 static void R_View_UpdateEntityLighting (void)
4703 {
4704         int i;
4705         entity_render_t *ent;
4706         vec3_t tempdiffusenormal, avg;
4707         vec_t f, fa, fd, fdd;
4708         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4709
4710         for (i = 0;i < r_refdef.scene.numentities;i++)
4711         {
4712                 ent = r_refdef.scene.entities[i];
4713
4714                 // skip unseen models
4715                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4716                         continue;
4717
4718                 // skip bsp models
4719                 if (ent->model && ent->model->brush.num_leafs)
4720                 {
4721                         // TODO: use modellight for r_ambient settings on world?
4722                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4723                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4724                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4725                         continue;
4726                 }
4727
4728                 // fetch the lighting from the worldmodel data
4729                 VectorClear(ent->modellight_ambient);
4730                 VectorClear(ent->modellight_diffuse);
4731                 VectorClear(tempdiffusenormal);
4732                 if (ent->flags & RENDER_LIGHT)
4733                 {
4734                         vec3_t org;
4735                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4736
4737                         // complete lightning for lit sprites
4738                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4739                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4740                         {
4741                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4742                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4743                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4744                         }
4745                         else
4746                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4747
4748                         if(ent->flags & RENDER_EQUALIZE)
4749                         {
4750                                 // first fix up ambient lighting...
4751                                 if(r_equalize_entities_minambient.value > 0)
4752                                 {
4753                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4754                                         if(fd > 0)
4755                                         {
4756                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4757                                                 if(fa < r_equalize_entities_minambient.value * fd)
4758                                                 {
4759                                                         // solve:
4760                                                         //   fa'/fd' = minambient
4761                                                         //   fa'+0.25*fd' = fa+0.25*fd
4762                                                         //   ...
4763                                                         //   fa' = fd' * minambient
4764                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4765                                                         //   ...
4766                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4767                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4768                                                         //   ...
4769                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4770                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
4771                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4772                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4773                                                 }
4774                                         }
4775                                 }
4776
4777                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4778                                 {
4779                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4780                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4781                                         f = fa + 0.25 * fd;
4782                                         if(f > 0)
4783                                         {
4784                                                 // adjust brightness and saturation to target
4785                                                 avg[0] = avg[1] = avg[2] = fa / f;
4786                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4787                                                 avg[0] = avg[1] = avg[2] = fd / f;
4788                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4789                                         }
4790                                 }
4791                         }
4792                 }
4793                 else // highly rare
4794                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4795
4796                 // move the light direction into modelspace coordinates for lighting code
4797                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4798                 if(VectorLength2(ent->modellight_lightdir) == 0)
4799                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4800                 VectorNormalize(ent->modellight_lightdir);
4801         }
4802 }
4803
4804 #define MAX_LINEOFSIGHTTRACES 64
4805
4806 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4807 {
4808         int i;
4809         vec3_t boxmins, boxmaxs;
4810         vec3_t start;
4811         vec3_t end;
4812         dp_model_t *model = r_refdef.scene.worldmodel;
4813
4814         if (!model || !model->brush.TraceLineOfSight)
4815                 return true;
4816
4817         // expand the box a little
4818         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4819         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4820         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4821         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4822         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4823         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4824
4825         // return true if eye is inside enlarged box
4826         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4827                 return true;
4828
4829         // try center
4830         VectorCopy(eye, start);
4831         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4832         if (model->brush.TraceLineOfSight(model, start, end))
4833                 return true;
4834
4835         // try various random positions
4836         for (i = 0;i < numsamples;i++)
4837         {
4838                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4839                 if (model->brush.TraceLineOfSight(model, start, end))
4840                         return true;
4841         }
4842
4843         return false;
4844 }
4845
4846
4847 static void R_View_UpdateEntityVisible (void)
4848 {
4849         int i;
4850         int renderimask;
4851         int samples;
4852         entity_render_t *ent;
4853
4854         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4855                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4856                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4857                 :                                                          RENDER_EXTERIORMODEL;
4858         if (!r_drawviewmodel.integer)
4859                 renderimask |= RENDER_VIEWMODEL;
4860         if (!r_drawexteriormodel.integer)
4861                 renderimask |= RENDER_EXTERIORMODEL;
4862         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4863         {
4864                 // worldmodel can check visibility
4865                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4866                 for (i = 0;i < r_refdef.scene.numentities;i++)
4867                 {
4868                         ent = r_refdef.scene.entities[i];
4869                         if (!(ent->flags & renderimask))
4870                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
4871                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4872                                 r_refdef.viewcache.entityvisible[i] = true;
4873                 }
4874         }
4875         else
4876         {
4877                 // no worldmodel or it can't check visibility
4878                 for (i = 0;i < r_refdef.scene.numentities;i++)
4879                 {
4880                         ent = r_refdef.scene.entities[i];
4881                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4882                 }
4883         }
4884         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4885                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4886         {
4887                 for (i = 0;i < r_refdef.scene.numentities;i++)
4888                 {
4889                         if (!r_refdef.viewcache.entityvisible[i])
4890                                 continue;
4891                         ent = r_refdef.scene.entities[i];
4892                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4893                         {
4894                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4895                                 if (samples < 0)
4896                                         continue; // temp entities do pvs only
4897                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4898                                         ent->last_trace_visibility = realtime;
4899                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4900                                         r_refdef.viewcache.entityvisible[i] = 0;
4901                         }
4902                 }
4903         }
4904 }
4905
4906 /// only used if skyrendermasked, and normally returns false
4907 int R_DrawBrushModelsSky (void)
4908 {
4909         int i, sky;
4910         entity_render_t *ent;
4911
4912         sky = false;
4913         for (i = 0;i < r_refdef.scene.numentities;i++)
4914         {
4915                 if (!r_refdef.viewcache.entityvisible[i])
4916                         continue;
4917                 ent = r_refdef.scene.entities[i];
4918                 if (!ent->model || !ent->model->DrawSky)
4919                         continue;
4920                 ent->model->DrawSky(ent);
4921                 sky = true;
4922         }
4923         return sky;
4924 }
4925
4926 static void R_DrawNoModel(entity_render_t *ent);
4927 static void R_DrawModels(void)
4928 {
4929         int i;
4930         entity_render_t *ent;
4931
4932         for (i = 0;i < r_refdef.scene.numentities;i++)
4933         {
4934                 if (!r_refdef.viewcache.entityvisible[i])
4935                         continue;
4936                 ent = r_refdef.scene.entities[i];
4937                 r_refdef.stats.entities++;
4938                 /*
4939                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4940                 {
4941                         vec3_t f, l, u, o;
4942                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4943                         Con_Printf("R_DrawModels\n");
4944                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
4945                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
4946                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
4947                 }
4948                 */
4949                 if (ent->model && ent->model->Draw != NULL)
4950                         ent->model->Draw(ent);
4951                 else
4952                         R_DrawNoModel(ent);
4953         }
4954 }
4955
4956 static void R_DrawModelsDepth(void)
4957 {
4958         int i;
4959         entity_render_t *ent;
4960
4961         for (i = 0;i < r_refdef.scene.numentities;i++)
4962         {
4963                 if (!r_refdef.viewcache.entityvisible[i])
4964                         continue;
4965                 ent = r_refdef.scene.entities[i];
4966                 if (ent->model && ent->model->DrawDepth != NULL)
4967                         ent->model->DrawDepth(ent);
4968         }
4969 }
4970
4971 static void R_DrawModelsDebug(void)
4972 {
4973         int i;
4974         entity_render_t *ent;
4975
4976         for (i = 0;i < r_refdef.scene.numentities;i++)
4977         {
4978                 if (!r_refdef.viewcache.entityvisible[i])
4979                         continue;
4980                 ent = r_refdef.scene.entities[i];
4981                 if (ent->model && ent->model->DrawDebug != NULL)
4982                         ent->model->DrawDebug(ent);
4983         }
4984 }
4985
4986 static void R_DrawModelsAddWaterPlanes(void)
4987 {
4988         int i;
4989         entity_render_t *ent;
4990
4991         for (i = 0;i < r_refdef.scene.numentities;i++)
4992         {
4993                 if (!r_refdef.viewcache.entityvisible[i])
4994                         continue;
4995                 ent = r_refdef.scene.entities[i];
4996                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4997                         ent->model->DrawAddWaterPlanes(ent);
4998         }
4999 }
5000
5001 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5002 {
5003         if (r_hdr_irisadaptation.integer)
5004         {
5005                 vec3_t ambient;
5006                 vec3_t diffuse;
5007                 vec3_t diffusenormal;
5008                 vec_t brightness;
5009                 vec_t goal;
5010                 vec_t adjust;
5011                 vec_t current;
5012                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5013                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5014                 brightness = max(0.0000001f, brightness);
5015                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5016                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5017                 adjust = r_hdr_irisadaptation_fade.value * cl.realframetime;
5018                 current = r_hdr_irisadaptation_value.value;
5019                 if (current < goal)
5020                         current = min(current + adjust, goal);
5021                 else if (current > goal)
5022                         current = max(current - adjust, goal);
5023                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5024                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5025         }
5026         else if (r_hdr_irisadaptation_value.value != 1.0f)
5027                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5028 }
5029
5030 static void R_View_SetFrustum(const int *scissor)
5031 {
5032         int i;
5033         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5034         vec3_t forward, left, up, origin, v;
5035
5036         if(scissor)
5037         {
5038                 // flipped x coordinates (because x points left here)
5039                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5040                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5041
5042                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5043                 switch(vid.renderpath)
5044                 {
5045                         case RENDERPATH_D3D9:
5046                         case RENDERPATH_D3D10:
5047                         case RENDERPATH_D3D11:
5048                                 // non-flipped y coordinates
5049                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5050                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5051                                 break;
5052                         case RENDERPATH_SOFT:
5053                         case RENDERPATH_GL11:
5054                         case RENDERPATH_GL13:
5055                         case RENDERPATH_GL20:
5056                         case RENDERPATH_GLES1:
5057                         case RENDERPATH_GLES2:
5058                                 // non-flipped y coordinates
5059                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5060                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5061                                 break;
5062                 }
5063         }
5064
5065         // we can't trust r_refdef.view.forward and friends in reflected scenes
5066         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5067
5068 #if 0
5069         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5070         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5071         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5072         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5073         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5074         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5075         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5076         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5077         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5078         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5079         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5080         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5081 #endif
5082
5083 #if 0
5084         zNear = r_refdef.nearclip;
5085         nudge = 1.0 - 1.0 / (1<<23);
5086         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5087         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5088         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5089         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5090         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5091         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5092         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5093         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5094 #endif
5095
5096
5097
5098 #if 0
5099         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5100         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5101         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5102         r_refdef.view.frustum[0].dist = m[15] - m[12];
5103
5104         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5105         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5106         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5107         r_refdef.view.frustum[1].dist = m[15] + m[12];
5108
5109         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5110         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5111         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5112         r_refdef.view.frustum[2].dist = m[15] - m[13];
5113
5114         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5115         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5116         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5117         r_refdef.view.frustum[3].dist = m[15] + m[13];
5118
5119         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5120         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5121         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5122         r_refdef.view.frustum[4].dist = m[15] - m[14];
5123
5124         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5125         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5126         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5127         r_refdef.view.frustum[5].dist = m[15] + m[14];
5128 #endif
5129
5130         if (r_refdef.view.useperspective)
5131         {
5132                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5133                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5134                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5135                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5136                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5137
5138                 // then the normals from the corners relative to origin
5139                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5140                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5141                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5142                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5143
5144                 // in a NORMAL view, forward cross left == up
5145                 // in a REFLECTED view, forward cross left == down
5146                 // so our cross products above need to be adjusted for a left handed coordinate system
5147                 CrossProduct(forward, left, v);
5148                 if(DotProduct(v, up) < 0)
5149                 {
5150                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5151                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5152                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5153                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5154                 }
5155
5156                 // Leaving those out was a mistake, those were in the old code, and they
5157                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5158                 // I couldn't reproduce it after adding those normalizations. --blub
5159                 VectorNormalize(r_refdef.view.frustum[0].normal);
5160                 VectorNormalize(r_refdef.view.frustum[1].normal);
5161                 VectorNormalize(r_refdef.view.frustum[2].normal);
5162                 VectorNormalize(r_refdef.view.frustum[3].normal);
5163
5164                 // make the corners absolute
5165                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5166                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5167                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5168                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5169
5170                 // one more normal
5171                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5172
5173                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5174                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5175                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5176                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5177                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5178         }
5179         else
5180         {
5181                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5182                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5183                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5184                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5185                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5186                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5187                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5188                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5189                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5190                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5191         }
5192         r_refdef.view.numfrustumplanes = 5;
5193
5194         if (r_refdef.view.useclipplane)
5195         {
5196                 r_refdef.view.numfrustumplanes = 6;
5197                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5198         }
5199
5200         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5201                 PlaneClassify(r_refdef.view.frustum + i);
5202
5203         // LordHavoc: note to all quake engine coders, Quake had a special case
5204         // for 90 degrees which assumed a square view (wrong), so I removed it,
5205         // Quake2 has it disabled as well.
5206
5207         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5208         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5209         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5210         //PlaneClassify(&frustum[0]);
5211
5212         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5213         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5214         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5215         //PlaneClassify(&frustum[1]);
5216
5217         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5218         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5219         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5220         //PlaneClassify(&frustum[2]);
5221
5222         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5223         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5224         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5225         //PlaneClassify(&frustum[3]);
5226
5227         // nearclip plane
5228         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5229         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5230         //PlaneClassify(&frustum[4]);
5231 }
5232
5233 void R_View_UpdateWithScissor(const int *myscissor)
5234 {
5235         R_Main_ResizeViewCache();
5236         R_View_SetFrustum(myscissor);
5237         R_View_WorldVisibility(r_refdef.view.useclipplane);
5238         R_View_UpdateEntityVisible();
5239         R_View_UpdateEntityLighting();
5240 }
5241
5242 void R_View_Update(void)
5243 {
5244         R_Main_ResizeViewCache();
5245         R_View_SetFrustum(NULL);
5246         R_View_WorldVisibility(r_refdef.view.useclipplane);
5247         R_View_UpdateEntityVisible();
5248         R_View_UpdateEntityLighting();
5249 }
5250
5251 float viewscalefpsadjusted = 1.0f;
5252
5253 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5254 {
5255         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5256         scale = bound(0.03125f, scale, 1.0f);
5257         *outwidth = (int)ceil(width * scale);
5258         *outheight = (int)ceil(height * scale);
5259 }
5260
5261 void R_Mesh_SetMainRenderTargets(void)
5262 {
5263         if (r_bloomstate.fbo_framebuffer)
5264                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5265         else
5266                 R_Mesh_ResetRenderTargets();
5267 }
5268
5269 void R_SetupView(qboolean allowwaterclippingplane)
5270 {
5271         const float *customclipplane = NULL;
5272         float plane[4];
5273         int scaledwidth, scaledheight;
5274         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5275         {
5276                 // LordHavoc: couldn't figure out how to make this approach the
5277                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5278                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5279                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5280                         dist = r_refdef.view.clipplane.dist;
5281                 plane[0] = r_refdef.view.clipplane.normal[0];
5282                 plane[1] = r_refdef.view.clipplane.normal[1];
5283                 plane[2] = r_refdef.view.clipplane.normal[2];
5284                 plane[3] = -dist;
5285                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5286         }
5287
5288         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5289         if (!r_refdef.view.useperspective)
5290                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5291         else if (vid.stencil && r_useinfinitefarclip.integer)
5292                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5293         else
5294                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5295         R_Mesh_SetMainRenderTargets();
5296         R_SetViewport(&r_refdef.view.viewport);
5297         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5298         {
5299                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5300                 float screenplane[4];
5301                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5302                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5303                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5304                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5305                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5306         }
5307 }
5308
5309 void R_EntityMatrix(const matrix4x4_t *matrix)
5310 {
5311         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5312         {
5313                 gl_modelmatrixchanged = false;
5314                 gl_modelmatrix = *matrix;
5315                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5316                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5317                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5318                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5319                 CHECKGLERROR
5320                 switch(vid.renderpath)
5321                 {
5322                 case RENDERPATH_D3D9:
5323 #ifdef SUPPORTD3D
5324                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5325                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5326 #endif
5327                         break;
5328                 case RENDERPATH_D3D10:
5329                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5330                         break;
5331                 case RENDERPATH_D3D11:
5332                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5333                         break;
5334                 case RENDERPATH_GL11:
5335                 case RENDERPATH_GL13:
5336                 case RENDERPATH_GLES1:
5337                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5338                         break;
5339                 case RENDERPATH_SOFT:
5340                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5341                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5342                         break;
5343                 case RENDERPATH_GL20:
5344                 case RENDERPATH_GLES2:
5345                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5346                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5347                         break;
5348                 }
5349         }
5350 }
5351
5352 void R_ResetViewRendering2D(void)
5353 {
5354         r_viewport_t viewport;
5355         DrawQ_Finish();
5356
5357         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5358         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
5359         R_Mesh_ResetRenderTargets();
5360         R_SetViewport(&viewport);
5361         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5362         GL_Color(1, 1, 1, 1);
5363         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5364         GL_BlendFunc(GL_ONE, GL_ZERO);
5365         GL_ScissorTest(false);
5366         GL_DepthMask(false);
5367         GL_DepthRange(0, 1);
5368         GL_DepthTest(false);
5369         GL_DepthFunc(GL_LEQUAL);
5370         R_EntityMatrix(&identitymatrix);
5371         R_Mesh_ResetTextureState();
5372         GL_PolygonOffset(0, 0);
5373         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5374         switch(vid.renderpath)
5375         {
5376         case RENDERPATH_GL11:
5377         case RENDERPATH_GL13:
5378         case RENDERPATH_GL20:
5379         case RENDERPATH_GLES1:
5380         case RENDERPATH_GLES2:
5381                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5382                 break;
5383         case RENDERPATH_D3D9:
5384         case RENDERPATH_D3D10:
5385         case RENDERPATH_D3D11:
5386         case RENDERPATH_SOFT:
5387                 break;
5388         }
5389         GL_CullFace(GL_NONE);
5390 }
5391
5392 void R_ResetViewRendering3D(void)
5393 {
5394         DrawQ_Finish();
5395
5396         R_SetupView(true);
5397         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5398         GL_Color(1, 1, 1, 1);
5399         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5400         GL_BlendFunc(GL_ONE, GL_ZERO);
5401         GL_ScissorTest(true);
5402         GL_DepthMask(true);
5403         GL_DepthRange(0, 1);
5404         GL_DepthTest(true);
5405         GL_DepthFunc(GL_LEQUAL);
5406         R_EntityMatrix(&identitymatrix);
5407         R_Mesh_ResetTextureState();
5408         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5409         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5410         switch(vid.renderpath)
5411         {
5412         case RENDERPATH_GL11:
5413         case RENDERPATH_GL13:
5414         case RENDERPATH_GL20:
5415         case RENDERPATH_GLES1:
5416         case RENDERPATH_GLES2:
5417                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5418                 break;
5419         case RENDERPATH_D3D9:
5420         case RENDERPATH_D3D10:
5421         case RENDERPATH_D3D11:
5422         case RENDERPATH_SOFT:
5423                 break;
5424         }
5425         GL_CullFace(r_refdef.view.cullface_back);
5426 }
5427
5428 /*
5429 ================
5430 R_RenderView_UpdateViewVectors
5431 ================
5432 */
5433 static void R_RenderView_UpdateViewVectors(void)
5434 {
5435         // break apart the view matrix into vectors for various purposes
5436         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5437         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5438         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5439         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5440         // make an inverted copy of the view matrix for tracking sprites
5441         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5442 }
5443
5444 void R_RenderScene(void);
5445 void R_RenderWaterPlanes(void);
5446
5447 static void R_Water_StartFrame(void)
5448 {
5449         int i;
5450         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5451         r_waterstate_waterplane_t *p;
5452
5453         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5454                 return;
5455
5456         switch(vid.renderpath)
5457         {
5458         case RENDERPATH_GL20:
5459         case RENDERPATH_D3D9:
5460         case RENDERPATH_D3D10:
5461         case RENDERPATH_D3D11:
5462         case RENDERPATH_SOFT:
5463         case RENDERPATH_GLES2:
5464                 break;
5465         case RENDERPATH_GL11:
5466         case RENDERPATH_GL13:
5467         case RENDERPATH_GLES1:
5468                 return;
5469         }
5470
5471         // set waterwidth and waterheight to the water resolution that will be
5472         // used (often less than the screen resolution for faster rendering)
5473         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5474
5475         // calculate desired texture sizes
5476         // can't use water if the card does not support the texture size
5477         if (!r_water.integer || r_showsurfaces.integer)
5478                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5479         else if (vid.support.arb_texture_non_power_of_two)
5480         {
5481                 texturewidth = waterwidth;
5482                 textureheight = waterheight;
5483                 camerawidth = waterwidth;
5484                 cameraheight = waterheight;
5485         }
5486         else
5487         {
5488                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5489                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5490                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5491                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5492         }
5493
5494         // allocate textures as needed
5495         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5496         {
5497                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5498                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5499                 {
5500                         if (p->texture_refraction)
5501                                 R_FreeTexture(p->texture_refraction);
5502                         p->texture_refraction = NULL;
5503                         if (p->texture_reflection)
5504                                 R_FreeTexture(p->texture_reflection);
5505                         p->texture_reflection = NULL;
5506                         if (p->texture_camera)
5507                                 R_FreeTexture(p->texture_camera);
5508                         p->texture_camera = NULL;
5509                 }
5510                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5511                 r_waterstate.texturewidth = texturewidth;
5512                 r_waterstate.textureheight = textureheight;
5513                 r_waterstate.camerawidth = camerawidth;
5514                 r_waterstate.cameraheight = cameraheight;
5515         }
5516
5517         if (r_waterstate.texturewidth)
5518         {
5519                 int scaledwidth, scaledheight;
5520
5521                 r_waterstate.enabled = true;
5522
5523                 // when doing a reduced render (HDR) we want to use a smaller area
5524                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5525                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5526                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5527
5528                 // set up variables that will be used in shader setup
5529                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5530                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5531                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5532                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5533         }
5534
5535         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5536         r_waterstate.numwaterplanes = 0;
5537 }
5538
5539 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5540 {
5541         int triangleindex, planeindex;
5542         const int *e;
5543         vec3_t vert[3];
5544         vec3_t normal;
5545         vec3_t center;
5546         mplane_t plane;
5547         r_waterstate_waterplane_t *p;
5548         texture_t *t = R_GetCurrentTexture(surface->texture);
5549
5550         // just use the first triangle with a valid normal for any decisions
5551         VectorClear(normal);
5552         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5553         {
5554                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5555                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5556                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5557                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5558                 if (VectorLength2(normal) >= 0.001)
5559                         break;
5560         }
5561
5562         VectorCopy(normal, plane.normal);
5563         VectorNormalize(plane.normal);
5564         plane.dist = DotProduct(vert[0], plane.normal);
5565         PlaneClassify(&plane);
5566         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5567         {
5568                 // skip backfaces (except if nocullface is set)
5569                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5570                         return;
5571                 VectorNegate(plane.normal, plane.normal);
5572                 plane.dist *= -1;
5573                 PlaneClassify(&plane);
5574         }
5575
5576
5577         // find a matching plane if there is one
5578         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5579                 if(p->camera_entity == t->camera_entity)
5580                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5581                                 break;
5582         if (planeindex >= r_waterstate.maxwaterplanes)
5583                 return; // nothing we can do, out of planes
5584
5585         // if this triangle does not fit any known plane rendered this frame, add one
5586         if (planeindex >= r_waterstate.numwaterplanes)
5587         {
5588                 // store the new plane
5589                 r_waterstate.numwaterplanes++;
5590                 p->plane = plane;
5591                 // clear materialflags and pvs
5592                 p->materialflags = 0;
5593                 p->pvsvalid = false;
5594                 p->camera_entity = t->camera_entity;
5595                 VectorCopy(surface->mins, p->mins);
5596                 VectorCopy(surface->maxs, p->maxs);
5597         }
5598         else
5599         {
5600                 // merge mins/maxs
5601                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5602                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5603                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5604                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5605                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5606                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5607         }
5608         // merge this surface's materialflags into the waterplane
5609         p->materialflags |= t->currentmaterialflags;
5610         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5611         {
5612                 // merge this surface's PVS into the waterplane
5613                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5614                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5615                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5616                 {
5617                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5618                         p->pvsvalid = true;
5619                 }
5620         }
5621 }
5622
5623 extern cvar_t r_drawparticles;
5624 extern cvar_t r_drawdecals;
5625
5626 static void R_Water_ProcessPlanes(void)
5627 {
5628         int myscissor[4];
5629         r_refdef_view_t originalview;
5630         r_refdef_view_t myview;
5631         int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5632         r_waterstate_waterplane_t *p;
5633         vec3_t visorigin;
5634
5635         originalview = r_refdef.view;
5636
5637         // lowquality hack, temporarily shut down some cvars and restore afterwards
5638         qualityreduction = r_water_lowquality.integer;
5639         if (qualityreduction > 0)
5640         {
5641                 if (qualityreduction >= 1)
5642                 {
5643                         old_r_shadows = r_shadows.integer;
5644                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5645                         old_r_dlight = r_shadow_realtime_dlight.integer;
5646                         Cvar_SetValueQuick(&r_shadows, 0);
5647                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5648                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5649                 }
5650                 if (qualityreduction >= 2)
5651                 {
5652                         old_r_dynamic = r_dynamic.integer;
5653                         old_r_particles = r_drawparticles.integer;
5654                         old_r_decals = r_drawdecals.integer;
5655                         Cvar_SetValueQuick(&r_dynamic, 0);
5656                         Cvar_SetValueQuick(&r_drawparticles, 0);
5657                         Cvar_SetValueQuick(&r_drawdecals, 0);
5658                 }
5659         }
5660
5661         // make sure enough textures are allocated
5662         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5663         {
5664                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5665                 {
5666                         if (!p->texture_refraction)
5667                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5668                         if (!p->texture_refraction)
5669                                 goto error;
5670                 }
5671                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5672                 {
5673                         if (!p->texture_camera)
5674                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5675                         if (!p->texture_camera)
5676                                 goto error;
5677                 }
5678
5679                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5680                 {
5681                         if (!p->texture_reflection)
5682                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5683                         if (!p->texture_reflection)
5684                                 goto error;
5685                 }
5686         }
5687
5688         // render views
5689         r_refdef.view = originalview;
5690         r_refdef.view.showdebug = false;
5691         r_refdef.view.width = r_waterstate.waterwidth;
5692         r_refdef.view.height = r_waterstate.waterheight;
5693         r_refdef.view.useclipplane = true;
5694         myview = r_refdef.view;
5695         r_waterstate.renderingscene = true;
5696         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5697         {
5698                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5699                 {
5700                         r_refdef.view = myview;
5701                         if(r_water_scissormode.integer)
5702                         {
5703                                 R_SetupView(true);
5704                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5705                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5706                         }
5707
5708                         // render reflected scene and copy into texture
5709                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5710                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5711                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5712                         r_refdef.view.clipplane = p->plane;
5713                         // reverse the cullface settings for this render
5714                         r_refdef.view.cullface_front = GL_FRONT;
5715                         r_refdef.view.cullface_back = GL_BACK;
5716                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5717                         {
5718                                 r_refdef.view.usecustompvs = true;
5719                                 if (p->pvsvalid)
5720                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5721                                 else
5722                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5723                         }
5724
5725                         R_ResetViewRendering3D();
5726                         R_ClearScreen(r_refdef.fogenabled);
5727                         if(r_water_scissormode.integer & 2)
5728                                 R_View_UpdateWithScissor(myscissor);
5729                         else
5730                                 R_View_Update();
5731                         if(r_water_scissormode.integer & 1)
5732                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5733                         R_RenderScene();
5734
5735                         R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5736                 }
5737
5738                 // render the normal view scene and copy into texture
5739                 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
5740                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5741                 {
5742                         r_refdef.view = myview;
5743                         if(r_water_scissormode.integer)
5744                         {
5745                                 R_SetupView(true);
5746                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5747                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5748                         }
5749
5750                         r_waterstate.renderingrefraction = true;
5751
5752                         r_refdef.view.clipplane = p->plane;
5753                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5754                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5755
5756                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5757                         {
5758                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5759                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5760                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5761                                 R_RenderView_UpdateViewVectors();
5762                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5763                                 {
5764                                         r_refdef.view.usecustompvs = true;
5765                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5766                                 }
5767                         }
5768
5769                         PlaneClassify(&r_refdef.view.clipplane);
5770
5771                         R_ResetViewRendering3D();
5772                         R_ClearScreen(r_refdef.fogenabled);
5773                         if(r_water_scissormode.integer & 2)
5774                                 R_View_UpdateWithScissor(myscissor);
5775                         else
5776                                 R_View_Update();
5777                         if(r_water_scissormode.integer & 1)
5778                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5779                         R_RenderScene();
5780
5781                         R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5782                         r_waterstate.renderingrefraction = false;
5783                 }
5784                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5785                 {
5786                         r_refdef.view = myview;
5787
5788                         r_refdef.view.clipplane = p->plane;
5789                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5790                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5791
5792                         r_refdef.view.width = r_waterstate.camerawidth;
5793                         r_refdef.view.height = r_waterstate.cameraheight;
5794                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5795                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5796
5797                         if(p->camera_entity)
5798                         {
5799                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5800                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5801                         }
5802
5803                         // note: all of the view is used for displaying... so
5804                         // there is no use in scissoring
5805
5806                         // reverse the cullface settings for this render
5807                         r_refdef.view.cullface_front = GL_FRONT;
5808                         r_refdef.view.cullface_back = GL_BACK;
5809                         // also reverse the view matrix
5810                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
5811                         R_RenderView_UpdateViewVectors();
5812                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5813                         {
5814                                 r_refdef.view.usecustompvs = true;
5815                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5816                         }
5817                         
5818                         // camera needs no clipplane
5819                         r_refdef.view.useclipplane = false;
5820
5821                         PlaneClassify(&r_refdef.view.clipplane);
5822
5823                         R_ResetViewRendering3D();
5824                         R_ClearScreen(r_refdef.fogenabled);
5825                         R_View_Update();
5826                         R_RenderScene();
5827
5828                         R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5829                         r_waterstate.renderingrefraction = false;
5830                 }
5831
5832         }
5833         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5834         r_waterstate.renderingscene = false;
5835         r_refdef.view = originalview;
5836         R_ResetViewRendering3D();
5837         R_ClearScreen(r_refdef.fogenabled);
5838         R_View_Update();
5839         goto finish;
5840 error:
5841         r_refdef.view = originalview;
5842         r_waterstate.renderingscene = false;
5843         Cvar_SetValueQuick(&r_water, 0);
5844         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5845 finish:
5846         // lowquality hack, restore cvars
5847         if (qualityreduction > 0)
5848         {
5849                 if (qualityreduction >= 1)
5850                 {
5851                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5852                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5853                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5854                 }
5855                 if (qualityreduction >= 2)
5856                 {
5857                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5858                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5859                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5860                 }
5861         }
5862 }
5863
5864 void R_Bloom_StartFrame(void)
5865 {
5866         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5867         int viewwidth, viewheight;
5868         textype_t textype;
5869
5870         if (r_viewscale_fpsscaling.integer)
5871         {
5872                 double actualframetime;
5873                 double targetframetime;
5874                 double adjust;
5875                 actualframetime = r_refdef.lastdrawscreentime;
5876                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5877                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5878                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5879                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5880                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5881                 viewscalefpsadjusted += adjust;
5882                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5883         }
5884         else
5885                 viewscalefpsadjusted = 1.0f;
5886
5887         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5888
5889         switch(vid.renderpath)
5890         {
5891         case RENDERPATH_GL20:
5892         case RENDERPATH_D3D9:
5893         case RENDERPATH_D3D10:
5894         case RENDERPATH_D3D11:
5895         case RENDERPATH_SOFT:
5896         case RENDERPATH_GLES2:
5897                 break;
5898         case RENDERPATH_GL11:
5899         case RENDERPATH_GL13:
5900         case RENDERPATH_GLES1:
5901                 return;
5902         }
5903
5904         // set bloomwidth and bloomheight to the bloom resolution that will be
5905         // used (often less than the screen resolution for faster rendering)
5906         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5907         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5908         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5909         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5910         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5911
5912         // calculate desired texture sizes
5913         if (vid.support.arb_texture_non_power_of_two)
5914         {
5915                 screentexturewidth = vid.width;
5916                 screentextureheight = vid.height;
5917                 bloomtexturewidth = r_bloomstate.bloomwidth;
5918                 bloomtextureheight = r_bloomstate.bloomheight;
5919         }
5920         else
5921         {
5922                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5923                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5924                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5925                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5926         }
5927
5928         if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
5929         {
5930                 Cvar_SetValueQuick(&r_hdr, 0);
5931                 Cvar_SetValueQuick(&r_bloom, 0);
5932                 Cvar_SetValueQuick(&r_motionblur, 0);
5933                 Cvar_SetValueQuick(&r_damageblur, 0);
5934         }
5935
5936         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5937                 screentexturewidth = screentextureheight = 0;
5938         if (!r_hdr.integer && !r_bloom.integer)
5939                 bloomtexturewidth = bloomtextureheight = 0;
5940
5941         textype = TEXTYPE_COLORBUFFER;
5942         switch (vid.renderpath)
5943         {
5944         case RENDERPATH_GL20:
5945         case RENDERPATH_GLES2:
5946                 if (vid.support.ext_framebuffer_object)
5947                 {
5948                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5949                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5950                 }
5951                 break;
5952         case RENDERPATH_GL11:
5953         case RENDERPATH_GL13:
5954         case RENDERPATH_GLES1:
5955         case RENDERPATH_D3D9:
5956         case RENDERPATH_D3D10:
5957         case RENDERPATH_D3D11:
5958         case RENDERPATH_SOFT:
5959                 break;
5960         }
5961
5962         // allocate textures as needed
5963         if (r_bloomstate.screentexturewidth != screentexturewidth
5964          || r_bloomstate.screentextureheight != screentextureheight
5965          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5966          || r_bloomstate.bloomtextureheight != bloomtextureheight
5967          || r_bloomstate.texturetype != textype
5968          || r_bloomstate.viewfbo != r_viewfbo.integer)
5969         {
5970                 if (r_bloomstate.texture_bloom)
5971                         R_FreeTexture(r_bloomstate.texture_bloom);
5972                 r_bloomstate.texture_bloom = NULL;
5973                 if (r_bloomstate.texture_screen)
5974                         R_FreeTexture(r_bloomstate.texture_screen);
5975                 r_bloomstate.texture_screen = NULL;
5976                 if (r_bloomstate.fbo_framebuffer)
5977                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5978                 r_bloomstate.fbo_framebuffer = 0;
5979                 if (r_bloomstate.texture_framebuffercolor)
5980                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5981                 r_bloomstate.texture_framebuffercolor = NULL;
5982                 if (r_bloomstate.texture_framebufferdepth)
5983                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5984                 r_bloomstate.texture_framebufferdepth = NULL;
5985                 r_bloomstate.screentexturewidth = screentexturewidth;
5986                 r_bloomstate.screentextureheight = screentextureheight;
5987                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5988                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5989                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5990                 {
5991                         // FIXME: choose depth bits based on a cvar
5992                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5993                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5994                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5995                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5996                         // render depth into one texture and normalmap into the other
5997                         if (qglDrawBuffer)
5998                         {
5999                                 int status;
6000                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6001                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6002                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
6003                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
6004                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6005                         }
6006                 }
6007                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6008                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6009                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6010                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6011                 r_bloomstate.viewfbo = r_viewfbo.integer;
6012                 r_bloomstate.texturetype = textype;
6013         }
6014
6015         // when doing a reduced render (HDR) we want to use a smaller area
6016         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6017         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6018         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6019         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6020         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6021
6022         // set up a texcoord array for the full resolution screen image
6023         // (we have to keep this around to copy back during final render)
6024         r_bloomstate.screentexcoord2f[0] = 0;
6025         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6026         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6027         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6028         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6029         r_bloomstate.screentexcoord2f[5] = 0;
6030         r_bloomstate.screentexcoord2f[6] = 0;
6031         r_bloomstate.screentexcoord2f[7] = 0;
6032
6033         // set up a texcoord array for the reduced resolution bloom image
6034         // (which will be additive blended over the screen image)
6035         r_bloomstate.bloomtexcoord2f[0] = 0;
6036         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6037         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6038         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6039         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6040         r_bloomstate.bloomtexcoord2f[5] = 0;
6041         r_bloomstate.bloomtexcoord2f[6] = 0;
6042         r_bloomstate.bloomtexcoord2f[7] = 0;
6043
6044         switch(vid.renderpath)
6045         {
6046         case RENDERPATH_GL11:
6047         case RENDERPATH_GL13:
6048         case RENDERPATH_GL20:
6049         case RENDERPATH_SOFT:
6050         case RENDERPATH_GLES1:
6051         case RENDERPATH_GLES2:
6052                 break;
6053         case RENDERPATH_D3D9:
6054         case RENDERPATH_D3D10:
6055         case RENDERPATH_D3D11:
6056                 {
6057                         int i;
6058                         for (i = 0;i < 4;i++)
6059                         {
6060                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6061                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6062                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6063                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6064                         }
6065                 }
6066                 break;
6067         }
6068
6069         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6070         {
6071                 r_bloomstate.enabled = true;
6072                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6073         }
6074
6075         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6076
6077         if (r_bloomstate.fbo_framebuffer)
6078                 r_refdef.view.clear = true;
6079 }
6080
6081 void R_Bloom_CopyBloomTexture(float colorscale)
6082 {
6083         r_refdef.stats.bloom++;
6084
6085         // scale down screen texture to the bloom texture size
6086         CHECKGLERROR
6087         R_Mesh_SetMainRenderTargets();
6088         R_SetViewport(&r_bloomstate.viewport);
6089         GL_BlendFunc(GL_ONE, GL_ZERO);
6090         GL_Color(colorscale, colorscale, colorscale, 1);
6091         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6092         switch(vid.renderpath)
6093         {
6094         case RENDERPATH_GL11:
6095         case RENDERPATH_GL13:
6096         case RENDERPATH_GL20:
6097         case RENDERPATH_GLES1:
6098         case RENDERPATH_GLES2:
6099         case RENDERPATH_SOFT:
6100                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6101                 break;
6102         case RENDERPATH_D3D9:
6103         case RENDERPATH_D3D10:
6104         case RENDERPATH_D3D11:
6105                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6106                 break;
6107         }
6108         // TODO: do boxfilter scale-down in shader?
6109         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6110         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6111         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6112
6113         // we now have a bloom image in the framebuffer
6114         // copy it into the bloom image texture for later processing
6115         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6116         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6117 }
6118
6119 void R_Bloom_CopyHDRTexture(void)
6120 {
6121         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6122         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6123 }
6124
6125 void R_Bloom_MakeTexture(void)
6126 {
6127         int x, range, dir;
6128         float xoffset, yoffset, r, brighten;
6129
6130         r_refdef.stats.bloom++;
6131
6132         R_ResetViewRendering2D();
6133
6134         // we have a bloom image in the framebuffer
6135         CHECKGLERROR
6136         R_SetViewport(&r_bloomstate.viewport);
6137
6138         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6139         {
6140                 x *= 2;
6141                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6142                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6143                 GL_Color(r,r,r,1);
6144                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6145                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6146                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6147                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6148
6149                 // copy the vertically blurred bloom view to a texture
6150                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6151                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6152         }
6153
6154         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6155         brighten = r_bloom_brighten.value;
6156         if (r_bloomstate.hdr)
6157                 brighten *= r_hdr_range.value;
6158         brighten = sqrt(brighten);
6159         if(range >= 1)
6160                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6161         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6162
6163         for (dir = 0;dir < 2;dir++)
6164         {
6165                 // blend on at multiple vertical offsets to achieve a vertical blur
6166                 // TODO: do offset blends using GLSL
6167                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6168                 GL_BlendFunc(GL_ONE, GL_ZERO);
6169                 for (x = -range;x <= range;x++)
6170                 {
6171                         if (!dir){xoffset = 0;yoffset = x;}
6172                         else {xoffset = x;yoffset = 0;}
6173                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6174                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6175                         // compute a texcoord array with the specified x and y offset
6176                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6177                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6178                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6179                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6180                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6181                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6182                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6183                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6184                         // this r value looks like a 'dot' particle, fading sharply to
6185                         // black at the edges
6186                         // (probably not realistic but looks good enough)
6187                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6188                         //r = brighten/(range*2+1);
6189                         r = brighten / (range * 2 + 1);
6190                         if(range >= 1)
6191                                 r *= (1 - x*x/(float)(range*range));
6192                         GL_Color(r, r, r, 1);
6193                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6194                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6195                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6196                         GL_BlendFunc(GL_ONE, GL_ONE);
6197                 }
6198
6199                 // copy the vertically blurred bloom view to a texture
6200                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6201                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6202         }
6203 }
6204
6205 void R_HDR_RenderBloomTexture(void)
6206 {
6207         int oldwidth, oldheight;
6208         float oldcolorscale;
6209         qboolean oldwaterstate;
6210
6211         oldwaterstate = r_waterstate.enabled;
6212         oldcolorscale = r_refdef.view.colorscale;
6213         oldwidth = r_refdef.view.width;
6214         oldheight = r_refdef.view.height;
6215         r_refdef.view.width = r_bloomstate.bloomwidth;
6216         r_refdef.view.height = r_bloomstate.bloomheight;
6217
6218         if(r_hdr.integer < 2)
6219                 r_waterstate.enabled = false;
6220
6221         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6222         // TODO: add exposure compensation features
6223         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6224
6225         r_refdef.view.showdebug = false;
6226         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6227
6228         R_ResetViewRendering3D();
6229
6230         R_ClearScreen(r_refdef.fogenabled);
6231         if (r_timereport_active)
6232                 R_TimeReport("HDRclear");
6233
6234         R_View_Update();
6235         if (r_timereport_active)
6236                 R_TimeReport("visibility");
6237
6238         // only do secondary renders with HDR if r_hdr is 2 or higher
6239         r_waterstate.numwaterplanes = 0;
6240         if (r_waterstate.enabled)
6241                 R_RenderWaterPlanes();
6242
6243         r_refdef.view.showdebug = true;
6244         R_RenderScene();
6245         r_waterstate.numwaterplanes = 0;
6246
6247         R_ResetViewRendering2D();
6248
6249         R_Bloom_CopyHDRTexture();
6250         R_Bloom_MakeTexture();
6251
6252         // restore the view settings
6253         r_waterstate.enabled = oldwaterstate;
6254         r_refdef.view.width = oldwidth;
6255         r_refdef.view.height = oldheight;
6256         r_refdef.view.colorscale = oldcolorscale;
6257
6258         R_ResetViewRendering3D();
6259
6260         R_ClearScreen(r_refdef.fogenabled);
6261         if (r_timereport_active)
6262                 R_TimeReport("viewclear");
6263 }
6264
6265 static void R_BlendView(void)
6266 {
6267         unsigned int permutation;
6268         float uservecs[4][4];
6269
6270         switch (vid.renderpath)
6271         {
6272         case RENDERPATH_GL20:
6273         case RENDERPATH_D3D9:
6274         case RENDERPATH_D3D10:
6275         case RENDERPATH_D3D11:
6276         case RENDERPATH_SOFT:
6277         case RENDERPATH_GLES2:
6278                 permutation =
6279                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6280                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6281                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6282                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6283                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6284
6285                 if (r_bloomstate.texture_screen)
6286                 {
6287                         // make sure the buffer is available
6288                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6289
6290                         R_ResetViewRendering2D();
6291                         R_Mesh_SetMainRenderTargets();
6292
6293                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6294                         {
6295                                 // declare variables
6296                                 float speed;
6297                                 static float avgspeed;
6298
6299                                 speed = VectorLength(cl.movement_velocity);
6300
6301                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6302                                 avgspeed = avgspeed * (1 - cl.motionbluralpha) + speed * cl.motionbluralpha;
6303
6304                                 speed = (avgspeed - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value);
6305                                 speed = bound(0, speed, 1);
6306                                 speed = speed * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6307
6308                                 // calculate values into a standard alpha
6309                                 cl.motionbluralpha = 1 - exp(-
6310                                                 (
6311                                                  (r_motionblur.value * speed / 80)
6312                                                  +
6313                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6314                                                 )
6315                                                 /
6316                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6317                                            );
6318
6319                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6320                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6321                                 // apply the blur
6322                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6323                                 {
6324                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6325                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6326                                         switch(vid.renderpath)
6327                                         {
6328                                         case RENDERPATH_GL11:
6329                                         case RENDERPATH_GL13:
6330                                         case RENDERPATH_GL20:
6331                                         case RENDERPATH_GLES1:
6332                                         case RENDERPATH_GLES2:
6333                                         case RENDERPATH_SOFT:
6334                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6335                                                 break;
6336                                         case RENDERPATH_D3D9:
6337                                         case RENDERPATH_D3D10:
6338                                         case RENDERPATH_D3D11:
6339                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6340                                                 break;
6341                                         }
6342                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6343                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6344                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6345                                 }
6346                         }
6347
6348                         // copy view into the screen texture
6349                         R_Mesh_CopyToTexture(r_bloomstate.texture_screen, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6350                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6351                 }
6352                 else if (!r_bloomstate.texture_bloom)
6353                 {
6354                         // we may still have to do view tint...
6355                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6356                         {
6357                                 // apply a color tint to the whole view
6358                                 R_ResetViewRendering2D();
6359                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6360                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6361                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6362                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6363                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6364                         }
6365                         break; // no screen processing, no bloom, skip it
6366                 }
6367
6368                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6369                 {
6370                         // render simple bloom effect
6371                         // copy the screen and shrink it and darken it for the bloom process
6372                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6373                         // make the bloom texture
6374                         R_Bloom_MakeTexture();
6375                 }
6376
6377 #if _MSC_VER >= 1400
6378 #define sscanf sscanf_s
6379 #endif
6380                 memset(uservecs, 0, sizeof(uservecs));
6381                 if (r_glsl_postprocess_uservec1_enable.integer)
6382                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6383                 if (r_glsl_postprocess_uservec2_enable.integer)
6384                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6385                 if (r_glsl_postprocess_uservec3_enable.integer)
6386                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6387                 if (r_glsl_postprocess_uservec4_enable.integer)
6388                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6389
6390                 R_ResetViewRendering2D();
6391                 GL_Color(1, 1, 1, 1);
6392                 GL_BlendFunc(GL_ONE, GL_ZERO);
6393
6394                 switch(vid.renderpath)
6395                 {
6396                 case RENDERPATH_GL20:
6397                 case RENDERPATH_GLES2:
6398                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6399                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6400                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6401                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6402                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6403                         if (r_glsl_permutation->loc_ViewTintColor           >= 0) qglUniform4f(r_glsl_permutation->loc_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6404                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6405                         if (r_glsl_permutation->loc_UserVec1                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6406                         if (r_glsl_permutation->loc_UserVec2                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6407                         if (r_glsl_permutation->loc_UserVec3                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6408                         if (r_glsl_permutation->loc_UserVec4                >= 0) qglUniform4f(r_glsl_permutation->loc_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6409                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6410                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6411                         if (r_glsl_permutation->loc_BloomColorSubtract      >= 0) qglUniform4f(r_glsl_permutation->loc_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6412                         break;
6413                 case RENDERPATH_D3D9:
6414 #ifdef SUPPORTD3D
6415                         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6416                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6417                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6418                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6419                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6420                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6421                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6422                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6423                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6424                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6425                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6426                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6427                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6428                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6429                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6430 #endif
6431                         break;
6432                 case RENDERPATH_D3D10:
6433                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6434                         break;
6435                 case RENDERPATH_D3D11:
6436                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6437                         break;
6438                 case RENDERPATH_SOFT:
6439                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6440                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6441                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6442                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6443                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6444                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6445                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6446                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6447                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6448                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6449                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6450                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6451                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6452                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6453                         break;
6454                 default:
6455                         break;
6456                 }
6457                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6458                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6459                 break;
6460         case RENDERPATH_GL11:
6461         case RENDERPATH_GL13:
6462         case RENDERPATH_GLES1:
6463                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6464                 {
6465                         // apply a color tint to the whole view
6466                         R_ResetViewRendering2D();
6467                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6468                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6469                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6470                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6471                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6472                 }
6473                 break;
6474         }
6475 }
6476
6477 matrix4x4_t r_waterscrollmatrix;
6478
6479 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6480 {
6481         if (r_refdef.fog_density)
6482         {
6483                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6484                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6485                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6486
6487                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6488                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6489                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6490                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6491
6492                 {
6493                         vec3_t fogvec;
6494                         VectorCopy(r_refdef.fogcolor, fogvec);
6495                         //   color.rgb *= ContrastBoost * SceneBrightness;
6496                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6497                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6498                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6499                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6500                 }
6501         }
6502 }
6503
6504 void R_UpdateVariables(void)
6505 {
6506         R_Textures_Frame();
6507
6508         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6509
6510         r_refdef.farclip = r_farclip_base.value;
6511         if (r_refdef.scene.worldmodel)
6512                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6513         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6514
6515         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6516                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6517         r_refdef.polygonfactor = 0;
6518         r_refdef.polygonoffset = 0;
6519         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6520         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6521
6522         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6523         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6524         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6525         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6526         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6527         if (FAKELIGHT_ENABLED)
6528         {
6529                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6530         }
6531         if (r_showsurfaces.integer)
6532         {
6533                 r_refdef.scene.rtworld = false;
6534                 r_refdef.scene.rtworldshadows = false;
6535                 r_refdef.scene.rtdlight = false;
6536                 r_refdef.scene.rtdlightshadows = false;
6537                 r_refdef.lightmapintensity = 0;
6538         }
6539
6540         if (gamemode == GAME_NEHAHRA)
6541         {
6542                 if (gl_fogenable.integer)
6543                 {
6544                         r_refdef.oldgl_fogenable = true;
6545                         r_refdef.fog_density = gl_fogdensity.value;
6546                         r_refdef.fog_red = gl_fogred.value;
6547                         r_refdef.fog_green = gl_foggreen.value;
6548                         r_refdef.fog_blue = gl_fogblue.value;
6549                         r_refdef.fog_alpha = 1;
6550                         r_refdef.fog_start = 0;
6551                         r_refdef.fog_end = gl_skyclip.value;
6552                         r_refdef.fog_height = 1<<30;
6553                         r_refdef.fog_fadedepth = 128;
6554                 }
6555                 else if (r_refdef.oldgl_fogenable)
6556                 {
6557                         r_refdef.oldgl_fogenable = false;
6558                         r_refdef.fog_density = 0;
6559                         r_refdef.fog_red = 0;
6560                         r_refdef.fog_green = 0;
6561                         r_refdef.fog_blue = 0;
6562                         r_refdef.fog_alpha = 0;
6563                         r_refdef.fog_start = 0;
6564                         r_refdef.fog_end = 0;
6565                         r_refdef.fog_height = 1<<30;
6566                         r_refdef.fog_fadedepth = 128;
6567                 }
6568         }
6569
6570         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6571         r_refdef.fog_start = max(0, r_refdef.fog_start);
6572         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6573
6574         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6575
6576         if (r_refdef.fog_density && r_drawfog.integer)
6577         {
6578                 r_refdef.fogenabled = true;
6579                 // this is the point where the fog reaches 0.9986 alpha, which we
6580                 // consider a good enough cutoff point for the texture
6581                 // (0.9986 * 256 == 255.6)
6582                 if (r_fog_exp2.integer)
6583                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6584                 else
6585                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6586                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6587                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6588                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6589                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6590                         R_BuildFogHeightTexture();
6591                 // fog color was already set
6592                 // update the fog texture
6593                 if (r_refdef.fogmasktable_start != r_refdef.fog_start || r_refdef.fogmasktable_alpha != r_refdef.fog_alpha || r_refdef.fogmasktable_density != r_refdef.fog_density || r_refdef.fogmasktable_range != r_refdef.fogrange)
6594                         R_BuildFogTexture();
6595                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6596                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6597         }
6598         else
6599                 r_refdef.fogenabled = false;
6600
6601         switch(vid.renderpath)
6602         {
6603         case RENDERPATH_GL20:
6604         case RENDERPATH_D3D9:
6605         case RENDERPATH_D3D10:
6606         case RENDERPATH_D3D11:
6607         case RENDERPATH_SOFT:
6608         case RENDERPATH_GLES2:
6609                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6610                 {
6611                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6612                         {
6613                                 // build GLSL gamma texture
6614 #define RAMPWIDTH 256
6615                                 unsigned short ramp[RAMPWIDTH * 3];
6616                                 unsigned char rampbgr[RAMPWIDTH][4];
6617                                 int i;
6618
6619                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6620
6621                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6622                                 for(i = 0; i < RAMPWIDTH; ++i)
6623                                 {
6624                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6625                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6626                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6627                                         rampbgr[i][3] = 0;
6628                                 }
6629                                 if (r_texture_gammaramps)
6630                                 {
6631                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6632                                 }
6633                                 else
6634                                 {
6635                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6636                                 }
6637                         }
6638                 }
6639                 else
6640                 {
6641                         // remove GLSL gamma texture
6642                 }
6643                 break;
6644         case RENDERPATH_GL11:
6645         case RENDERPATH_GL13:
6646         case RENDERPATH_GLES1:
6647                 break;
6648         }
6649 }
6650
6651 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6652 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6653 /*
6654 ================
6655 R_SelectScene
6656 ================
6657 */
6658 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6659         if( scenetype != r_currentscenetype ) {
6660                 // store the old scenetype
6661                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6662                 r_currentscenetype = scenetype;
6663                 // move in the new scene
6664                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6665         }
6666 }
6667
6668 /*
6669 ================
6670 R_GetScenePointer
6671 ================
6672 */
6673 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6674 {
6675         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6676         if( scenetype == r_currentscenetype ) {
6677                 return &r_refdef.scene;
6678         } else {
6679                 return &r_scenes_store[ scenetype ];
6680         }
6681 }
6682
6683 /*
6684 ================
6685 R_RenderView
6686 ================
6687 */
6688 int dpsoftrast_test;
6689 void R_RenderView(void)
6690 {
6691         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6692
6693         dpsoftrast_test = r_test.integer;
6694
6695         if (r_timereport_active)
6696                 R_TimeReport("start");
6697         r_textureframe++; // used only by R_GetCurrentTexture
6698         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6699
6700         if(R_CompileShader_CheckStaticParms())
6701                 R_GLSL_Restart_f();
6702
6703         if (!r_drawentities.integer)
6704                 r_refdef.scene.numentities = 0;
6705
6706         R_AnimCache_ClearCache();
6707         R_FrameData_NewFrame();
6708
6709         /* adjust for stereo display */
6710         if(R_Stereo_Active())
6711         {
6712                 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);
6713                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6714         }
6715
6716         if (r_refdef.view.isoverlay)
6717         {
6718                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6719                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6720                 R_TimeReport("depthclear");
6721
6722                 r_refdef.view.showdebug = false;
6723
6724                 r_waterstate.enabled = false;
6725                 r_waterstate.numwaterplanes = 0;
6726
6727                 R_RenderScene();
6728
6729                 r_refdef.view.matrix = originalmatrix;
6730
6731                 CHECKGLERROR
6732                 return;
6733         }
6734
6735         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6736         {
6737                 r_refdef.view.matrix = originalmatrix;
6738                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6739         }
6740
6741         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6742
6743         R_RenderView_UpdateViewVectors();
6744
6745         R_Shadow_UpdateWorldLightSelection();
6746
6747         R_Bloom_StartFrame();
6748         R_Water_StartFrame();
6749
6750         CHECKGLERROR
6751         if (r_timereport_active)
6752                 R_TimeReport("viewsetup");
6753
6754         R_ResetViewRendering3D();
6755
6756         if (r_refdef.view.clear || r_refdef.fogenabled)
6757         {
6758                 R_ClearScreen(r_refdef.fogenabled);
6759                 if (r_timereport_active)
6760                         R_TimeReport("viewclear");
6761         }
6762         r_refdef.view.clear = true;
6763
6764         // this produces a bloom texture to be used in R_BlendView() later
6765         if (r_bloomstate.hdr)
6766         {
6767                 R_HDR_RenderBloomTexture();
6768                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6769                 r_textureframe++; // used only by R_GetCurrentTexture
6770         }
6771
6772         r_refdef.view.showdebug = true;
6773
6774         R_View_Update();
6775         if (r_timereport_active)
6776                 R_TimeReport("visibility");
6777
6778         r_waterstate.numwaterplanes = 0;
6779         if (r_waterstate.enabled)
6780                 R_RenderWaterPlanes();
6781
6782         R_RenderScene();
6783         r_waterstate.numwaterplanes = 0;
6784
6785         R_BlendView();
6786         if (r_timereport_active)
6787                 R_TimeReport("blendview");
6788
6789         GL_Scissor(0, 0, vid.width, vid.height);
6790         GL_ScissorTest(false);
6791
6792         r_refdef.view.matrix = originalmatrix;
6793
6794         CHECKGLERROR
6795 }
6796
6797 void R_RenderWaterPlanes(void)
6798 {
6799         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6800         {
6801                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6802                 if (r_timereport_active)
6803                         R_TimeReport("waterworld");
6804         }
6805
6806         // don't let sound skip if going slow
6807         if (r_refdef.scene.extraupdate)
6808                 S_ExtraUpdate ();
6809
6810         R_DrawModelsAddWaterPlanes();
6811         if (r_timereport_active)
6812                 R_TimeReport("watermodels");
6813
6814         if (r_waterstate.numwaterplanes)
6815         {
6816                 R_Water_ProcessPlanes();
6817                 if (r_timereport_active)
6818                         R_TimeReport("waterscenes");
6819         }
6820 }
6821
6822 extern void R_DrawLightningBeams (void);
6823 extern void VM_CL_AddPolygonsToMeshQueue (void);
6824 extern void R_DrawPortals (void);
6825 extern cvar_t cl_locs_show;
6826 static void R_DrawLocs(void);
6827 static void R_DrawEntityBBoxes(void);
6828 static void R_DrawModelDecals(void);
6829 extern void R_DrawModelShadows(void);
6830 extern void R_DrawModelShadowMaps(void);
6831 extern cvar_t cl_decals_newsystem;
6832 extern qboolean r_shadow_usingdeferredprepass;
6833 void R_RenderScene(void)
6834 {
6835         qboolean shadowmapping = false;
6836
6837         if (r_timereport_active)
6838                 R_TimeReport("beginscene");
6839
6840         r_refdef.stats.renders++;
6841
6842         R_UpdateFogColor();
6843
6844         // don't let sound skip if going slow
6845         if (r_refdef.scene.extraupdate)
6846                 S_ExtraUpdate ();
6847
6848         R_MeshQueue_BeginScene();
6849
6850         R_SkyStartFrame();
6851
6852         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);
6853
6854         if (r_timereport_active)
6855                 R_TimeReport("skystartframe");
6856
6857         if (cl.csqc_vidvars.drawworld)
6858         {
6859                 // don't let sound skip if going slow
6860                 if (r_refdef.scene.extraupdate)
6861                         S_ExtraUpdate ();
6862
6863                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6864                 {
6865                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6866                         if (r_timereport_active)
6867                                 R_TimeReport("worldsky");
6868                 }
6869
6870                 if (R_DrawBrushModelsSky() && r_timereport_active)
6871                         R_TimeReport("bmodelsky");
6872
6873                 if (skyrendermasked && skyrenderlater)
6874                 {
6875                         // we have to force off the water clipping plane while rendering sky
6876                         R_SetupView(false);
6877                         R_Sky();
6878                         R_SetupView(true);
6879                         if (r_timereport_active)
6880                                 R_TimeReport("sky");
6881                 }
6882         }
6883
6884         R_AnimCache_CacheVisibleEntities();
6885         if (r_timereport_active)
6886                 R_TimeReport("animation");
6887
6888         R_Shadow_PrepareLights();
6889         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6890                 R_Shadow_PrepareModelShadows();
6891         if (r_timereport_active)
6892                 R_TimeReport("preparelights");
6893
6894         if (R_Shadow_ShadowMappingEnabled())
6895                 shadowmapping = true;
6896
6897         if (r_shadow_usingdeferredprepass)
6898                 R_Shadow_DrawPrepass();
6899
6900         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6901         {
6902                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6903                 if (r_timereport_active)
6904                         R_TimeReport("worlddepth");
6905         }
6906         if (r_depthfirst.integer >= 2)
6907         {
6908                 R_DrawModelsDepth();
6909                 if (r_timereport_active)
6910                         R_TimeReport("modeldepth");
6911         }
6912
6913         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6914         {
6915                 R_DrawModelShadowMaps();
6916                 R_ResetViewRendering3D();
6917                 // don't let sound skip if going slow
6918                 if (r_refdef.scene.extraupdate)
6919                         S_ExtraUpdate ();
6920         }
6921
6922         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6923         {
6924                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6925                 if (r_timereport_active)
6926                         R_TimeReport("world");
6927         }
6928
6929         // don't let sound skip if going slow
6930         if (r_refdef.scene.extraupdate)
6931                 S_ExtraUpdate ();
6932
6933         R_DrawModels();
6934         if (r_timereport_active)
6935                 R_TimeReport("models");
6936
6937         // don't let sound skip if going slow
6938         if (r_refdef.scene.extraupdate)
6939                 S_ExtraUpdate ();
6940
6941         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6942         {
6943                 R_DrawModelShadows();
6944                 R_ResetViewRendering3D();
6945                 // don't let sound skip if going slow
6946                 if (r_refdef.scene.extraupdate)
6947                         S_ExtraUpdate ();
6948         }
6949
6950         if (!r_shadow_usingdeferredprepass)
6951         {
6952                 R_Shadow_DrawLights();
6953                 if (r_timereport_active)
6954                         R_TimeReport("rtlights");
6955         }
6956
6957         // don't let sound skip if going slow
6958         if (r_refdef.scene.extraupdate)
6959                 S_ExtraUpdate ();
6960
6961         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6962         {
6963                 R_DrawModelShadows();
6964                 R_ResetViewRendering3D();
6965                 // don't let sound skip if going slow
6966                 if (r_refdef.scene.extraupdate)
6967                         S_ExtraUpdate ();
6968         }
6969
6970         if (cl.csqc_vidvars.drawworld)
6971         {
6972                 if (cl_decals_newsystem.integer)
6973                 {
6974                         R_DrawModelDecals();
6975                         if (r_timereport_active)
6976                                 R_TimeReport("modeldecals");
6977                 }
6978                 else
6979                 {
6980                         R_DrawDecals();
6981                         if (r_timereport_active)
6982                                 R_TimeReport("decals");
6983                 }
6984
6985                 R_DrawParticles();
6986                 if (r_timereport_active)
6987                         R_TimeReport("particles");
6988
6989                 R_DrawExplosions();
6990                 if (r_timereport_active)
6991                         R_TimeReport("explosions");
6992
6993                 R_DrawLightningBeams();
6994                 if (r_timereport_active)
6995                         R_TimeReport("lightning");
6996         }
6997
6998         VM_CL_AddPolygonsToMeshQueue();
6999
7000         if (r_refdef.view.showdebug)
7001         {
7002                 if (cl_locs_show.integer)
7003                 {
7004                         R_DrawLocs();
7005                         if (r_timereport_active)
7006                                 R_TimeReport("showlocs");
7007                 }
7008
7009                 if (r_drawportals.integer)
7010                 {
7011                         R_DrawPortals();
7012                         if (r_timereport_active)
7013                                 R_TimeReport("portals");
7014                 }
7015
7016                 if (r_showbboxes.value > 0)
7017                 {
7018                         R_DrawEntityBBoxes();
7019                         if (r_timereport_active)
7020                                 R_TimeReport("bboxes");
7021                 }
7022         }
7023
7024         if (r_transparent.integer)
7025         {
7026                 R_MeshQueue_RenderTransparent();
7027                 if (r_timereport_active)
7028                         R_TimeReport("drawtrans");
7029         }
7030
7031         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))
7032         {
7033                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7034                 if (r_timereport_active)
7035                         R_TimeReport("worlddebug");
7036                 R_DrawModelsDebug();
7037                 if (r_timereport_active)
7038                         R_TimeReport("modeldebug");
7039         }
7040
7041         if (cl.csqc_vidvars.drawworld)
7042         {
7043                 R_Shadow_DrawCoronas();
7044                 if (r_timereport_active)
7045                         R_TimeReport("coronas");
7046         }
7047
7048 #if 0
7049         {
7050                 GL_DepthTest(false);
7051                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7052                 GL_Color(1, 1, 1, 1);
7053                 qglBegin(GL_POLYGON);
7054                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7055                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7056                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7057                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7058                 qglEnd();
7059                 qglBegin(GL_POLYGON);
7060                 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]);
7061                 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]);
7062                 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]);
7063                 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]);
7064                 qglEnd();
7065                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7066         }
7067 #endif
7068
7069         // don't let sound skip if going slow
7070         if (r_refdef.scene.extraupdate)
7071                 S_ExtraUpdate ();
7072
7073         R_ResetViewRendering2D();
7074 }
7075
7076 static const unsigned short bboxelements[36] =
7077 {
7078         5, 1, 3, 5, 3, 7,
7079         6, 2, 0, 6, 0, 4,
7080         7, 3, 2, 7, 2, 6,
7081         4, 0, 1, 4, 1, 5,
7082         4, 5, 7, 4, 7, 6,
7083         1, 0, 2, 1, 2, 3,
7084 };
7085
7086 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7087 {
7088         int i;
7089         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7090
7091         RSurf_ActiveWorldEntity();
7092
7093         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7094         GL_DepthMask(false);
7095         GL_DepthRange(0, 1);
7096         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7097 //      R_Mesh_ResetTextureState();
7098
7099         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7100         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7101         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7102         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7103         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7104         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7105         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7106         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7107         R_FillColors(color4f, 8, cr, cg, cb, ca);
7108         if (r_refdef.fogenabled)
7109         {
7110                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7111                 {
7112                         f1 = RSurf_FogVertex(v);
7113                         f2 = 1 - f1;
7114                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7115                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7116                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7117                 }
7118         }
7119         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7120         R_Mesh_ResetTextureState();
7121         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7122         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7123 }
7124
7125 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7126 {
7127         int i;
7128         float color[4];
7129         prvm_edict_t *edict;
7130         prvm_prog_t *prog_save = prog;
7131
7132         // this function draws bounding boxes of server entities
7133         if (!sv.active)
7134                 return;
7135
7136         GL_CullFace(GL_NONE);
7137         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7138
7139         prog = 0;
7140         SV_VM_Begin();
7141         for (i = 0;i < numsurfaces;i++)
7142         {
7143                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7144                 switch ((int)PRVM_serveredictfloat(edict, solid))
7145                 {
7146                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7147                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7148                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7149                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7150                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7151                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7152                 }
7153                 color[3] *= r_showbboxes.value;
7154                 color[3] = bound(0, color[3], 1);
7155                 GL_DepthTest(!r_showdisabledepthtest.integer);
7156                 GL_CullFace(r_refdef.view.cullface_front);
7157                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7158         }
7159         SV_VM_End();
7160         prog = prog_save;
7161 }
7162
7163 static void R_DrawEntityBBoxes(void)
7164 {
7165         int i;
7166         prvm_edict_t *edict;
7167         vec3_t center;
7168         prvm_prog_t *prog_save = prog;
7169
7170         // this function draws bounding boxes of server entities
7171         if (!sv.active)
7172                 return;
7173
7174         prog = 0;
7175         SV_VM_Begin();
7176         for (i = 0;i < prog->num_edicts;i++)
7177         {
7178                 edict = PRVM_EDICT_NUM(i);
7179                 if (edict->priv.server->free)
7180                         continue;
7181                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7182                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7183                         continue;
7184                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7185                         continue;
7186                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7187                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7188         }
7189         SV_VM_End();
7190         prog = prog_save;
7191 }
7192
7193 static const int nomodelelement3i[24] =
7194 {
7195         5, 2, 0,
7196         5, 1, 2,
7197         5, 0, 3,
7198         5, 3, 1,
7199         0, 2, 4,
7200         2, 1, 4,
7201         3, 0, 4,
7202         1, 3, 4
7203 };
7204
7205 static const unsigned short nomodelelement3s[24] =
7206 {
7207         5, 2, 0,
7208         5, 1, 2,
7209         5, 0, 3,
7210         5, 3, 1,
7211         0, 2, 4,
7212         2, 1, 4,
7213         3, 0, 4,
7214         1, 3, 4
7215 };
7216
7217 static const float nomodelvertex3f[6*3] =
7218 {
7219         -16,   0,   0,
7220          16,   0,   0,
7221           0, -16,   0,
7222           0,  16,   0,
7223           0,   0, -16,
7224           0,   0,  16
7225 };
7226
7227 static const float nomodelcolor4f[6*4] =
7228 {
7229         0.0f, 0.0f, 0.5f, 1.0f,
7230         0.0f, 0.0f, 0.5f, 1.0f,
7231         0.0f, 0.5f, 0.0f, 1.0f,
7232         0.0f, 0.5f, 0.0f, 1.0f,
7233         0.5f, 0.0f, 0.0f, 1.0f,
7234         0.5f, 0.0f, 0.0f, 1.0f
7235 };
7236
7237 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7238 {
7239         int i;
7240         float f1, f2, *c;
7241         float color4f[6*4];
7242
7243         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);
7244
7245         // this is only called once per entity so numsurfaces is always 1, and
7246         // surfacelist is always {0}, so this code does not handle batches
7247
7248         if (rsurface.ent_flags & RENDER_ADDITIVE)
7249         {
7250                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7251                 GL_DepthMask(false);
7252         }
7253         else if (rsurface.colormod[3] < 1)
7254         {
7255                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7256                 GL_DepthMask(false);
7257         }
7258         else
7259         {
7260                 GL_BlendFunc(GL_ONE, GL_ZERO);
7261                 GL_DepthMask(true);
7262         }
7263         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7264         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7265         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7266         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7267         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7268         for (i = 0, c = color4f;i < 6;i++, c += 4)
7269         {
7270                 c[0] *= rsurface.colormod[0];
7271                 c[1] *= rsurface.colormod[1];
7272                 c[2] *= rsurface.colormod[2];
7273                 c[3] *= rsurface.colormod[3];
7274         }
7275         if (r_refdef.fogenabled)
7276         {
7277                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7278                 {
7279                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7280                         f2 = 1 - f1;
7281                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7282                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7283                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7284                 }
7285         }
7286 //      R_Mesh_ResetTextureState();
7287         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7288         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7289         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7290 }
7291
7292 void R_DrawNoModel(entity_render_t *ent)
7293 {
7294         vec3_t org;
7295         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7296         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7297                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7298         else
7299                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7300 }
7301
7302 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7303 {
7304         vec3_t right1, right2, diff, normal;
7305
7306         VectorSubtract (org2, org1, normal);
7307
7308         // calculate 'right' vector for start
7309         VectorSubtract (r_refdef.view.origin, org1, diff);
7310         CrossProduct (normal, diff, right1);
7311         VectorNormalize (right1);
7312
7313         // calculate 'right' vector for end
7314         VectorSubtract (r_refdef.view.origin, org2, diff);
7315         CrossProduct (normal, diff, right2);
7316         VectorNormalize (right2);
7317
7318         vert[ 0] = org1[0] + width * right1[0];
7319         vert[ 1] = org1[1] + width * right1[1];
7320         vert[ 2] = org1[2] + width * right1[2];
7321         vert[ 3] = org1[0] - width * right1[0];
7322         vert[ 4] = org1[1] - width * right1[1];
7323         vert[ 5] = org1[2] - width * right1[2];
7324         vert[ 6] = org2[0] - width * right2[0];
7325         vert[ 7] = org2[1] - width * right2[1];
7326         vert[ 8] = org2[2] - width * right2[2];
7327         vert[ 9] = org2[0] + width * right2[0];
7328         vert[10] = org2[1] + width * right2[1];
7329         vert[11] = org2[2] + width * right2[2];
7330 }
7331
7332 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)
7333 {
7334         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7335         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7336         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7337         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7338         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7339         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7340         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7341         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7342         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7343         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7344         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7345         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7346 }
7347
7348 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7349 {
7350         int i;
7351         float *vertex3f;
7352         float v[3];
7353         VectorSet(v, x, y, z);
7354         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7355                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7356                         break;
7357         if (i == mesh->numvertices)
7358         {
7359                 if (mesh->numvertices < mesh->maxvertices)
7360                 {
7361                         VectorCopy(v, vertex3f);
7362                         mesh->numvertices++;
7363                 }
7364                 return mesh->numvertices;
7365         }
7366         else
7367                 return i;
7368 }
7369
7370 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7371 {
7372         int i;
7373         int *e, element[3];
7374         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7375         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7376         e = mesh->element3i + mesh->numtriangles * 3;
7377         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7378         {
7379                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7380                 if (mesh->numtriangles < mesh->maxtriangles)
7381                 {
7382                         *e++ = element[0];
7383                         *e++ = element[1];
7384                         *e++ = element[2];
7385                         mesh->numtriangles++;
7386                 }
7387                 element[1] = element[2];
7388         }
7389 }
7390
7391 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7392 {
7393         int i;
7394         int *e, element[3];
7395         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7396         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7397         e = mesh->element3i + mesh->numtriangles * 3;
7398         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7399         {
7400                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7401                 if (mesh->numtriangles < mesh->maxtriangles)
7402                 {
7403                         *e++ = element[0];
7404                         *e++ = element[1];
7405                         *e++ = element[2];
7406                         mesh->numtriangles++;
7407                 }
7408                 element[1] = element[2];
7409         }
7410 }
7411
7412 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7413 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7414 {
7415         int planenum, planenum2;
7416         int w;
7417         int tempnumpoints;
7418         mplane_t *plane, *plane2;
7419         double maxdist;
7420         double temppoints[2][256*3];
7421         // figure out how large a bounding box we need to properly compute this brush
7422         maxdist = 0;
7423         for (w = 0;w < numplanes;w++)
7424                 maxdist = max(maxdist, fabs(planes[w].dist));
7425         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7426         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7427         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7428         {
7429                 w = 0;
7430                 tempnumpoints = 4;
7431                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7432                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7433                 {
7434                         if (planenum2 == planenum)
7435                                 continue;
7436                         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);
7437                         w = !w;
7438                 }
7439                 if (tempnumpoints < 3)
7440                         continue;
7441                 // generate elements forming a triangle fan for this polygon
7442                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7443         }
7444 }
7445
7446 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)
7447 {
7448         texturelayer_t *layer;
7449         layer = t->currentlayers + t->currentnumlayers++;
7450         layer->type = type;
7451         layer->depthmask = depthmask;
7452         layer->blendfunc1 = blendfunc1;
7453         layer->blendfunc2 = blendfunc2;
7454         layer->texture = texture;
7455         layer->texmatrix = *matrix;
7456         layer->color[0] = r;
7457         layer->color[1] = g;
7458         layer->color[2] = b;
7459         layer->color[3] = a;
7460 }
7461
7462 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7463 {
7464         if(parms[0] == 0 && parms[1] == 0)
7465                 return false;
7466         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7467                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7468                         return false;
7469         return true;
7470 }
7471
7472 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7473 {
7474         double index, f;
7475         index = parms[2] + rsurface.shadertime * parms[3];
7476         index -= floor(index);
7477         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7478         {
7479         default:
7480         case Q3WAVEFUNC_NONE:
7481         case Q3WAVEFUNC_NOISE:
7482         case Q3WAVEFUNC_COUNT:
7483                 f = 0;
7484                 break;
7485         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7486         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7487         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7488         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7489         case Q3WAVEFUNC_TRIANGLE:
7490                 index *= 4;
7491                 f = index - floor(index);
7492                 if (index < 1)
7493                         f = f;
7494                 else if (index < 2)
7495                         f = 1 - f;
7496                 else if (index < 3)
7497                         f = -f;
7498                 else
7499                         f = -(1 - f);
7500                 break;
7501         }
7502         f = parms[0] + parms[1] * f;
7503         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7504                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7505         return (float) f;
7506 }
7507
7508 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7509 {
7510         int w, h, idx;
7511         double f;
7512         double offsetd[2];
7513         float tcmat[12];
7514         matrix4x4_t matrix, temp;
7515         switch(tcmod->tcmod)
7516         {
7517                 case Q3TCMOD_COUNT:
7518                 case Q3TCMOD_NONE:
7519                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7520                                 matrix = r_waterscrollmatrix;
7521                         else
7522                                 matrix = identitymatrix;
7523                         break;
7524                 case Q3TCMOD_ENTITYTRANSLATE:
7525                         // this is used in Q3 to allow the gamecode to control texcoord
7526                         // scrolling on the entity, which is not supported in darkplaces yet.
7527                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7528                         break;
7529                 case Q3TCMOD_ROTATE:
7530                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7531                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7532                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7533                         break;
7534                 case Q3TCMOD_SCALE:
7535                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7536                         break;
7537                 case Q3TCMOD_SCROLL:
7538                         // extra care is needed because of precision breakdown with large values of time
7539                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7540                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7541                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7542                         break;
7543                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7544                         w = (int) tcmod->parms[0];
7545                         h = (int) tcmod->parms[1];
7546                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7547                         f = f - floor(f);
7548                         idx = (int) floor(f * w * h);
7549                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7550                         break;
7551                 case Q3TCMOD_STRETCH:
7552                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7553                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7554                         break;
7555                 case Q3TCMOD_TRANSFORM:
7556                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7557                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7558                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7559                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7560                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7561                         break;
7562                 case Q3TCMOD_TURBULENT:
7563                         // this is handled in the RSurf_PrepareVertices function
7564                         matrix = identitymatrix;
7565                         break;
7566         }
7567         temp = *texmatrix;
7568         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7569 }
7570
7571 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7572 {
7573         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7574         char name[MAX_QPATH];
7575         skinframe_t *skinframe;
7576         unsigned char pixels[296*194];
7577         strlcpy(cache->name, skinname, sizeof(cache->name));
7578         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7579         if (developer_loading.integer)
7580                 Con_Printf("loading %s\n", name);
7581         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7582         if (!skinframe || !skinframe->base)
7583         {
7584                 unsigned char *f;
7585                 fs_offset_t filesize;
7586                 skinframe = NULL;
7587                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7588                 if (f)
7589                 {
7590                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7591                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7592                         Mem_Free(f);
7593                 }
7594         }
7595         cache->skinframe = skinframe;
7596 }
7597
7598 texture_t *R_GetCurrentTexture(texture_t *t)
7599 {
7600         int i;
7601         const entity_render_t *ent = rsurface.entity;
7602         dp_model_t *model = ent->model;
7603         q3shaderinfo_layer_tcmod_t *tcmod;
7604
7605         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7606                 return t->currentframe;
7607         t->update_lastrenderframe = r_textureframe;
7608         t->update_lastrenderentity = (void *)ent;
7609
7610         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7611                 t->camera_entity = ent->entitynumber;
7612         else
7613                 t->camera_entity = 0;
7614
7615         // switch to an alternate material if this is a q1bsp animated material
7616         {
7617                 texture_t *texture = t;
7618                 int s = rsurface.ent_skinnum;
7619                 if ((unsigned int)s >= (unsigned int)model->numskins)
7620                         s = 0;
7621                 if (model->skinscenes)
7622                 {
7623                         if (model->skinscenes[s].framecount > 1)
7624                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7625                         else
7626                                 s = model->skinscenes[s].firstframe;
7627                 }
7628                 if (s > 0)
7629                         t = t + s * model->num_surfaces;
7630                 if (t->animated)
7631                 {
7632                         // use an alternate animation if the entity's frame is not 0,
7633                         // and only if the texture has an alternate animation
7634                         if (rsurface.ent_alttextures && t->anim_total[1])
7635                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7636                         else
7637                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7638                 }
7639                 texture->currentframe = t;
7640         }
7641
7642         // update currentskinframe to be a qw skin or animation frame
7643         if (rsurface.ent_qwskin >= 0)
7644         {
7645                 i = rsurface.ent_qwskin;
7646                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7647                 {
7648                         r_qwskincache_size = cl.maxclients;
7649                         if (r_qwskincache)
7650                                 Mem_Free(r_qwskincache);
7651                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7652                 }
7653                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7654                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7655                 t->currentskinframe = r_qwskincache[i].skinframe;
7656                 if (t->currentskinframe == NULL)
7657                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7658         }
7659         else if (t->numskinframes >= 2)
7660                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7661         if (t->backgroundnumskinframes >= 2)
7662                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7663
7664         t->currentmaterialflags = t->basematerialflags;
7665         t->currentalpha = rsurface.colormod[3];
7666         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7667                 t->currentalpha *= r_wateralpha.value;
7668         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7669                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7670         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7671                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7672         if (!(rsurface.ent_flags & RENDER_LIGHT))
7673                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7674         else if (FAKELIGHT_ENABLED)
7675         {
7676                 // no modellight if using fakelight for the map
7677         }
7678         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7679         {
7680                 // pick a model lighting mode
7681                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7682                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7683                 else
7684                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7685         }
7686         if (rsurface.ent_flags & RENDER_ADDITIVE)
7687                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7688         else if (t->currentalpha < 1)
7689                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7690         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7691                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7692         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7693                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7694         if (t->backgroundnumskinframes)
7695                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7696         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7697         {
7698                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7699                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7700         }
7701         else
7702                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7703         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7704         {
7705                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7706                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7707         }
7708         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7709                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7710
7711         // there is no tcmod
7712         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7713         {
7714                 t->currenttexmatrix = r_waterscrollmatrix;
7715                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7716         }
7717         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7718         {
7719                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7720                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7721         }
7722
7723         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7724                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7725         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7726                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7727
7728         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7729         if (t->currentskinframe->qpixels)
7730                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7731         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7732         if (!t->basetexture)
7733                 t->basetexture = r_texture_notexture;
7734         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7735         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7736         t->nmaptexture = t->currentskinframe->nmap;
7737         if (!t->nmaptexture)
7738                 t->nmaptexture = r_texture_blanknormalmap;
7739         t->glosstexture = r_texture_black;
7740         t->glowtexture = t->currentskinframe->glow;
7741         t->fogtexture = t->currentskinframe->fog;
7742         t->reflectmasktexture = t->currentskinframe->reflect;
7743         if (t->backgroundnumskinframes)
7744         {
7745                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7746                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7747                 t->backgroundglosstexture = r_texture_black;
7748                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7749                 if (!t->backgroundnmaptexture)
7750                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7751         }
7752         else
7753         {
7754                 t->backgroundbasetexture = r_texture_white;
7755                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7756                 t->backgroundglosstexture = r_texture_black;
7757                 t->backgroundglowtexture = NULL;
7758         }
7759         t->specularpower = r_shadow_glossexponent.value;
7760         // TODO: store reference values for these in the texture?
7761         t->specularscale = 0;
7762         if (r_shadow_gloss.integer > 0)
7763         {
7764                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7765                 {
7766                         if (r_shadow_glossintensity.value > 0)
7767                         {
7768                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7769                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7770                                 t->specularscale = r_shadow_glossintensity.value;
7771                         }
7772                 }
7773                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7774                 {
7775                         t->glosstexture = r_texture_white;
7776                         t->backgroundglosstexture = r_texture_white;
7777                         t->specularscale = r_shadow_gloss2intensity.value;
7778                         t->specularpower = r_shadow_gloss2exponent.value;
7779                 }
7780         }
7781         t->specularscale *= t->specularscalemod;
7782         t->specularpower *= t->specularpowermod;
7783
7784         // lightmaps mode looks bad with dlights using actual texturing, so turn
7785         // off the colormap and glossmap, but leave the normalmap on as it still
7786         // accurately represents the shading involved
7787         if (gl_lightmaps.integer)
7788         {
7789                 t->basetexture = r_texture_grey128;
7790                 t->pantstexture = r_texture_black;
7791                 t->shirttexture = r_texture_black;
7792                 t->nmaptexture = r_texture_blanknormalmap;
7793                 t->glosstexture = r_texture_black;
7794                 t->glowtexture = NULL;
7795                 t->fogtexture = NULL;
7796                 t->reflectmasktexture = NULL;
7797                 t->backgroundbasetexture = NULL;
7798                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7799                 t->backgroundglosstexture = r_texture_black;
7800                 t->backgroundglowtexture = NULL;
7801                 t->specularscale = 0;
7802                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7803         }
7804
7805         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7806         VectorClear(t->dlightcolor);
7807         t->currentnumlayers = 0;
7808         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7809         {
7810                 int blendfunc1, blendfunc2;
7811                 qboolean depthmask;
7812                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7813                 {
7814                         blendfunc1 = GL_SRC_ALPHA;
7815                         blendfunc2 = GL_ONE;
7816                 }
7817                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7818                 {
7819                         blendfunc1 = GL_SRC_ALPHA;
7820                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7821                 }
7822                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7823                 {
7824                         blendfunc1 = t->customblendfunc[0];
7825                         blendfunc2 = t->customblendfunc[1];
7826                 }
7827                 else
7828                 {
7829                         blendfunc1 = GL_ONE;
7830                         blendfunc2 = GL_ZERO;
7831                 }
7832                 // don't colormod evilblend textures
7833                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7834                         VectorSet(t->lightmapcolor, 1, 1, 1);
7835                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7836                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7837                 {
7838                         // fullbright is not affected by r_refdef.lightmapintensity
7839                         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]);
7840                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7841                                 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]);
7842                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7843                                 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]);
7844                 }
7845                 else
7846                 {
7847                         vec3_t ambientcolor;
7848                         float colorscale;
7849                         // set the color tint used for lights affecting this surface
7850                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7851                         colorscale = 2;
7852                         // q3bsp has no lightmap updates, so the lightstylevalue that
7853                         // would normally be baked into the lightmap must be
7854                         // applied to the color
7855                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7856                         if (model->type == mod_brushq3)
7857                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7858                         colorscale *= r_refdef.lightmapintensity;
7859                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7860                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7861                         // basic lit geometry
7862                         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]);
7863                         // add pants/shirt if needed
7864                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7865                                 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]);
7866                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7867                                 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]);
7868                         // now add ambient passes if needed
7869                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7870                         {
7871                                 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]);
7872                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7873                                         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]);
7874                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7875                                         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]);
7876                         }
7877                 }
7878                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7879                         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]);
7880                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7881                 {
7882                         // if this is opaque use alpha blend which will darken the earlier
7883                         // passes cheaply.
7884                         //
7885                         // if this is an alpha blended material, all the earlier passes
7886                         // were darkened by fog already, so we only need to add the fog
7887                         // color ontop through the fog mask texture
7888                         //
7889                         // if this is an additive blended material, all the earlier passes
7890                         // were darkened by fog already, and we should not add fog color
7891                         // (because the background was not darkened, there is no fog color
7892                         // that was lost behind it).
7893                         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]);
7894                 }
7895         }
7896
7897         return t->currentframe;
7898 }
7899
7900 rsurfacestate_t rsurface;
7901
7902 void RSurf_ActiveWorldEntity(void)
7903 {
7904         dp_model_t *model = r_refdef.scene.worldmodel;
7905         //if (rsurface.entity == r_refdef.scene.worldentity)
7906         //      return;
7907         rsurface.entity = r_refdef.scene.worldentity;
7908         rsurface.skeleton = NULL;
7909         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7910         rsurface.ent_skinnum = 0;
7911         rsurface.ent_qwskin = -1;
7912         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7913         rsurface.shadertime = r_refdef.scene.time;
7914         rsurface.matrix = identitymatrix;
7915         rsurface.inversematrix = identitymatrix;
7916         rsurface.matrixscale = 1;
7917         rsurface.inversematrixscale = 1;
7918         R_EntityMatrix(&identitymatrix);
7919         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7920         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7921         rsurface.fograngerecip = r_refdef.fograngerecip;
7922         rsurface.fogheightfade = r_refdef.fogheightfade;
7923         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7924         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7925         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7926         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7927         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7928         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7929         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7930         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7931         rsurface.colormod[3] = 1;
7932         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);
7933         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7934         rsurface.frameblend[0].lerp = 1;
7935         rsurface.ent_alttextures = false;
7936         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7937         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7938         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7939         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7940         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7941         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7942         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7943         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7944         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7945         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7946         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7947         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7948         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7949         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7950         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7951         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7952         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7953         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7954         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7955         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7956         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7957         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7958         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7959         rsurface.modelelement3i = model->surfmesh.data_element3i;
7960         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7961         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7962         rsurface.modelelement3s = model->surfmesh.data_element3s;
7963         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7964         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7965         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7966         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7967         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7968         rsurface.modelsurfaces = model->data_surfaces;
7969         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7970         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7971         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7972         rsurface.modelgeneratedvertex = false;
7973         rsurface.batchgeneratedvertex = false;
7974         rsurface.batchfirstvertex = 0;
7975         rsurface.batchnumvertices = 0;
7976         rsurface.batchfirsttriangle = 0;
7977         rsurface.batchnumtriangles = 0;
7978         rsurface.batchvertex3f  = NULL;
7979         rsurface.batchvertex3f_vertexbuffer = NULL;
7980         rsurface.batchvertex3f_bufferoffset = 0;
7981         rsurface.batchsvector3f = NULL;
7982         rsurface.batchsvector3f_vertexbuffer = NULL;
7983         rsurface.batchsvector3f_bufferoffset = 0;
7984         rsurface.batchtvector3f = NULL;
7985         rsurface.batchtvector3f_vertexbuffer = NULL;
7986         rsurface.batchtvector3f_bufferoffset = 0;
7987         rsurface.batchnormal3f  = NULL;
7988         rsurface.batchnormal3f_vertexbuffer = NULL;
7989         rsurface.batchnormal3f_bufferoffset = 0;
7990         rsurface.batchlightmapcolor4f = NULL;
7991         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
7992         rsurface.batchlightmapcolor4f_bufferoffset = 0;
7993         rsurface.batchtexcoordtexture2f = NULL;
7994         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
7995         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
7996         rsurface.batchtexcoordlightmap2f = NULL;
7997         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
7998         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
7999         rsurface.batchvertexmesh = NULL;
8000         rsurface.batchvertexmeshbuffer = NULL;
8001         rsurface.batchvertex3fbuffer = NULL;
8002         rsurface.batchelement3i = NULL;
8003         rsurface.batchelement3i_indexbuffer = NULL;
8004         rsurface.batchelement3i_bufferoffset = 0;
8005         rsurface.batchelement3s = NULL;
8006         rsurface.batchelement3s_indexbuffer = NULL;
8007         rsurface.batchelement3s_bufferoffset = 0;
8008         rsurface.passcolor4f = NULL;
8009         rsurface.passcolor4f_vertexbuffer = NULL;
8010         rsurface.passcolor4f_bufferoffset = 0;
8011 }
8012
8013 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8014 {
8015         dp_model_t *model = ent->model;
8016         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8017         //      return;
8018         rsurface.entity = (entity_render_t *)ent;
8019         rsurface.skeleton = ent->skeleton;
8020         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8021         rsurface.ent_skinnum = ent->skinnum;
8022         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;
8023         rsurface.ent_flags = ent->flags;
8024         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8025         rsurface.matrix = ent->matrix;
8026         rsurface.inversematrix = ent->inversematrix;
8027         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8028         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8029         R_EntityMatrix(&rsurface.matrix);
8030         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8031         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8032         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8033         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8034         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8035         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8036         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8037         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8038         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8039         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8040         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8041         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8042         rsurface.colormod[3] = ent->alpha;
8043         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8044         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8045         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8046         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8047         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8048         if (ent->model->brush.submodel && !prepass)
8049         {
8050                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8051                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8052         }
8053         if (model->surfmesh.isanimated && model->AnimateVertices)
8054         {
8055                 if (ent->animcache_vertex3f)
8056                 {
8057                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8058                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8059                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8060                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8061                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8062                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8063                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8064                 }
8065                 else if (wanttangents)
8066                 {
8067                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8068                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8069                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8070                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8071                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8072                         rsurface.modelvertexmesh = NULL;
8073                         rsurface.modelvertexmeshbuffer = NULL;
8074                         rsurface.modelvertex3fbuffer = NULL;
8075                 }
8076                 else if (wantnormals)
8077                 {
8078                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8079                         rsurface.modelsvector3f = NULL;
8080                         rsurface.modeltvector3f = NULL;
8081                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8082                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8083                         rsurface.modelvertexmesh = NULL;
8084                         rsurface.modelvertexmeshbuffer = NULL;
8085                         rsurface.modelvertex3fbuffer = NULL;
8086                 }
8087                 else
8088                 {
8089                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8090                         rsurface.modelsvector3f = NULL;
8091                         rsurface.modeltvector3f = NULL;
8092                         rsurface.modelnormal3f = NULL;
8093                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8094                         rsurface.modelvertexmesh = NULL;
8095                         rsurface.modelvertexmeshbuffer = NULL;
8096                         rsurface.modelvertex3fbuffer = NULL;
8097                 }
8098                 rsurface.modelvertex3f_vertexbuffer = 0;
8099                 rsurface.modelvertex3f_bufferoffset = 0;
8100                 rsurface.modelsvector3f_vertexbuffer = 0;
8101                 rsurface.modelsvector3f_bufferoffset = 0;
8102                 rsurface.modeltvector3f_vertexbuffer = 0;
8103                 rsurface.modeltvector3f_bufferoffset = 0;
8104                 rsurface.modelnormal3f_vertexbuffer = 0;
8105                 rsurface.modelnormal3f_bufferoffset = 0;
8106                 rsurface.modelgeneratedvertex = true;
8107         }
8108         else
8109         {
8110                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8111                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8112                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8113                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8114                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8115                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8116                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8117                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8118                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8119                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8120                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8121                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8122                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8123                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8124                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8125                 rsurface.modelgeneratedvertex = false;
8126         }
8127         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8128         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8129         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8130         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8131         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8132         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8133         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8134         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8135         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8136         rsurface.modelelement3i = model->surfmesh.data_element3i;
8137         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8138         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8139         rsurface.modelelement3s = model->surfmesh.data_element3s;
8140         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8141         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8142         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8143         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8144         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8145         rsurface.modelsurfaces = model->data_surfaces;
8146         rsurface.batchgeneratedvertex = false;
8147         rsurface.batchfirstvertex = 0;
8148         rsurface.batchnumvertices = 0;
8149         rsurface.batchfirsttriangle = 0;
8150         rsurface.batchnumtriangles = 0;
8151         rsurface.batchvertex3f  = NULL;
8152         rsurface.batchvertex3f_vertexbuffer = NULL;
8153         rsurface.batchvertex3f_bufferoffset = 0;
8154         rsurface.batchsvector3f = NULL;
8155         rsurface.batchsvector3f_vertexbuffer = NULL;
8156         rsurface.batchsvector3f_bufferoffset = 0;
8157         rsurface.batchtvector3f = NULL;
8158         rsurface.batchtvector3f_vertexbuffer = NULL;
8159         rsurface.batchtvector3f_bufferoffset = 0;
8160         rsurface.batchnormal3f  = NULL;
8161         rsurface.batchnormal3f_vertexbuffer = NULL;
8162         rsurface.batchnormal3f_bufferoffset = 0;
8163         rsurface.batchlightmapcolor4f = NULL;
8164         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8165         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8166         rsurface.batchtexcoordtexture2f = NULL;
8167         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8168         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8169         rsurface.batchtexcoordlightmap2f = NULL;
8170         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8171         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8172         rsurface.batchvertexmesh = NULL;
8173         rsurface.batchvertexmeshbuffer = NULL;
8174         rsurface.batchvertex3fbuffer = NULL;
8175         rsurface.batchelement3i = NULL;
8176         rsurface.batchelement3i_indexbuffer = NULL;
8177         rsurface.batchelement3i_bufferoffset = 0;
8178         rsurface.batchelement3s = NULL;
8179         rsurface.batchelement3s_indexbuffer = NULL;
8180         rsurface.batchelement3s_bufferoffset = 0;
8181         rsurface.passcolor4f = NULL;
8182         rsurface.passcolor4f_vertexbuffer = NULL;
8183         rsurface.passcolor4f_bufferoffset = 0;
8184 }
8185
8186 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)
8187 {
8188         rsurface.entity = r_refdef.scene.worldentity;
8189         rsurface.skeleton = NULL;
8190         rsurface.ent_skinnum = 0;
8191         rsurface.ent_qwskin = -1;
8192         rsurface.ent_flags = entflags;
8193         rsurface.shadertime = r_refdef.scene.time - shadertime;
8194         rsurface.modelnumvertices = numvertices;
8195         rsurface.modelnumtriangles = numtriangles;
8196         rsurface.matrix = *matrix;
8197         rsurface.inversematrix = *inversematrix;
8198         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8199         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8200         R_EntityMatrix(&rsurface.matrix);
8201         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8202         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8203         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8204         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8205         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8206         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8207         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8208         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8209         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8210         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8211         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8212         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8213         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);
8214         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8215         rsurface.frameblend[0].lerp = 1;
8216         rsurface.ent_alttextures = false;
8217         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8218         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8219         if (wanttangents)
8220         {
8221                 rsurface.modelvertex3f = (float *)vertex3f;
8222                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8223                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8224                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8225         }
8226         else if (wantnormals)
8227         {
8228                 rsurface.modelvertex3f = (float *)vertex3f;
8229                 rsurface.modelsvector3f = NULL;
8230                 rsurface.modeltvector3f = NULL;
8231                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8232         }
8233         else
8234         {
8235                 rsurface.modelvertex3f = (float *)vertex3f;
8236                 rsurface.modelsvector3f = NULL;
8237                 rsurface.modeltvector3f = NULL;
8238                 rsurface.modelnormal3f = NULL;
8239         }
8240         rsurface.modelvertexmesh = NULL;
8241         rsurface.modelvertexmeshbuffer = NULL;
8242         rsurface.modelvertex3fbuffer = NULL;
8243         rsurface.modelvertex3f_vertexbuffer = 0;
8244         rsurface.modelvertex3f_bufferoffset = 0;
8245         rsurface.modelsvector3f_vertexbuffer = 0;
8246         rsurface.modelsvector3f_bufferoffset = 0;
8247         rsurface.modeltvector3f_vertexbuffer = 0;
8248         rsurface.modeltvector3f_bufferoffset = 0;
8249         rsurface.modelnormal3f_vertexbuffer = 0;
8250         rsurface.modelnormal3f_bufferoffset = 0;
8251         rsurface.modelgeneratedvertex = true;
8252         rsurface.modellightmapcolor4f  = (float *)color4f;
8253         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8254         rsurface.modellightmapcolor4f_bufferoffset = 0;
8255         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8256         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8257         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8258         rsurface.modeltexcoordlightmap2f  = NULL;
8259         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8260         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8261         rsurface.modelelement3i = (int *)element3i;
8262         rsurface.modelelement3i_indexbuffer = NULL;
8263         rsurface.modelelement3i_bufferoffset = 0;
8264         rsurface.modelelement3s = (unsigned short *)element3s;
8265         rsurface.modelelement3s_indexbuffer = NULL;
8266         rsurface.modelelement3s_bufferoffset = 0;
8267         rsurface.modellightmapoffsets = NULL;
8268         rsurface.modelsurfaces = NULL;
8269         rsurface.batchgeneratedvertex = false;
8270         rsurface.batchfirstvertex = 0;
8271         rsurface.batchnumvertices = 0;
8272         rsurface.batchfirsttriangle = 0;
8273         rsurface.batchnumtriangles = 0;
8274         rsurface.batchvertex3f  = NULL;
8275         rsurface.batchvertex3f_vertexbuffer = NULL;
8276         rsurface.batchvertex3f_bufferoffset = 0;
8277         rsurface.batchsvector3f = NULL;
8278         rsurface.batchsvector3f_vertexbuffer = NULL;
8279         rsurface.batchsvector3f_bufferoffset = 0;
8280         rsurface.batchtvector3f = NULL;
8281         rsurface.batchtvector3f_vertexbuffer = NULL;
8282         rsurface.batchtvector3f_bufferoffset = 0;
8283         rsurface.batchnormal3f  = NULL;
8284         rsurface.batchnormal3f_vertexbuffer = NULL;
8285         rsurface.batchnormal3f_bufferoffset = 0;
8286         rsurface.batchlightmapcolor4f = NULL;
8287         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8288         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8289         rsurface.batchtexcoordtexture2f = NULL;
8290         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8291         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8292         rsurface.batchtexcoordlightmap2f = NULL;
8293         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8294         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8295         rsurface.batchvertexmesh = NULL;
8296         rsurface.batchvertexmeshbuffer = NULL;
8297         rsurface.batchvertex3fbuffer = NULL;
8298         rsurface.batchelement3i = NULL;
8299         rsurface.batchelement3i_indexbuffer = NULL;
8300         rsurface.batchelement3i_bufferoffset = 0;
8301         rsurface.batchelement3s = NULL;
8302         rsurface.batchelement3s_indexbuffer = NULL;
8303         rsurface.batchelement3s_bufferoffset = 0;
8304         rsurface.passcolor4f = NULL;
8305         rsurface.passcolor4f_vertexbuffer = NULL;
8306         rsurface.passcolor4f_bufferoffset = 0;
8307
8308         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8309         {
8310                 if ((wantnormals || wanttangents) && !normal3f)
8311                 {
8312                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8313                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8314                 }
8315                 if (wanttangents && !svector3f)
8316                 {
8317                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8318                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8319                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8320                 }
8321         }
8322 }
8323
8324 float RSurf_FogPoint(const float *v)
8325 {
8326         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8327         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8328         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8329         float FogHeightFade = r_refdef.fogheightfade;
8330         float fogfrac;
8331         unsigned int fogmasktableindex;
8332         if (r_refdef.fogplaneviewabove)
8333                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8334         else
8335                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8336         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8337         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8338 }
8339
8340 float RSurf_FogVertex(const float *v)
8341 {
8342         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8343         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8344         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8345         float FogHeightFade = rsurface.fogheightfade;
8346         float fogfrac;
8347         unsigned int fogmasktableindex;
8348         if (r_refdef.fogplaneviewabove)
8349                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8350         else
8351                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8352         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8353         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8354 }
8355
8356 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8357 {
8358         int i;
8359         for (i = 0;i < numelements;i++)
8360                 outelement3i[i] = inelement3i[i] + adjust;
8361 }
8362
8363 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8364 extern cvar_t gl_vbo;
8365 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8366 {
8367         int deformindex;
8368         int firsttriangle;
8369         int numtriangles;
8370         int firstvertex;
8371         int endvertex;
8372         int numvertices;
8373         int surfacefirsttriangle;
8374         int surfacenumtriangles;
8375         int surfacefirstvertex;
8376         int surfaceendvertex;
8377         int surfacenumvertices;
8378         int batchnumvertices;
8379         int batchnumtriangles;
8380         int needsupdate;
8381         int i, j;
8382         qboolean gaps;
8383         qboolean dynamicvertex;
8384         float amplitude;
8385         float animpos;
8386         float scale;
8387         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8388         float waveparms[4];
8389         q3shaderinfo_deform_t *deform;
8390         const msurface_t *surface, *firstsurface;
8391         r_vertexmesh_t *vertexmesh;
8392         if (!texturenumsurfaces)
8393                 return;
8394         // find vertex range of this surface batch
8395         gaps = false;
8396         firstsurface = texturesurfacelist[0];
8397         firsttriangle = firstsurface->num_firsttriangle;
8398         batchnumvertices = 0;
8399         batchnumtriangles = 0;
8400         firstvertex = endvertex = firstsurface->num_firstvertex;
8401         for (i = 0;i < texturenumsurfaces;i++)
8402         {
8403                 surface = texturesurfacelist[i];
8404                 if (surface != firstsurface + i)
8405                         gaps = true;
8406                 surfacefirstvertex = surface->num_firstvertex;
8407                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8408                 surfacenumvertices = surface->num_vertices;
8409                 surfacenumtriangles = surface->num_triangles;
8410                 if (firstvertex > surfacefirstvertex)
8411                         firstvertex = surfacefirstvertex;
8412                 if (endvertex < surfaceendvertex)
8413                         endvertex = surfaceendvertex;
8414                 batchnumvertices += surfacenumvertices;
8415                 batchnumtriangles += surfacenumtriangles;
8416         }
8417
8418         // we now know the vertex range used, and if there are any gaps in it
8419         rsurface.batchfirstvertex = firstvertex;
8420         rsurface.batchnumvertices = endvertex - firstvertex;
8421         rsurface.batchfirsttriangle = firsttriangle;
8422         rsurface.batchnumtriangles = batchnumtriangles;
8423
8424         // this variable holds flags for which properties have been updated that
8425         // may require regenerating vertexmesh array...
8426         needsupdate = 0;
8427
8428         // check if any dynamic vertex processing must occur
8429         dynamicvertex = false;
8430
8431         // if there is a chance of animated vertex colors, it's a dynamic batch
8432         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8433         {
8434                 dynamicvertex = true;
8435                 batchneed |= BATCHNEED_NOGAPS;
8436                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8437         }
8438
8439         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8440         {
8441                 switch (deform->deform)
8442                 {
8443                 default:
8444                 case Q3DEFORM_PROJECTIONSHADOW:
8445                 case Q3DEFORM_TEXT0:
8446                 case Q3DEFORM_TEXT1:
8447                 case Q3DEFORM_TEXT2:
8448                 case Q3DEFORM_TEXT3:
8449                 case Q3DEFORM_TEXT4:
8450                 case Q3DEFORM_TEXT5:
8451                 case Q3DEFORM_TEXT6:
8452                 case Q3DEFORM_TEXT7:
8453                 case Q3DEFORM_NONE:
8454                         break;
8455                 case Q3DEFORM_AUTOSPRITE:
8456                         dynamicvertex = true;
8457                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8458                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8459                         break;
8460                 case Q3DEFORM_AUTOSPRITE2:
8461                         dynamicvertex = true;
8462                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8463                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8464                         break;
8465                 case Q3DEFORM_NORMAL:
8466                         dynamicvertex = true;
8467                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8468                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8469                         break;
8470                 case Q3DEFORM_WAVE:
8471                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8472                                 break; // if wavefunc is a nop, ignore this transform
8473                         dynamicvertex = true;
8474                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8475                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8476                         break;
8477                 case Q3DEFORM_BULGE:
8478                         dynamicvertex = true;
8479                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8480                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8481                         break;
8482                 case Q3DEFORM_MOVE:
8483                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8484                                 break; // if wavefunc is a nop, ignore this transform
8485                         dynamicvertex = true;
8486                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8487                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8488                         break;
8489                 }
8490         }
8491         switch(rsurface.texture->tcgen.tcgen)
8492         {
8493         default:
8494         case Q3TCGEN_TEXTURE:
8495                 break;
8496         case Q3TCGEN_LIGHTMAP:
8497                 dynamicvertex = true;
8498                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8499                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8500                 break;
8501         case Q3TCGEN_VECTOR:
8502                 dynamicvertex = true;
8503                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8504                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8505                 break;
8506         case Q3TCGEN_ENVIRONMENT:
8507                 dynamicvertex = true;
8508                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8509                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8510                 break;
8511         }
8512         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8513         {
8514                 dynamicvertex = true;
8515                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8516                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8517         }
8518
8519         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8520         {
8521                 dynamicvertex = true;
8522                 batchneed |= BATCHNEED_NOGAPS;
8523                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8524         }
8525
8526         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8527         {
8528                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8529                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8530                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8531                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8532                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8533                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8534                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8535         }
8536
8537         // when the model data has no vertex buffer (dynamic mesh), we need to
8538         // eliminate gaps
8539         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8540                 batchneed |= BATCHNEED_NOGAPS;
8541
8542         // if needsupdate, we have to do a dynamic vertex batch for sure
8543         if (needsupdate & batchneed)
8544                 dynamicvertex = true;
8545
8546         // see if we need to build vertexmesh from arrays
8547         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8548                 dynamicvertex = true;
8549
8550         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8551         // also some drivers strongly dislike firstvertex
8552         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8553                 dynamicvertex = true;
8554
8555         rsurface.batchvertex3f = rsurface.modelvertex3f;
8556         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8557         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8558         rsurface.batchsvector3f = rsurface.modelsvector3f;
8559         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8560         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8561         rsurface.batchtvector3f = rsurface.modeltvector3f;
8562         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8563         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8564         rsurface.batchnormal3f = rsurface.modelnormal3f;
8565         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8566         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8567         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8568         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8569         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8570         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8571         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8572         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8573         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8574         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8575         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8576         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8577         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8578         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8579         rsurface.batchelement3i = rsurface.modelelement3i;
8580         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8581         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8582         rsurface.batchelement3s = rsurface.modelelement3s;
8583         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8584         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8585
8586         // if any dynamic vertex processing has to occur in software, we copy the
8587         // entire surface list together before processing to rebase the vertices
8588         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8589         //
8590         // if any gaps exist and we do not have a static vertex buffer, we have to
8591         // copy the surface list together to avoid wasting upload bandwidth on the
8592         // vertices in the gaps.
8593         //
8594         // if gaps exist and we have a static vertex buffer, we still have to
8595         // combine the index buffer ranges into one dynamic index buffer.
8596         //
8597         // in all cases we end up with data that can be drawn in one call.
8598
8599         if (!dynamicvertex)
8600         {
8601                 // static vertex data, just set pointers...
8602                 rsurface.batchgeneratedvertex = false;
8603                 // if there are gaps, we want to build a combined index buffer,
8604                 // otherwise use the original static buffer with an appropriate offset
8605                 if (gaps)
8606                 {
8607                         // build a new triangle elements array for this batch
8608                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8609                         rsurface.batchfirsttriangle = 0;
8610                         numtriangles = 0;
8611                         for (i = 0;i < texturenumsurfaces;i++)
8612                         {
8613                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8614                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8615                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8616                                 numtriangles += surfacenumtriangles;
8617                         }
8618                         rsurface.batchelement3i_indexbuffer = NULL;
8619                         rsurface.batchelement3i_bufferoffset = 0;
8620                         rsurface.batchelement3s = NULL;
8621                         rsurface.batchelement3s_indexbuffer = NULL;
8622                         rsurface.batchelement3s_bufferoffset = 0;
8623                         if (endvertex <= 65536)
8624                         {
8625                                 // make a 16bit (unsigned short) index array if possible
8626                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8627                                 for (i = 0;i < numtriangles*3;i++)
8628                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8629                         }
8630                 }
8631                 return;
8632         }
8633
8634         // something needs software processing, do it for real...
8635         // we only directly handle separate array data in this case and then
8636         // generate interleaved data if needed...
8637         rsurface.batchgeneratedvertex = true;
8638
8639         // now copy the vertex data into a combined array and make an index array
8640         // (this is what Quake3 does all the time)
8641         //if (gaps || rsurface.batchfirstvertex)
8642         {
8643                 rsurface.batchvertex3fbuffer = NULL;
8644                 rsurface.batchvertexmesh = NULL;
8645                 rsurface.batchvertexmeshbuffer = NULL;
8646                 rsurface.batchvertex3f = NULL;
8647                 rsurface.batchvertex3f_vertexbuffer = NULL;
8648                 rsurface.batchvertex3f_bufferoffset = 0;
8649                 rsurface.batchsvector3f = NULL;
8650                 rsurface.batchsvector3f_vertexbuffer = NULL;
8651                 rsurface.batchsvector3f_bufferoffset = 0;
8652                 rsurface.batchtvector3f = NULL;
8653                 rsurface.batchtvector3f_vertexbuffer = NULL;
8654                 rsurface.batchtvector3f_bufferoffset = 0;
8655                 rsurface.batchnormal3f = NULL;
8656                 rsurface.batchnormal3f_vertexbuffer = NULL;
8657                 rsurface.batchnormal3f_bufferoffset = 0;
8658                 rsurface.batchlightmapcolor4f = NULL;
8659                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8660                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8661                 rsurface.batchtexcoordtexture2f = NULL;
8662                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8663                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8664                 rsurface.batchtexcoordlightmap2f = NULL;
8665                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8666                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8667                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8668                 rsurface.batchelement3i_indexbuffer = NULL;
8669                 rsurface.batchelement3i_bufferoffset = 0;
8670                 rsurface.batchelement3s = NULL;
8671                 rsurface.batchelement3s_indexbuffer = NULL;
8672                 rsurface.batchelement3s_bufferoffset = 0;
8673                 // we'll only be setting up certain arrays as needed
8674                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8675                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8676                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8677                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8678                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8679                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8680                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8681                 {
8682                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8683                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8684                 }
8685                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8686                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8687                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8688                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8689                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8690                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8691                 numvertices = 0;
8692                 numtriangles = 0;
8693                 for (i = 0;i < texturenumsurfaces;i++)
8694                 {
8695                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8696                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8697                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8698                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8699                         // copy only the data requested
8700                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8701                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8702                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8703                         {
8704                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8705                                 {
8706                                         if (rsurface.batchvertex3f)
8707                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8708                                         else
8709                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8710                                 }
8711                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8712                                 {
8713                                         if (rsurface.modelnormal3f)
8714                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8715                                         else
8716                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8717                                 }
8718                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8719                                 {
8720                                         if (rsurface.modelsvector3f)
8721                                         {
8722                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8723                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8724                                         }
8725                                         else
8726                                         {
8727                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8728                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8729                                         }
8730                                 }
8731                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8732                                 {
8733                                         if (rsurface.modellightmapcolor4f)
8734                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8735                                         else
8736                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8737                                 }
8738                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8739                                 {
8740                                         if (rsurface.modeltexcoordtexture2f)
8741                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8742                                         else
8743                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8744                                 }
8745                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8746                                 {
8747                                         if (rsurface.modeltexcoordlightmap2f)
8748                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8749                                         else
8750                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8751                                 }
8752                         }
8753                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8754                         numvertices += surfacenumvertices;
8755                         numtriangles += surfacenumtriangles;
8756                 }
8757
8758                 // generate a 16bit index array as well if possible
8759                 // (in general, dynamic batches fit)
8760                 if (numvertices <= 65536)
8761                 {
8762                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8763                         for (i = 0;i < numtriangles*3;i++)
8764                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8765                 }
8766
8767                 // since we've copied everything, the batch now starts at 0
8768                 rsurface.batchfirstvertex = 0;
8769                 rsurface.batchnumvertices = batchnumvertices;
8770                 rsurface.batchfirsttriangle = 0;
8771                 rsurface.batchnumtriangles = batchnumtriangles;
8772         }
8773
8774         // q1bsp surfaces rendered in vertex color mode have to have colors
8775         // calculated based on lightstyles
8776         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8777         {
8778                 // generate color arrays for the surfaces in this list
8779                 int c[4];
8780                 int scale;
8781                 int size3;
8782                 const int *offsets;
8783                 const unsigned char *lm;
8784                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8785                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8786                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8787                 numvertices = 0;
8788                 for (i = 0;i < texturenumsurfaces;i++)
8789                 {
8790                         surface = texturesurfacelist[i];
8791                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8792                         surfacenumvertices = surface->num_vertices;
8793                         if (surface->lightmapinfo->samples)
8794                         {
8795                                 for (j = 0;j < surfacenumvertices;j++)
8796                                 {
8797                                         lm = surface->lightmapinfo->samples + offsets[j];
8798                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8799                                         VectorScale(lm, scale, c);
8800                                         if (surface->lightmapinfo->styles[1] != 255)
8801                                         {
8802                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8803                                                 lm += size3;
8804                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8805                                                 VectorMA(c, scale, lm, c);
8806                                                 if (surface->lightmapinfo->styles[2] != 255)
8807                                                 {
8808                                                         lm += size3;
8809                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8810                                                         VectorMA(c, scale, lm, c);
8811                                                         if (surface->lightmapinfo->styles[3] != 255)
8812                                                         {
8813                                                                 lm += size3;
8814                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8815                                                                 VectorMA(c, scale, lm, c);
8816                                                         }
8817                                                 }
8818                                         }
8819                                         c[0] >>= 7;
8820                                         c[1] >>= 7;
8821                                         c[2] >>= 7;
8822                                         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);
8823                                         numvertices++;
8824                                 }
8825                         }
8826                         else
8827                         {
8828                                 for (j = 0;j < surfacenumvertices;j++)
8829                                 {
8830                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8831                                         numvertices++;
8832                                 }
8833                         }
8834                 }
8835         }
8836
8837         // if vertices are deformed (sprite flares and things in maps, possibly
8838         // water waves, bulges and other deformations), modify the copied vertices
8839         // in place
8840         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8841         {
8842                 switch (deform->deform)
8843                 {
8844                 default:
8845                 case Q3DEFORM_PROJECTIONSHADOW:
8846                 case Q3DEFORM_TEXT0:
8847                 case Q3DEFORM_TEXT1:
8848                 case Q3DEFORM_TEXT2:
8849                 case Q3DEFORM_TEXT3:
8850                 case Q3DEFORM_TEXT4:
8851                 case Q3DEFORM_TEXT5:
8852                 case Q3DEFORM_TEXT6:
8853                 case Q3DEFORM_TEXT7:
8854                 case Q3DEFORM_NONE:
8855                         break;
8856                 case Q3DEFORM_AUTOSPRITE:
8857                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8858                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8859                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8860                         VectorNormalize(newforward);
8861                         VectorNormalize(newright);
8862                         VectorNormalize(newup);
8863 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8864 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8865 //                      rsurface.batchvertex3f_bufferoffset = 0;
8866 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8867 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8868 //                      rsurface.batchsvector3f_bufferoffset = 0;
8869 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8870 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8871 //                      rsurface.batchtvector3f_bufferoffset = 0;
8872 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8873 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8874 //                      rsurface.batchnormal3f_bufferoffset = 0;
8875                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8876                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8877                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8878                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8879                                 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);
8880                         // a single autosprite surface can contain multiple sprites...
8881                         for (j = 0;j < batchnumvertices - 3;j += 4)
8882                         {
8883                                 VectorClear(center);
8884                                 for (i = 0;i < 4;i++)
8885                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8886                                 VectorScale(center, 0.25f, center);
8887                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8888                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8889                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8890                                 for (i = 0;i < 4;i++)
8891                                 {
8892                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8893                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8894                                 }
8895                         }
8896                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8897                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8898                         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);
8899                         break;
8900                 case Q3DEFORM_AUTOSPRITE2:
8901                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8902                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8903                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8904                         VectorNormalize(newforward);
8905                         VectorNormalize(newright);
8906                         VectorNormalize(newup);
8907 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8908 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8909 //                      rsurface.batchvertex3f_bufferoffset = 0;
8910                         {
8911                                 const float *v1, *v2;
8912                                 vec3_t start, end;
8913                                 float f, l;
8914                                 struct
8915                                 {
8916                                         float length2;
8917                                         const float *v1;
8918                                         const float *v2;
8919                                 }
8920                                 shortest[2];
8921                                 memset(shortest, 0, sizeof(shortest));
8922                                 // a single autosprite surface can contain multiple sprites...
8923                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8924                                 {
8925                                         VectorClear(center);
8926                                         for (i = 0;i < 4;i++)
8927                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8928                                         VectorScale(center, 0.25f, center);
8929                                         // find the two shortest edges, then use them to define the
8930                                         // axis vectors for rotating around the central axis
8931                                         for (i = 0;i < 6;i++)
8932                                         {
8933                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8934                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8935                                                 l = VectorDistance2(v1, v2);
8936                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8937                                                 if (v1[2] != v2[2])
8938                                                         l += (1.0f / 1024.0f);
8939                                                 if (shortest[0].length2 > l || i == 0)
8940                                                 {
8941                                                         shortest[1] = shortest[0];
8942                                                         shortest[0].length2 = l;
8943                                                         shortest[0].v1 = v1;
8944                                                         shortest[0].v2 = v2;
8945                                                 }
8946                                                 else if (shortest[1].length2 > l || i == 1)
8947                                                 {
8948                                                         shortest[1].length2 = l;
8949                                                         shortest[1].v1 = v1;
8950                                                         shortest[1].v2 = v2;
8951                                                 }
8952                                         }
8953                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8954                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8955                                         // this calculates the right vector from the shortest edge
8956                                         // and the up vector from the edge midpoints
8957                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8958                                         VectorNormalize(right);
8959                                         VectorSubtract(end, start, up);
8960                                         VectorNormalize(up);
8961                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8962                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8963                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8964                                         VectorNegate(forward, forward);
8965                                         VectorReflect(forward, 0, up, forward);
8966                                         VectorNormalize(forward);
8967                                         CrossProduct(up, forward, newright);
8968                                         VectorNormalize(newright);
8969                                         // rotate the quad around the up axis vector, this is made
8970                                         // especially easy by the fact we know the quad is flat,
8971                                         // so we only have to subtract the center position and
8972                                         // measure distance along the right vector, and then
8973                                         // multiply that by the newright vector and add back the
8974                                         // center position
8975                                         // we also need to subtract the old position to undo the
8976                                         // displacement from the center, which we do with a
8977                                         // DotProduct, the subtraction/addition of center is also
8978                                         // optimized into DotProducts here
8979                                         l = DotProduct(right, center);
8980                                         for (i = 0;i < 4;i++)
8981                                         {
8982                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8983                                                 f = DotProduct(right, v1) - l;
8984                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8985                                         }
8986                                 }
8987                         }
8988                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
8989                         {
8990 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8991 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
8992 //                              rsurface.batchnormal3f_bufferoffset = 0;
8993                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8994                         }
8995                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
8996                         {
8997 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8998 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
8999 //                              rsurface.batchsvector3f_bufferoffset = 0;
9000 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9001 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9002 //                              rsurface.batchtvector3f_bufferoffset = 0;
9003                                 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);
9004                         }
9005                         break;
9006                 case Q3DEFORM_NORMAL:
9007                         // deform the normals to make reflections wavey
9008                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9009                         rsurface.batchnormal3f_vertexbuffer = NULL;
9010                         rsurface.batchnormal3f_bufferoffset = 0;
9011                         for (j = 0;j < batchnumvertices;j++)
9012                         {
9013                                 float vertex[3];
9014                                 float *normal = rsurface.batchnormal3f + 3*j;
9015                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9016                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9017                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9018                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9019                                 VectorNormalize(normal);
9020                         }
9021                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9022                         {
9023 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9024 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9025 //                              rsurface.batchsvector3f_bufferoffset = 0;
9026 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9027 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9028 //                              rsurface.batchtvector3f_bufferoffset = 0;
9029                                 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);
9030                         }
9031                         break;
9032                 case Q3DEFORM_WAVE:
9033                         // deform vertex array to make wavey water and flags and such
9034                         waveparms[0] = deform->waveparms[0];
9035                         waveparms[1] = deform->waveparms[1];
9036                         waveparms[2] = deform->waveparms[2];
9037                         waveparms[3] = deform->waveparms[3];
9038                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9039                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9040                         // this is how a divisor of vertex influence on deformation
9041                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9042                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9043 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9044 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9045 //                      rsurface.batchvertex3f_bufferoffset = 0;
9046 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9047 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9048 //                      rsurface.batchnormal3f_bufferoffset = 0;
9049                         for (j = 0;j < batchnumvertices;j++)
9050                         {
9051                                 // if the wavefunc depends on time, evaluate it per-vertex
9052                                 if (waveparms[3])
9053                                 {
9054                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9055                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9056                                 }
9057                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9058                         }
9059                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9060                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9061                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9062                         {
9063 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9064 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9065 //                              rsurface.batchsvector3f_bufferoffset = 0;
9066 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9067 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9068 //                              rsurface.batchtvector3f_bufferoffset = 0;
9069                                 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);
9070                         }
9071                         break;
9072                 case Q3DEFORM_BULGE:
9073                         // deform vertex array to make the surface have moving bulges
9074 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9075 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9076 //                      rsurface.batchvertex3f_bufferoffset = 0;
9077 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9078 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9079 //                      rsurface.batchnormal3f_bufferoffset = 0;
9080                         for (j = 0;j < batchnumvertices;j++)
9081                         {
9082                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9083                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9084                         }
9085                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9086                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9087                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9088                         {
9089 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9090 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9091 //                              rsurface.batchsvector3f_bufferoffset = 0;
9092 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9093 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9094 //                              rsurface.batchtvector3f_bufferoffset = 0;
9095                                 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);
9096                         }
9097                         break;
9098                 case Q3DEFORM_MOVE:
9099                         // deform vertex array
9100                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9101                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9102                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9103                         VectorScale(deform->parms, scale, waveparms);
9104 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9105 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9106 //                      rsurface.batchvertex3f_bufferoffset = 0;
9107                         for (j = 0;j < batchnumvertices;j++)
9108                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9109                         break;
9110                 }
9111         }
9112
9113         // generate texcoords based on the chosen texcoord source
9114         switch(rsurface.texture->tcgen.tcgen)
9115         {
9116         default:
9117         case Q3TCGEN_TEXTURE:
9118                 break;
9119         case Q3TCGEN_LIGHTMAP:
9120 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9121 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9122 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9123                 if (rsurface.batchtexcoordlightmap2f)
9124                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9125                 break;
9126         case Q3TCGEN_VECTOR:
9127 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9128 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9129 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9130                 for (j = 0;j < batchnumvertices;j++)
9131                 {
9132                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9133                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9134                 }
9135                 break;
9136         case Q3TCGEN_ENVIRONMENT:
9137                 // make environment reflections using a spheremap
9138                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9139                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9140                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9141                 for (j = 0;j < batchnumvertices;j++)
9142                 {
9143                         // identical to Q3A's method, but executed in worldspace so
9144                         // carried models can be shiny too
9145
9146                         float viewer[3], d, reflected[3], worldreflected[3];
9147
9148                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9149                         // VectorNormalize(viewer);
9150
9151                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9152
9153                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9154                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9155                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9156                         // note: this is proportinal to viewer, so we can normalize later
9157
9158                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9159                         VectorNormalize(worldreflected);
9160
9161                         // note: this sphere map only uses world x and z!
9162                         // so positive and negative y will LOOK THE SAME.
9163                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9164                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9165                 }
9166                 break;
9167         }
9168         // the only tcmod that needs software vertex processing is turbulent, so
9169         // check for it here and apply the changes if needed
9170         // and we only support that as the first one
9171         // (handling a mixture of turbulent and other tcmods would be problematic
9172         //  without punting it entirely to a software path)
9173         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9174         {
9175                 amplitude = rsurface.texture->tcmods[0].parms[1];
9176                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9177 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9178 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9179 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9180                 for (j = 0;j < batchnumvertices;j++)
9181                 {
9182                         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);
9183                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9184                 }
9185         }
9186
9187         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9188         {
9189                 // convert the modified arrays to vertex structs
9190 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9191 //              rsurface.batchvertexmeshbuffer = NULL;
9192                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9193                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9194                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9195                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9196                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9197                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9198                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9199                 {
9200                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9201                         {
9202                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9203                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9204                         }
9205                 }
9206                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9207                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9208                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9209                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9210                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9211                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9212                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9213                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9214                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9215         }
9216 }
9217
9218 void RSurf_DrawBatch(void)
9219 {
9220         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9221         // through the pipeline, killing it earlier in the pipeline would have
9222         // per-surface overhead rather than per-batch overhead, so it's best to
9223         // reject it here, before it hits glDraw.
9224         if (rsurface.batchnumtriangles == 0)
9225                 return;
9226 #if 0
9227         // batch debugging code
9228         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9229         {
9230                 int i;
9231                 int j;
9232                 int c;
9233                 const int *e;
9234                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9235                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9236                 {
9237                         c = e[i];
9238                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9239                         {
9240                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9241                                 {
9242                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9243                                                 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);
9244                                         break;
9245                                 }
9246                         }
9247                 }
9248         }
9249 #endif
9250         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);
9251 }
9252
9253 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9254 {
9255         // pick the closest matching water plane
9256         int planeindex, vertexindex, bestplaneindex = -1;
9257         float d, bestd;
9258         vec3_t vert;
9259         const float *v;
9260         r_waterstate_waterplane_t *p;
9261         qboolean prepared = false;
9262         bestd = 0;
9263         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9264         {
9265                 if(p->camera_entity != rsurface.texture->camera_entity)
9266                         continue;
9267                 d = 0;
9268                 if(!prepared)
9269                 {
9270                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9271                         prepared = true;
9272                         if(rsurface.batchnumvertices == 0)
9273                                 break;
9274                 }
9275                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9276                 {
9277                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9278                         d += fabs(PlaneDiff(vert, &p->plane));
9279                 }
9280                 if (bestd > d || bestplaneindex < 0)
9281                 {
9282                         bestd = d;
9283                         bestplaneindex = planeindex;
9284                 }
9285         }
9286         return bestplaneindex;
9287         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9288         // this situation though, as it might be better to render single larger
9289         // batches with useless stuff (backface culled for example) than to
9290         // render multiple smaller batches
9291 }
9292
9293 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9294 {
9295         int i;
9296         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9297         rsurface.passcolor4f_vertexbuffer = 0;
9298         rsurface.passcolor4f_bufferoffset = 0;
9299         for (i = 0;i < rsurface.batchnumvertices;i++)
9300                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9301 }
9302
9303 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9304 {
9305         int i;
9306         float f;
9307         const float *v;
9308         const float *c;
9309         float *c2;
9310         if (rsurface.passcolor4f)
9311         {
9312                 // generate color arrays
9313                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9314                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9315                 rsurface.passcolor4f_vertexbuffer = 0;
9316                 rsurface.passcolor4f_bufferoffset = 0;
9317                 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)
9318                 {
9319                         f = RSurf_FogVertex(v);
9320                         c2[0] = c[0] * f;
9321                         c2[1] = c[1] * f;
9322                         c2[2] = c[2] * f;
9323                         c2[3] = c[3];
9324                 }
9325         }
9326         else
9327         {
9328                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9329                 rsurface.passcolor4f_vertexbuffer = 0;
9330                 rsurface.passcolor4f_bufferoffset = 0;
9331                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9332                 {
9333                         f = RSurf_FogVertex(v);
9334                         c2[0] = f;
9335                         c2[1] = f;
9336                         c2[2] = f;
9337                         c2[3] = 1;
9338                 }
9339         }
9340 }
9341
9342 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9343 {
9344         int i;
9345         float f;
9346         const float *v;
9347         const float *c;
9348         float *c2;
9349         if (!rsurface.passcolor4f)
9350                 return;
9351         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9352         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9353         rsurface.passcolor4f_vertexbuffer = 0;
9354         rsurface.passcolor4f_bufferoffset = 0;
9355         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)
9356         {
9357                 f = RSurf_FogVertex(v);
9358                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9359                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9360                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9361                 c2[3] = c[3];
9362         }
9363 }
9364
9365 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9366 {
9367         int i;
9368         const float *c;
9369         float *c2;
9370         if (!rsurface.passcolor4f)
9371                 return;
9372         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9373         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9374         rsurface.passcolor4f_vertexbuffer = 0;
9375         rsurface.passcolor4f_bufferoffset = 0;
9376         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9377         {
9378                 c2[0] = c[0] * r;
9379                 c2[1] = c[1] * g;
9380                 c2[2] = c[2] * b;
9381                 c2[3] = c[3] * a;
9382         }
9383 }
9384
9385 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9386 {
9387         int i;
9388         const float *c;
9389         float *c2;
9390         if (!rsurface.passcolor4f)
9391                 return;
9392         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9393         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9394         rsurface.passcolor4f_vertexbuffer = 0;
9395         rsurface.passcolor4f_bufferoffset = 0;
9396         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9397         {
9398                 c2[0] = c[0] + r_refdef.scene.ambient;
9399                 c2[1] = c[1] + r_refdef.scene.ambient;
9400                 c2[2] = c[2] + r_refdef.scene.ambient;
9401                 c2[3] = c[3];
9402         }
9403 }
9404
9405 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9406 {
9407         // TODO: optimize
9408         rsurface.passcolor4f = NULL;
9409         rsurface.passcolor4f_vertexbuffer = 0;
9410         rsurface.passcolor4f_bufferoffset = 0;
9411         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9412         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9413         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9414         GL_Color(r, g, b, a);
9415         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9416         RSurf_DrawBatch();
9417 }
9418
9419 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9420 {
9421         // TODO: optimize applyfog && applycolor case
9422         // just apply fog if necessary, and tint the fog color array if necessary
9423         rsurface.passcolor4f = NULL;
9424         rsurface.passcolor4f_vertexbuffer = 0;
9425         rsurface.passcolor4f_bufferoffset = 0;
9426         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9427         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9428         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9429         GL_Color(r, g, b, a);
9430         RSurf_DrawBatch();
9431 }
9432
9433 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9434 {
9435         // TODO: optimize
9436         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9437         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9438         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9439         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9440         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9441         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9442         GL_Color(r, g, b, a);
9443         RSurf_DrawBatch();
9444 }
9445
9446 static void RSurf_DrawBatch_GL11_ClampColor(void)
9447 {
9448         int i;
9449         const float *c1;
9450         float *c2;
9451         if (!rsurface.passcolor4f)
9452                 return;
9453         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9454         {
9455                 c2[0] = bound(0.0f, c1[0], 1.0f);
9456                 c2[1] = bound(0.0f, c1[1], 1.0f);
9457                 c2[2] = bound(0.0f, c1[2], 1.0f);
9458                 c2[3] = bound(0.0f, c1[3], 1.0f);
9459         }
9460 }
9461
9462 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9463 {
9464         int i;
9465         float f;
9466         const float *v;
9467         const float *n;
9468         float *c;
9469         //vec3_t eyedir;
9470
9471         // fake shading
9472         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9473         rsurface.passcolor4f_vertexbuffer = 0;
9474         rsurface.passcolor4f_bufferoffset = 0;
9475         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)
9476         {
9477                 f = -DotProduct(r_refdef.view.forward, n);
9478                 f = max(0, f);
9479                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9480                 f *= r_refdef.lightmapintensity;
9481                 Vector4Set(c, f, f, f, 1);
9482         }
9483 }
9484
9485 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9486 {
9487         RSurf_DrawBatch_GL11_ApplyFakeLight();
9488         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9489         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9490         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9491         GL_Color(r, g, b, a);
9492         RSurf_DrawBatch();
9493 }
9494
9495 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9496 {
9497         int i;
9498         float f;
9499         float alpha;
9500         const float *v;
9501         const float *n;
9502         float *c;
9503         vec3_t ambientcolor;
9504         vec3_t diffusecolor;
9505         vec3_t lightdir;
9506         // TODO: optimize
9507         // model lighting
9508         VectorCopy(rsurface.modellight_lightdir, lightdir);
9509         f = 0.5f * r_refdef.lightmapintensity;
9510         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9511         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9512         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9513         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9514         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9515         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9516         alpha = *a;
9517         if (VectorLength2(diffusecolor) > 0)
9518         {
9519                 // q3-style directional shading
9520                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9521                 rsurface.passcolor4f_vertexbuffer = 0;
9522                 rsurface.passcolor4f_bufferoffset = 0;
9523                 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)
9524                 {
9525                         if ((f = DotProduct(n, lightdir)) > 0)
9526                                 VectorMA(ambientcolor, f, diffusecolor, c);
9527                         else
9528                                 VectorCopy(ambientcolor, c);
9529                         c[3] = alpha;
9530                 }
9531                 *r = 1;
9532                 *g = 1;
9533                 *b = 1;
9534                 *a = 1;
9535                 *applycolor = false;
9536         }
9537         else
9538         {
9539                 *r = ambientcolor[0];
9540                 *g = ambientcolor[1];
9541                 *b = ambientcolor[2];
9542                 rsurface.passcolor4f = NULL;
9543                 rsurface.passcolor4f_vertexbuffer = 0;
9544                 rsurface.passcolor4f_bufferoffset = 0;
9545         }
9546 }
9547
9548 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9549 {
9550         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9551         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9552         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9553         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9554         GL_Color(r, g, b, a);
9555         RSurf_DrawBatch();
9556 }
9557
9558 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9559 {
9560         int i;
9561         float f;
9562         const float *v;
9563         float *c;
9564
9565         // fake shading
9566         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9567         rsurface.passcolor4f_vertexbuffer = 0;
9568         rsurface.passcolor4f_bufferoffset = 0;
9569
9570         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9571         {
9572                 f = 1 - RSurf_FogVertex(v);
9573                 c[0] = r;
9574                 c[1] = g;
9575                 c[2] = b;
9576                 c[3] = f * a;
9577         }
9578 }
9579
9580 void RSurf_SetupDepthAndCulling(void)
9581 {
9582         // submodels are biased to avoid z-fighting with world surfaces that they
9583         // may be exactly overlapping (avoids z-fighting artifacts on certain
9584         // doors and things in Quake maps)
9585         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9586         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9587         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9588         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9589 }
9590
9591 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9592 {
9593         // transparent sky would be ridiculous
9594         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9595                 return;
9596         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9597         skyrenderlater = true;
9598         RSurf_SetupDepthAndCulling();
9599         GL_DepthMask(true);
9600         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9601         // skymasking on them, and Quake3 never did sky masking (unlike
9602         // software Quake and software Quake2), so disable the sky masking
9603         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9604         // and skymasking also looks very bad when noclipping outside the
9605         // level, so don't use it then either.
9606         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9607         {
9608                 R_Mesh_ResetTextureState();
9609                 if (skyrendermasked)
9610                 {
9611                         R_SetupShader_DepthOrShadow(false);
9612                         // depth-only (masking)
9613                         GL_ColorMask(0,0,0,0);
9614                         // just to make sure that braindead drivers don't draw
9615                         // anything despite that colormask...
9616                         GL_BlendFunc(GL_ZERO, GL_ONE);
9617                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9618                         if (rsurface.batchvertex3fbuffer)
9619                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9620                         else
9621                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9622                 }
9623                 else
9624                 {
9625                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9626                         // fog sky
9627                         GL_BlendFunc(GL_ONE, GL_ZERO);
9628                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9629                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9630                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9631                 }
9632                 RSurf_DrawBatch();
9633                 if (skyrendermasked)
9634                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9635         }
9636         R_Mesh_ResetTextureState();
9637         GL_Color(1, 1, 1, 1);
9638 }
9639
9640 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9641 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9642 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9643 {
9644         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9645                 return;
9646         if (prepass)
9647         {
9648                 // render screenspace normalmap to texture
9649                 GL_DepthMask(true);
9650                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9651                 RSurf_DrawBatch();
9652         }
9653
9654         // bind lightmap texture
9655
9656         // water/refraction/reflection/camera surfaces have to be handled specially
9657         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9658         {
9659                 int start, end, startplaneindex;
9660                 for (start = 0;start < texturenumsurfaces;start = end)
9661                 {
9662                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9663                         if(startplaneindex < 0)
9664                         {
9665                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9666                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9667                                 end = start + 1;
9668                                 continue;
9669                         }
9670                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9671                                 ;
9672                         // now that we have a batch using the same planeindex, render it
9673                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9674                         {
9675                                 // render water or distortion background
9676                                 GL_DepthMask(true);
9677                                 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);
9678                                 RSurf_DrawBatch();
9679                                 // blend surface on top
9680                                 GL_DepthMask(false);
9681                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9682                                 RSurf_DrawBatch();
9683                         }
9684                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9685                         {
9686                                 // render surface with reflection texture as input
9687                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9688                                 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);
9689                                 RSurf_DrawBatch();
9690                         }
9691                 }
9692                 return;
9693         }
9694
9695         // render surface batch normally
9696         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9697         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);
9698         RSurf_DrawBatch();
9699 }
9700
9701 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9702 {
9703         // OpenGL 1.3 path - anything not completely ancient
9704         qboolean applycolor;
9705         qboolean applyfog;
9706         int layerindex;
9707         const texturelayer_t *layer;
9708         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);
9709         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9710
9711         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9712         {
9713                 vec4_t layercolor;
9714                 int layertexrgbscale;
9715                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9716                 {
9717                         if (layerindex == 0)
9718                                 GL_AlphaTest(true);
9719                         else
9720                         {
9721                                 GL_AlphaTest(false);
9722                                 GL_DepthFunc(GL_EQUAL);
9723                         }
9724                 }
9725                 GL_DepthMask(layer->depthmask && writedepth);
9726                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9727                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9728                 {
9729                         layertexrgbscale = 4;
9730                         VectorScale(layer->color, 0.25f, layercolor);
9731                 }
9732                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9733                 {
9734                         layertexrgbscale = 2;
9735                         VectorScale(layer->color, 0.5f, layercolor);
9736                 }
9737                 else
9738                 {
9739                         layertexrgbscale = 1;
9740                         VectorScale(layer->color, 1.0f, layercolor);
9741                 }
9742                 layercolor[3] = layer->color[3];
9743                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9744                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9745                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9746                 switch (layer->type)
9747                 {
9748                 case TEXTURELAYERTYPE_LITTEXTURE:
9749                         // single-pass lightmapped texture with 2x rgbscale
9750                         R_Mesh_TexBind(0, r_texture_white);
9751                         R_Mesh_TexMatrix(0, NULL);
9752                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9753                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9754                         R_Mesh_TexBind(1, layer->texture);
9755                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9756                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9757                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9758                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9759                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9760                         else if (FAKELIGHT_ENABLED)
9761                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9762                         else if (rsurface.uselightmaptexture)
9763                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9764                         else
9765                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9766                         break;
9767                 case TEXTURELAYERTYPE_TEXTURE:
9768                         // singletexture unlit texture with transparency support
9769                         R_Mesh_TexBind(0, layer->texture);
9770                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9771                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9772                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9773                         R_Mesh_TexBind(1, 0);
9774                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9775                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9776                         break;
9777                 case TEXTURELAYERTYPE_FOG:
9778                         // singletexture fogging
9779                         if (layer->texture)
9780                         {
9781                                 R_Mesh_TexBind(0, layer->texture);
9782                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9783                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9784                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9785                         }
9786                         else
9787                         {
9788                                 R_Mesh_TexBind(0, 0);
9789                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9790                         }
9791                         R_Mesh_TexBind(1, 0);
9792                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9793                         // generate a color array for the fog pass
9794                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9795                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9796                         RSurf_DrawBatch();
9797                         break;
9798                 default:
9799                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9800                 }
9801         }
9802         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9803         {
9804                 GL_DepthFunc(GL_LEQUAL);
9805                 GL_AlphaTest(false);
9806         }
9807 }
9808
9809 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9810 {
9811         // OpenGL 1.1 - crusty old voodoo path
9812         qboolean applyfog;
9813         int layerindex;
9814         const texturelayer_t *layer;
9815         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);
9816         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9817
9818         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9819         {
9820                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9821                 {
9822                         if (layerindex == 0)
9823                                 GL_AlphaTest(true);
9824                         else
9825                         {
9826                                 GL_AlphaTest(false);
9827                                 GL_DepthFunc(GL_EQUAL);
9828                         }
9829                 }
9830                 GL_DepthMask(layer->depthmask && writedepth);
9831                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9832                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9833                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9834                 switch (layer->type)
9835                 {
9836                 case TEXTURELAYERTYPE_LITTEXTURE:
9837                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9838                         {
9839                                 // two-pass lit texture with 2x rgbscale
9840                                 // first the lightmap pass
9841                                 R_Mesh_TexBind(0, r_texture_white);
9842                                 R_Mesh_TexMatrix(0, NULL);
9843                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9844                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9845                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9846                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9847                                 else if (FAKELIGHT_ENABLED)
9848                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9849                                 else if (rsurface.uselightmaptexture)
9850                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9851                                 else
9852                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9853                                 // then apply the texture to it
9854                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9855                                 R_Mesh_TexBind(0, layer->texture);
9856                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9857                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9858                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9859                                 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);
9860                         }
9861                         else
9862                         {
9863                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9864                                 R_Mesh_TexBind(0, layer->texture);
9865                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9866                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9867                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9868                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9869                                         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);
9870                                 else
9871                                         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);
9872                         }
9873                         break;
9874                 case TEXTURELAYERTYPE_TEXTURE:
9875                         // singletexture unlit texture with transparency support
9876                         R_Mesh_TexBind(0, layer->texture);
9877                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9878                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9879                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9880                         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);
9881                         break;
9882                 case TEXTURELAYERTYPE_FOG:
9883                         // singletexture fogging
9884                         if (layer->texture)
9885                         {
9886                                 R_Mesh_TexBind(0, layer->texture);
9887                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9888                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9889                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9890                         }
9891                         else
9892                         {
9893                                 R_Mesh_TexBind(0, 0);
9894                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9895                         }
9896                         // generate a color array for the fog pass
9897                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9898                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9899                         RSurf_DrawBatch();
9900                         break;
9901                 default:
9902                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9903                 }
9904         }
9905         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9906         {
9907                 GL_DepthFunc(GL_LEQUAL);
9908                 GL_AlphaTest(false);
9909         }
9910 }
9911
9912 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9913 {
9914         int vi;
9915         int j;
9916         r_vertexgeneric_t *batchvertex;
9917         float c[4];
9918
9919 //      R_Mesh_ResetTextureState();
9920         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9921
9922         if(rsurface.texture && rsurface.texture->currentskinframe)
9923         {
9924                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9925                 c[3] *= rsurface.texture->currentalpha;
9926         }
9927         else
9928         {
9929                 c[0] = 1;
9930                 c[1] = 0;
9931                 c[2] = 1;
9932                 c[3] = 1;
9933         }
9934
9935         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9936         {
9937                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9938                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9939                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9940         }
9941
9942         // brighten it up (as texture value 127 means "unlit")
9943         c[0] *= 2 * r_refdef.view.colorscale;
9944         c[1] *= 2 * r_refdef.view.colorscale;
9945         c[2] *= 2 * r_refdef.view.colorscale;
9946
9947         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9948                 c[3] *= r_wateralpha.value;
9949
9950         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9951         {
9952                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9953                 GL_DepthMask(false);
9954         }
9955         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9956         {
9957                 GL_BlendFunc(GL_ONE, GL_ONE);
9958                 GL_DepthMask(false);
9959         }
9960         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9961         {
9962                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9963                 GL_DepthMask(false);
9964         }
9965         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9966         {
9967                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9968                 GL_DepthMask(false);
9969         }
9970         else
9971         {
9972                 GL_BlendFunc(GL_ONE, GL_ZERO);
9973                 GL_DepthMask(writedepth);
9974         }
9975
9976         if (r_showsurfaces.integer == 3)
9977         {
9978                 rsurface.passcolor4f = NULL;
9979
9980                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9981                 {
9982                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9983
9984                         rsurface.passcolor4f = NULL;
9985                         rsurface.passcolor4f_vertexbuffer = 0;
9986                         rsurface.passcolor4f_bufferoffset = 0;
9987                 }
9988                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9989                 {
9990                         qboolean applycolor = true;
9991                         float one = 1.0;
9992
9993                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9994
9995                         r_refdef.lightmapintensity = 1;
9996                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
9997                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
9998                 }
9999                 else if (FAKELIGHT_ENABLED)
10000                 {
10001                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10002
10003                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10004                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10005                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10006                 }
10007                 else
10008                 {
10009                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10010
10011                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10012                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10013                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10014                 }
10015
10016                 if(!rsurface.passcolor4f)
10017                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10018
10019                 RSurf_DrawBatch_GL11_ApplyAmbient();
10020                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10021                 if(r_refdef.fogenabled)
10022                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10023                 RSurf_DrawBatch_GL11_ClampColor();
10024
10025                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10026                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10027                 RSurf_DrawBatch();
10028         }
10029         else if (!r_refdef.view.showdebug)
10030         {
10031                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10032                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10033                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10034                 {
10035                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10036                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10037                 }
10038                 R_Mesh_PrepareVertices_Generic_Unlock();
10039                 RSurf_DrawBatch();
10040         }
10041         else if (r_showsurfaces.integer == 4)
10042         {
10043                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10044                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10045                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10046                 {
10047                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10048                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10049                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10050                 }
10051                 R_Mesh_PrepareVertices_Generic_Unlock();
10052                 RSurf_DrawBatch();
10053         }
10054         else if (r_showsurfaces.integer == 2)
10055         {
10056                 const int *e;
10057                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10058                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10059                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10060                 {
10061                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10062                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10063                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10064                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10065                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10066                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10067                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10068                 }
10069                 R_Mesh_PrepareVertices_Generic_Unlock();
10070                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10071         }
10072         else
10073         {
10074                 int texturesurfaceindex;
10075                 int k;
10076                 const msurface_t *surface;
10077                 float surfacecolor4f[4];
10078                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10079                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10080                 vi = 0;
10081                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10082                 {
10083                         surface = texturesurfacelist[texturesurfaceindex];
10084                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10085                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10086                         for (j = 0;j < surface->num_vertices;j++)
10087                         {
10088                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10089                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10090                                 vi++;
10091                         }
10092                 }
10093                 R_Mesh_PrepareVertices_Generic_Unlock();
10094                 RSurf_DrawBatch();
10095         }
10096 }
10097
10098 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10099 {
10100         CHECKGLERROR
10101         RSurf_SetupDepthAndCulling();
10102         if (r_showsurfaces.integer)
10103         {
10104                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10105                 return;
10106         }
10107         switch (vid.renderpath)
10108         {
10109         case RENDERPATH_GL20:
10110         case RENDERPATH_D3D9:
10111         case RENDERPATH_D3D10:
10112         case RENDERPATH_D3D11:
10113         case RENDERPATH_SOFT:
10114         case RENDERPATH_GLES2:
10115                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10116                 break;
10117         case RENDERPATH_GL13:
10118         case RENDERPATH_GLES1:
10119                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10120                 break;
10121         case RENDERPATH_GL11:
10122                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10123                 break;
10124         }
10125         CHECKGLERROR
10126 }
10127
10128 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10129 {
10130         CHECKGLERROR
10131         RSurf_SetupDepthAndCulling();
10132         if (r_showsurfaces.integer)
10133         {
10134                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10135                 return;
10136         }
10137         switch (vid.renderpath)
10138         {
10139         case RENDERPATH_GL20:
10140         case RENDERPATH_D3D9:
10141         case RENDERPATH_D3D10:
10142         case RENDERPATH_D3D11:
10143         case RENDERPATH_SOFT:
10144         case RENDERPATH_GLES2:
10145                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10146                 break;
10147         case RENDERPATH_GL13:
10148         case RENDERPATH_GLES1:
10149                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10150                 break;
10151         case RENDERPATH_GL11:
10152                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10153                 break;
10154         }
10155         CHECKGLERROR
10156 }
10157
10158 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10159 {
10160         int i, j;
10161         int texturenumsurfaces, endsurface;
10162         texture_t *texture;
10163         const msurface_t *surface;
10164         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10165
10166         // if the model is static it doesn't matter what value we give for
10167         // wantnormals and wanttangents, so this logic uses only rules applicable
10168         // to a model, knowing that they are meaningless otherwise
10169         if (ent == r_refdef.scene.worldentity)
10170                 RSurf_ActiveWorldEntity();
10171         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10172                 RSurf_ActiveModelEntity(ent, false, false, false);
10173         else
10174         {
10175                 switch (vid.renderpath)
10176                 {
10177                 case RENDERPATH_GL20:
10178                 case RENDERPATH_D3D9:
10179                 case RENDERPATH_D3D10:
10180                 case RENDERPATH_D3D11:
10181                 case RENDERPATH_SOFT:
10182                 case RENDERPATH_GLES2:
10183                         RSurf_ActiveModelEntity(ent, true, true, false);
10184                         break;
10185                 case RENDERPATH_GL11:
10186                 case RENDERPATH_GL13:
10187                 case RENDERPATH_GLES1:
10188                         RSurf_ActiveModelEntity(ent, true, false, false);
10189                         break;
10190                 }
10191         }
10192
10193         if (r_transparentdepthmasking.integer)
10194         {
10195                 qboolean setup = false;
10196                 for (i = 0;i < numsurfaces;i = j)
10197                 {
10198                         j = i + 1;
10199                         surface = rsurface.modelsurfaces + surfacelist[i];
10200                         texture = surface->texture;
10201                         rsurface.texture = R_GetCurrentTexture(texture);
10202                         rsurface.lightmaptexture = NULL;
10203                         rsurface.deluxemaptexture = NULL;
10204                         rsurface.uselightmaptexture = false;
10205                         // scan ahead until we find a different texture
10206                         endsurface = min(i + 1024, numsurfaces);
10207                         texturenumsurfaces = 0;
10208                         texturesurfacelist[texturenumsurfaces++] = surface;
10209                         for (;j < endsurface;j++)
10210                         {
10211                                 surface = rsurface.modelsurfaces + surfacelist[j];
10212                                 if (texture != surface->texture)
10213                                         break;
10214                                 texturesurfacelist[texturenumsurfaces++] = surface;
10215                         }
10216                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10217                                 continue;
10218                         // render the range of surfaces as depth
10219                         if (!setup)
10220                         {
10221                                 setup = true;
10222                                 GL_ColorMask(0,0,0,0);
10223                                 GL_Color(1,1,1,1);
10224                                 GL_DepthTest(true);
10225                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10226                                 GL_DepthMask(true);
10227 //                              R_Mesh_ResetTextureState();
10228                                 R_SetupShader_DepthOrShadow(false);
10229                         }
10230                         RSurf_SetupDepthAndCulling();
10231                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10232                         if (rsurface.batchvertex3fbuffer)
10233                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10234                         else
10235                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10236                         RSurf_DrawBatch();
10237                 }
10238                 if (setup)
10239                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10240         }
10241
10242         for (i = 0;i < numsurfaces;i = j)
10243         {
10244                 j = i + 1;
10245                 surface = rsurface.modelsurfaces + surfacelist[i];
10246                 texture = surface->texture;
10247                 rsurface.texture = R_GetCurrentTexture(texture);
10248                 // scan ahead until we find a different texture
10249                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10250                 texturenumsurfaces = 0;
10251                 texturesurfacelist[texturenumsurfaces++] = surface;
10252                 if(FAKELIGHT_ENABLED)
10253                 {
10254                         rsurface.lightmaptexture = NULL;
10255                         rsurface.deluxemaptexture = NULL;
10256                         rsurface.uselightmaptexture = false;
10257                         for (;j < endsurface;j++)
10258                         {
10259                                 surface = rsurface.modelsurfaces + surfacelist[j];
10260                                 if (texture != surface->texture)
10261                                         break;
10262                                 texturesurfacelist[texturenumsurfaces++] = surface;
10263                         }
10264                 }
10265                 else
10266                 {
10267                         rsurface.lightmaptexture = surface->lightmaptexture;
10268                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10269                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10270                         for (;j < endsurface;j++)
10271                         {
10272                                 surface = rsurface.modelsurfaces + surfacelist[j];
10273                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10274                                         break;
10275                                 texturesurfacelist[texturenumsurfaces++] = surface;
10276                         }
10277                 }
10278                 // render the range of surfaces
10279                 if (ent == r_refdef.scene.worldentity)
10280                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10281                 else
10282                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10283         }
10284         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10285 }
10286
10287 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10288 {
10289         // transparent surfaces get pushed off into the transparent queue
10290         int surfacelistindex;
10291         const msurface_t *surface;
10292         vec3_t tempcenter, center;
10293         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10294         {
10295                 surface = texturesurfacelist[surfacelistindex];
10296                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10297                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10298                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10299                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10300                 if (queueentity->transparent_offset) // transparent offset
10301                 {
10302                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10303                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10304                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10305                 }
10306                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10307         }
10308 }
10309
10310 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10311 {
10312         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10313                 return;
10314         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10315                 return;
10316         RSurf_SetupDepthAndCulling();
10317         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10318         if (rsurface.batchvertex3fbuffer)
10319                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10320         else
10321                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10322         RSurf_DrawBatch();
10323 }
10324
10325 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10326 {
10327         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10328         CHECKGLERROR
10329         if (depthonly)
10330                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10331         else if (prepass)
10332         {
10333                 if (!rsurface.texture->currentnumlayers)
10334                         return;
10335                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10336                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10337                 else
10338                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10339         }
10340         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10341                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10342         else if (!rsurface.texture->currentnumlayers)
10343                 return;
10344         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10345         {
10346                 // in the deferred case, transparent surfaces were queued during prepass
10347                 if (!r_shadow_usingdeferredprepass)
10348                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10349         }
10350         else
10351         {
10352                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10353                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10354         }
10355         CHECKGLERROR
10356 }
10357
10358 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10359 {
10360         int i, j;
10361         texture_t *texture;
10362         R_FrameData_SetMark();
10363         // break the surface list down into batches by texture and use of lightmapping
10364         for (i = 0;i < numsurfaces;i = j)
10365         {
10366                 j = i + 1;
10367                 // texture is the base texture pointer, rsurface.texture is the
10368                 // current frame/skin the texture is directing us to use (for example
10369                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10370                 // use skin 1 instead)
10371                 texture = surfacelist[i]->texture;
10372                 rsurface.texture = R_GetCurrentTexture(texture);
10373                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10374                 {
10375                         // if this texture is not the kind we want, skip ahead to the next one
10376                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10377                                 ;
10378                         continue;
10379                 }
10380                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10381                 {
10382                         rsurface.lightmaptexture = NULL;
10383                         rsurface.deluxemaptexture = NULL;
10384                         rsurface.uselightmaptexture = false;
10385                         // simply scan ahead until we find a different texture or lightmap state
10386                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10387                                 ;
10388                 }
10389                 else
10390                 {
10391                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10392                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10393                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10394                         // simply scan ahead until we find a different texture or lightmap state
10395                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10396                                 ;
10397                 }
10398                 // render the range of surfaces
10399                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10400         }
10401         R_FrameData_ReturnToMark();
10402 }
10403
10404 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10405 {
10406         CHECKGLERROR
10407         if (depthonly)
10408                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10409         else if (prepass)
10410         {
10411                 if (!rsurface.texture->currentnumlayers)
10412                         return;
10413                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10414                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10415                 else
10416                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10417         }
10418         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10419                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10420         else if (!rsurface.texture->currentnumlayers)
10421                 return;
10422         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10423         {
10424                 // in the deferred case, transparent surfaces were queued during prepass
10425                 if (!r_shadow_usingdeferredprepass)
10426                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10427         }
10428         else
10429         {
10430                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10431                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10432         }
10433         CHECKGLERROR
10434 }
10435
10436 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10437 {
10438         int i, j;
10439         texture_t *texture;
10440         R_FrameData_SetMark();
10441         // break the surface list down into batches by texture and use of lightmapping
10442         for (i = 0;i < numsurfaces;i = j)
10443         {
10444                 j = i + 1;
10445                 // texture is the base texture pointer, rsurface.texture is the
10446                 // current frame/skin the texture is directing us to use (for example
10447                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10448                 // use skin 1 instead)
10449                 texture = surfacelist[i]->texture;
10450                 rsurface.texture = R_GetCurrentTexture(texture);
10451                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10452                 {
10453                         // if this texture is not the kind we want, skip ahead to the next one
10454                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10455                                 ;
10456                         continue;
10457                 }
10458                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10459                 {
10460                         rsurface.lightmaptexture = NULL;
10461                         rsurface.deluxemaptexture = NULL;
10462                         rsurface.uselightmaptexture = false;
10463                         // simply scan ahead until we find a different texture or lightmap state
10464                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10465                                 ;
10466                 }
10467                 else
10468                 {
10469                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10470                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10471                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10472                         // simply scan ahead until we find a different texture or lightmap state
10473                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10474                                 ;
10475                 }
10476                 // render the range of surfaces
10477                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10478         }
10479         R_FrameData_ReturnToMark();
10480 }
10481
10482 float locboxvertex3f[6*4*3] =
10483 {
10484         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10485         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10486         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10487         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10488         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10489         1,0,0, 0,0,0, 0,1,0, 1,1,0
10490 };
10491
10492 unsigned short locboxelements[6*2*3] =
10493 {
10494          0, 1, 2, 0, 2, 3,
10495          4, 5, 6, 4, 6, 7,
10496          8, 9,10, 8,10,11,
10497         12,13,14, 12,14,15,
10498         16,17,18, 16,18,19,
10499         20,21,22, 20,22,23
10500 };
10501
10502 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10503 {
10504         int i, j;
10505         cl_locnode_t *loc = (cl_locnode_t *)ent;
10506         vec3_t mins, size;
10507         float vertex3f[6*4*3];
10508         CHECKGLERROR
10509         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10510         GL_DepthMask(false);
10511         GL_DepthRange(0, 1);
10512         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10513         GL_DepthTest(true);
10514         GL_CullFace(GL_NONE);
10515         R_EntityMatrix(&identitymatrix);
10516
10517 //      R_Mesh_ResetTextureState();
10518
10519         i = surfacelist[0];
10520         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10521                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10522                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10523                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10524
10525         if (VectorCompare(loc->mins, loc->maxs))
10526         {
10527                 VectorSet(size, 2, 2, 2);
10528                 VectorMA(loc->mins, -0.5f, size, mins);
10529         }
10530         else
10531         {
10532                 VectorCopy(loc->mins, mins);
10533                 VectorSubtract(loc->maxs, loc->mins, size);
10534         }
10535
10536         for (i = 0;i < 6*4*3;)
10537                 for (j = 0;j < 3;j++, i++)
10538                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10539
10540         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10541         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10542         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10543 }
10544
10545 void R_DrawLocs(void)
10546 {
10547         int index;
10548         cl_locnode_t *loc, *nearestloc;
10549         vec3_t center;
10550         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10551         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10552         {
10553                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10554                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10555         }
10556 }
10557
10558 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10559 {
10560         if (decalsystem->decals)
10561                 Mem_Free(decalsystem->decals);
10562         memset(decalsystem, 0, sizeof(*decalsystem));
10563 }
10564
10565 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)
10566 {
10567         tridecal_t *decal;
10568         tridecal_t *decals;
10569         int i;
10570
10571         // expand or initialize the system
10572         if (decalsystem->maxdecals <= decalsystem->numdecals)
10573         {
10574                 decalsystem_t old = *decalsystem;
10575                 qboolean useshortelements;
10576                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10577                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10578                 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)));
10579                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10580                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10581                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10582                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10583                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10584                 if (decalsystem->numdecals)
10585                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10586                 if (old.decals)
10587                         Mem_Free(old.decals);
10588                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10589                         decalsystem->element3i[i] = i;
10590                 if (useshortelements)
10591                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10592                                 decalsystem->element3s[i] = i;
10593         }
10594
10595         // grab a decal and search for another free slot for the next one
10596         decals = decalsystem->decals;
10597         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10598         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10599                 ;
10600         decalsystem->freedecal = i;
10601         if (decalsystem->numdecals <= i)
10602                 decalsystem->numdecals = i + 1;
10603
10604         // initialize the decal
10605         decal->lived = 0;
10606         decal->triangleindex = triangleindex;
10607         decal->surfaceindex = surfaceindex;
10608         decal->decalsequence = decalsequence;
10609         decal->color4f[0][0] = c0[0];
10610         decal->color4f[0][1] = c0[1];
10611         decal->color4f[0][2] = c0[2];
10612         decal->color4f[0][3] = 1;
10613         decal->color4f[1][0] = c1[0];
10614         decal->color4f[1][1] = c1[1];
10615         decal->color4f[1][2] = c1[2];
10616         decal->color4f[1][3] = 1;
10617         decal->color4f[2][0] = c2[0];
10618         decal->color4f[2][1] = c2[1];
10619         decal->color4f[2][2] = c2[2];
10620         decal->color4f[2][3] = 1;
10621         decal->vertex3f[0][0] = v0[0];
10622         decal->vertex3f[0][1] = v0[1];
10623         decal->vertex3f[0][2] = v0[2];
10624         decal->vertex3f[1][0] = v1[0];
10625         decal->vertex3f[1][1] = v1[1];
10626         decal->vertex3f[1][2] = v1[2];
10627         decal->vertex3f[2][0] = v2[0];
10628         decal->vertex3f[2][1] = v2[1];
10629         decal->vertex3f[2][2] = v2[2];
10630         decal->texcoord2f[0][0] = t0[0];
10631         decal->texcoord2f[0][1] = t0[1];
10632         decal->texcoord2f[1][0] = t1[0];
10633         decal->texcoord2f[1][1] = t1[1];
10634         decal->texcoord2f[2][0] = t2[0];
10635         decal->texcoord2f[2][1] = t2[1];
10636         TriangleNormal(v0, v1, v2, decal->plane);
10637         VectorNormalize(decal->plane);
10638         decal->plane[3] = DotProduct(v0, decal->plane);
10639 }
10640
10641 extern cvar_t cl_decals_bias;
10642 extern cvar_t cl_decals_models;
10643 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10644 // baseparms, parms, temps
10645 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)
10646 {
10647         int cornerindex;
10648         int index;
10649         float v[9][3];
10650         const float *vertex3f;
10651         const float *normal3f;
10652         int numpoints;
10653         float points[2][9][3];
10654         float temp[3];
10655         float tc[9][2];
10656         float f;
10657         float c[9][4];
10658         const int *e;
10659
10660         e = rsurface.modelelement3i + 3*triangleindex;
10661
10662         vertex3f = rsurface.modelvertex3f;
10663         normal3f = rsurface.modelnormal3f;
10664
10665         if (normal3f)
10666         {
10667                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10668                 {
10669                         index = 3*e[cornerindex];
10670                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10671                 }
10672         }
10673         else
10674         {
10675                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10676                 {
10677                         index = 3*e[cornerindex];
10678                         VectorCopy(vertex3f + index, v[cornerindex]);
10679                 }
10680         }
10681
10682         // cull backfaces
10683         //TriangleNormal(v[0], v[1], v[2], normal);
10684         //if (DotProduct(normal, localnormal) < 0.0f)
10685         //      continue;
10686         // clip by each of the box planes formed from the projection matrix
10687         // if anything survives, we emit the decal
10688         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]);
10689         if (numpoints < 3)
10690                 return;
10691         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]);
10692         if (numpoints < 3)
10693                 return;
10694         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]);
10695         if (numpoints < 3)
10696                 return;
10697         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]);
10698         if (numpoints < 3)
10699                 return;
10700         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]);
10701         if (numpoints < 3)
10702                 return;
10703         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]);
10704         if (numpoints < 3)
10705                 return;
10706         // some part of the triangle survived, so we have to accept it...
10707         if (dynamic)
10708         {
10709                 // dynamic always uses the original triangle
10710                 numpoints = 3;
10711                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10712                 {
10713                         index = 3*e[cornerindex];
10714                         VectorCopy(vertex3f + index, v[cornerindex]);
10715                 }
10716         }
10717         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10718         {
10719                 // convert vertex positions to texcoords
10720                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10721                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10722                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10723                 // calculate distance fade from the projection origin
10724                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10725                 f = bound(0.0f, f, 1.0f);
10726                 c[cornerindex][0] = r * f;
10727                 c[cornerindex][1] = g * f;
10728                 c[cornerindex][2] = b * f;
10729                 c[cornerindex][3] = 1.0f;
10730                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10731         }
10732         if (dynamic)
10733                 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);
10734         else
10735                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10736                         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);
10737 }
10738 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)
10739 {
10740         matrix4x4_t projection;
10741         decalsystem_t *decalsystem;
10742         qboolean dynamic;
10743         dp_model_t *model;
10744         const msurface_t *surface;
10745         const msurface_t *surfaces;
10746         const int *surfacelist;
10747         const texture_t *texture;
10748         int numtriangles;
10749         int numsurfacelist;
10750         int surfacelistindex;
10751         int surfaceindex;
10752         int triangleindex;
10753         float localorigin[3];
10754         float localnormal[3];
10755         float localmins[3];
10756         float localmaxs[3];
10757         float localsize;
10758         //float normal[3];
10759         float planes[6][4];
10760         float angles[3];
10761         bih_t *bih;
10762         int bih_triangles_count;
10763         int bih_triangles[256];
10764         int bih_surfaces[256];
10765
10766         decalsystem = &ent->decalsystem;
10767         model = ent->model;
10768         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10769         {
10770                 R_DecalSystem_Reset(&ent->decalsystem);
10771                 return;
10772         }
10773
10774         if (!model->brush.data_leafs && !cl_decals_models.integer)
10775         {
10776                 if (decalsystem->model)
10777                         R_DecalSystem_Reset(decalsystem);
10778                 return;
10779         }
10780
10781         if (decalsystem->model != model)
10782                 R_DecalSystem_Reset(decalsystem);
10783         decalsystem->model = model;
10784
10785         RSurf_ActiveModelEntity(ent, true, false, false);
10786
10787         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10788         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10789         VectorNormalize(localnormal);
10790         localsize = worldsize*rsurface.inversematrixscale;
10791         localmins[0] = localorigin[0] - localsize;
10792         localmins[1] = localorigin[1] - localsize;
10793         localmins[2] = localorigin[2] - localsize;
10794         localmaxs[0] = localorigin[0] + localsize;
10795         localmaxs[1] = localorigin[1] + localsize;
10796         localmaxs[2] = localorigin[2] + localsize;
10797
10798         //VectorCopy(localnormal, planes[4]);
10799         //VectorVectors(planes[4], planes[2], planes[0]);
10800         AnglesFromVectors(angles, localnormal, NULL, false);
10801         AngleVectors(angles, planes[0], planes[2], planes[4]);
10802         VectorNegate(planes[0], planes[1]);
10803         VectorNegate(planes[2], planes[3]);
10804         VectorNegate(planes[4], planes[5]);
10805         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10806         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10807         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10808         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10809         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10810         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10811
10812 #if 1
10813 // works
10814 {
10815         matrix4x4_t forwardprojection;
10816         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10817         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10818 }
10819 #else
10820 // broken
10821 {
10822         float projectionvector[4][3];
10823         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10824         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10825         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10826         projectionvector[0][0] = planes[0][0] * ilocalsize;
10827         projectionvector[0][1] = planes[1][0] * ilocalsize;
10828         projectionvector[0][2] = planes[2][0] * ilocalsize;
10829         projectionvector[1][0] = planes[0][1] * ilocalsize;
10830         projectionvector[1][1] = planes[1][1] * ilocalsize;
10831         projectionvector[1][2] = planes[2][1] * ilocalsize;
10832         projectionvector[2][0] = planes[0][2] * ilocalsize;
10833         projectionvector[2][1] = planes[1][2] * ilocalsize;
10834         projectionvector[2][2] = planes[2][2] * ilocalsize;
10835         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10836         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10837         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10838         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10839 }
10840 #endif
10841
10842         dynamic = model->surfmesh.isanimated;
10843         numsurfacelist = model->nummodelsurfaces;
10844         surfacelist = model->sortedmodelsurfaces;
10845         surfaces = model->data_surfaces;
10846
10847         bih = NULL;
10848         bih_triangles_count = -1;
10849         if(!dynamic)
10850         {
10851                 if(model->render_bih.numleafs)
10852                         bih = &model->render_bih;
10853                 else if(model->collision_bih.numleafs)
10854                         bih = &model->collision_bih;
10855         }
10856         if(bih)
10857                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10858         if(bih_triangles_count == 0)
10859                 return;
10860         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10861                 return;
10862         if(bih_triangles_count > 0)
10863         {
10864                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10865                 {
10866                         surfaceindex = bih_surfaces[triangleindex];
10867                         surface = surfaces + surfaceindex;
10868                         texture = surface->texture;
10869                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10870                                 continue;
10871                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10872                                 continue;
10873                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10874                 }
10875         }
10876         else
10877         {
10878                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10879                 {
10880                         surfaceindex = surfacelist[surfacelistindex];
10881                         surface = surfaces + surfaceindex;
10882                         // check cull box first because it rejects more than any other check
10883                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10884                                 continue;
10885                         // skip transparent surfaces
10886                         texture = surface->texture;
10887                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10888                                 continue;
10889                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10890                                 continue;
10891                         numtriangles = surface->num_triangles;
10892                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10893                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10894                 }
10895         }
10896 }
10897
10898 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10899 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)
10900 {
10901         int renderentityindex;
10902         float worldmins[3];
10903         float worldmaxs[3];
10904         entity_render_t *ent;
10905
10906         if (!cl_decals_newsystem.integer)
10907                 return;
10908
10909         worldmins[0] = worldorigin[0] - worldsize;
10910         worldmins[1] = worldorigin[1] - worldsize;
10911         worldmins[2] = worldorigin[2] - worldsize;
10912         worldmaxs[0] = worldorigin[0] + worldsize;
10913         worldmaxs[1] = worldorigin[1] + worldsize;
10914         worldmaxs[2] = worldorigin[2] + worldsize;
10915
10916         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10917
10918         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10919         {
10920                 ent = r_refdef.scene.entities[renderentityindex];
10921                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10922                         continue;
10923
10924                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10925         }
10926 }
10927
10928 typedef struct r_decalsystem_splatqueue_s
10929 {
10930         vec3_t worldorigin;
10931         vec3_t worldnormal;
10932         float color[4];
10933         float tcrange[4];
10934         float worldsize;
10935         int decalsequence;
10936 }
10937 r_decalsystem_splatqueue_t;
10938
10939 int r_decalsystem_numqueued = 0;
10940 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10941
10942 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)
10943 {
10944         r_decalsystem_splatqueue_t *queue;
10945
10946         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10947                 return;
10948
10949         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10950         VectorCopy(worldorigin, queue->worldorigin);
10951         VectorCopy(worldnormal, queue->worldnormal);
10952         Vector4Set(queue->color, r, g, b, a);
10953         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10954         queue->worldsize = worldsize;
10955         queue->decalsequence = cl.decalsequence++;
10956 }
10957
10958 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10959 {
10960         int i;
10961         r_decalsystem_splatqueue_t *queue;
10962
10963         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10964                 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);
10965         r_decalsystem_numqueued = 0;
10966 }
10967
10968 extern cvar_t cl_decals_max;
10969 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10970 {
10971         int i;
10972         decalsystem_t *decalsystem = &ent->decalsystem;
10973         int numdecals;
10974         int killsequence;
10975         tridecal_t *decal;
10976         float frametime;
10977         float lifetime;
10978
10979         if (!decalsystem->numdecals)
10980                 return;
10981
10982         if (r_showsurfaces.integer)
10983                 return;
10984
10985         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10986         {
10987                 R_DecalSystem_Reset(decalsystem);
10988                 return;
10989         }
10990
10991         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
10992         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
10993
10994         if (decalsystem->lastupdatetime)
10995                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
10996         else
10997                 frametime = 0;
10998         decalsystem->lastupdatetime = r_refdef.scene.time;
10999         decal = decalsystem->decals;
11000         numdecals = decalsystem->numdecals;
11001
11002         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11003         {
11004                 if (decal->color4f[0][3])
11005                 {
11006                         decal->lived += frametime;
11007                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11008                         {
11009                                 memset(decal, 0, sizeof(*decal));
11010                                 if (decalsystem->freedecal > i)
11011                                         decalsystem->freedecal = i;
11012                         }
11013                 }
11014         }
11015         decal = decalsystem->decals;
11016         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11017                 numdecals--;
11018
11019         // collapse the array by shuffling the tail decals into the gaps
11020         for (;;)
11021         {
11022                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11023                         decalsystem->freedecal++;
11024                 if (decalsystem->freedecal == numdecals)
11025                         break;
11026                 decal[decalsystem->freedecal] = decal[--numdecals];
11027         }
11028
11029         decalsystem->numdecals = numdecals;
11030
11031         if (numdecals <= 0)
11032         {
11033                 // if there are no decals left, reset decalsystem
11034                 R_DecalSystem_Reset(decalsystem);
11035         }
11036 }
11037
11038 extern skinframe_t *decalskinframe;
11039 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11040 {
11041         int i;
11042         decalsystem_t *decalsystem = &ent->decalsystem;
11043         int numdecals;
11044         tridecal_t *decal;
11045         float faderate;
11046         float alpha;
11047         float *v3f;
11048         float *c4f;
11049         float *t2f;
11050         const int *e;
11051         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11052         int numtris = 0;
11053
11054         numdecals = decalsystem->numdecals;
11055         if (!numdecals)
11056                 return;
11057
11058         if (r_showsurfaces.integer)
11059                 return;
11060
11061         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11062         {
11063                 R_DecalSystem_Reset(decalsystem);
11064                 return;
11065         }
11066
11067         // if the model is static it doesn't matter what value we give for
11068         // wantnormals and wanttangents, so this logic uses only rules applicable
11069         // to a model, knowing that they are meaningless otherwise
11070         if (ent == r_refdef.scene.worldentity)
11071                 RSurf_ActiveWorldEntity();
11072         else
11073                 RSurf_ActiveModelEntity(ent, false, false, false);
11074
11075         decalsystem->lastupdatetime = r_refdef.scene.time;
11076         decal = decalsystem->decals;
11077
11078         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11079
11080         // update vertex positions for animated models
11081         v3f = decalsystem->vertex3f;
11082         c4f = decalsystem->color4f;
11083         t2f = decalsystem->texcoord2f;
11084         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11085         {
11086                 if (!decal->color4f[0][3])
11087                         continue;
11088
11089                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11090                         continue;
11091
11092                 // skip backfaces
11093                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11094                         continue;
11095
11096                 // update color values for fading decals
11097                 if (decal->lived >= cl_decals_time.value)
11098                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11099                 else
11100                         alpha = 1.0f;
11101
11102                 c4f[ 0] = decal->color4f[0][0] * alpha;
11103                 c4f[ 1] = decal->color4f[0][1] * alpha;
11104                 c4f[ 2] = decal->color4f[0][2] * alpha;
11105                 c4f[ 3] = 1;
11106                 c4f[ 4] = decal->color4f[1][0] * alpha;
11107                 c4f[ 5] = decal->color4f[1][1] * alpha;
11108                 c4f[ 6] = decal->color4f[1][2] * alpha;
11109                 c4f[ 7] = 1;
11110                 c4f[ 8] = decal->color4f[2][0] * alpha;
11111                 c4f[ 9] = decal->color4f[2][1] * alpha;
11112                 c4f[10] = decal->color4f[2][2] * alpha;
11113                 c4f[11] = 1;
11114
11115                 t2f[0] = decal->texcoord2f[0][0];
11116                 t2f[1] = decal->texcoord2f[0][1];
11117                 t2f[2] = decal->texcoord2f[1][0];
11118                 t2f[3] = decal->texcoord2f[1][1];
11119                 t2f[4] = decal->texcoord2f[2][0];
11120                 t2f[5] = decal->texcoord2f[2][1];
11121
11122                 // update vertex positions for animated models
11123                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11124                 {
11125                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11126                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11127                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11128                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11129                 }
11130                 else
11131                 {
11132                         VectorCopy(decal->vertex3f[0], v3f);
11133                         VectorCopy(decal->vertex3f[1], v3f + 3);
11134                         VectorCopy(decal->vertex3f[2], v3f + 6);
11135                 }
11136
11137                 if (r_refdef.fogenabled)
11138                 {
11139                         alpha = RSurf_FogVertex(v3f);
11140                         VectorScale(c4f, alpha, c4f);
11141                         alpha = RSurf_FogVertex(v3f + 3);
11142                         VectorScale(c4f + 4, alpha, c4f + 4);
11143                         alpha = RSurf_FogVertex(v3f + 6);
11144                         VectorScale(c4f + 8, alpha, c4f + 8);
11145                 }
11146
11147                 v3f += 9;
11148                 c4f += 12;
11149                 t2f += 6;
11150                 numtris++;
11151         }
11152
11153         if (numtris > 0)
11154         {
11155                 r_refdef.stats.drawndecals += numtris;
11156
11157                 // now render the decals all at once
11158                 // (this assumes they all use one particle font texture!)
11159                 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);
11160 //              R_Mesh_ResetTextureState();
11161                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11162                 GL_DepthMask(false);
11163                 GL_DepthRange(0, 1);
11164                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11165                 GL_DepthTest(true);
11166                 GL_CullFace(GL_NONE);
11167                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11168                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11169                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11170         }
11171 }
11172
11173 static void R_DrawModelDecals(void)
11174 {
11175         int i, numdecals;
11176
11177         // fade faster when there are too many decals
11178         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11179         for (i = 0;i < r_refdef.scene.numentities;i++)
11180                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11181
11182         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11183         for (i = 0;i < r_refdef.scene.numentities;i++)
11184                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11185                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11186
11187         R_DecalSystem_ApplySplatEntitiesQueue();
11188
11189         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11190         for (i = 0;i < r_refdef.scene.numentities;i++)
11191                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11192
11193         r_refdef.stats.totaldecals += numdecals;
11194
11195         if (r_showsurfaces.integer)
11196                 return;
11197
11198         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11199
11200         for (i = 0;i < r_refdef.scene.numentities;i++)
11201         {
11202                 if (!r_refdef.viewcache.entityvisible[i])
11203                         continue;
11204                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11205                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11206         }
11207 }
11208
11209 extern cvar_t mod_collision_bih;
11210 void R_DrawDebugModel(void)
11211 {
11212         entity_render_t *ent = rsurface.entity;
11213         int i, j, k, l, flagsmask;
11214         const msurface_t *surface;
11215         dp_model_t *model = ent->model;
11216         vec3_t v;
11217
11218         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11219                 return;
11220
11221         if (r_showoverdraw.value > 0)
11222         {
11223                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11224                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11225                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11226                 GL_DepthTest(false);
11227                 GL_DepthMask(false);
11228                 GL_DepthRange(0, 1);
11229                 GL_BlendFunc(GL_ONE, GL_ONE);
11230                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11231                 {
11232                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11233                                 continue;
11234                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11235                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11236                         {
11237                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11238                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11239                                 if (!rsurface.texture->currentlayers->depthmask)
11240                                         GL_Color(c, 0, 0, 1.0f);
11241                                 else if (ent == r_refdef.scene.worldentity)
11242                                         GL_Color(c, c, c, 1.0f);
11243                                 else
11244                                         GL_Color(0, c, 0, 1.0f);
11245                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11246                                 RSurf_DrawBatch();
11247                         }
11248                 }
11249                 rsurface.texture = NULL;
11250         }
11251
11252         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11253
11254 //      R_Mesh_ResetTextureState();
11255         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11256         GL_DepthRange(0, 1);
11257         GL_DepthTest(!r_showdisabledepthtest.integer);
11258         GL_DepthMask(false);
11259         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11260
11261         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11262         {
11263                 int triangleindex;
11264                 int bihleafindex;
11265                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11266                 const q3mbrush_t *brush;
11267                 const bih_t *bih = &model->collision_bih;
11268                 const bih_leaf_t *bihleaf;
11269                 float vertex3f[3][3];
11270                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11271                 cullbox = false;
11272                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11273                 {
11274                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11275                                 continue;
11276                         switch (bihleaf->type)
11277                         {
11278                         case BIH_BRUSH:
11279                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11280                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11281                                 {
11282                                         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);
11283                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11284                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11285                                 }
11286                                 break;
11287                         case BIH_COLLISIONTRIANGLE:
11288                                 triangleindex = bihleaf->itemindex;
11289                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11290                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11291                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11292                                 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);
11293                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11294                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11295                                 break;
11296                         case BIH_RENDERTRIANGLE:
11297                                 triangleindex = bihleaf->itemindex;
11298                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11299                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11300                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11301                                 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);
11302                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11303                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11304                                 break;
11305                         }
11306                 }
11307         }
11308
11309         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11310
11311         if (r_showtris.integer && qglPolygonMode)
11312         {
11313                 if (r_showdisabledepthtest.integer)
11314                 {
11315                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11316                         GL_DepthMask(false);
11317                 }
11318                 else
11319                 {
11320                         GL_BlendFunc(GL_ONE, GL_ZERO);
11321                         GL_DepthMask(true);
11322                 }
11323                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11324                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11325                 {
11326                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11327                                 continue;
11328                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11329                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11330                         {
11331                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11332                                 if (!rsurface.texture->currentlayers->depthmask)
11333                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11334                                 else if (ent == r_refdef.scene.worldentity)
11335                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11336                                 else
11337                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11338                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11339                                 RSurf_DrawBatch();
11340                         }
11341                 }
11342                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11343                 rsurface.texture = NULL;
11344         }
11345
11346         if (r_shownormals.value != 0 && qglBegin)
11347         {
11348                 if (r_showdisabledepthtest.integer)
11349                 {
11350                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11351                         GL_DepthMask(false);
11352                 }
11353                 else
11354                 {
11355                         GL_BlendFunc(GL_ONE, GL_ZERO);
11356                         GL_DepthMask(true);
11357                 }
11358                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11359                 {
11360                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11361                                 continue;
11362                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11363                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11364                         {
11365                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11366                                 qglBegin(GL_LINES);
11367                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11368                                 {
11369                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11370                                         {
11371                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11372                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11373                                                 qglVertex3f(v[0], v[1], v[2]);
11374                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11375                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11376                                                 qglVertex3f(v[0], v[1], v[2]);
11377                                         }
11378                                 }
11379                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11380                                 {
11381                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11382                                         {
11383                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11384                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11385                                                 qglVertex3f(v[0], v[1], v[2]);
11386                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11387                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11388                                                 qglVertex3f(v[0], v[1], v[2]);
11389                                         }
11390                                 }
11391                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11392                                 {
11393                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11394                                         {
11395                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11396                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11397                                                 qglVertex3f(v[0], v[1], v[2]);
11398                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11399                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11400                                                 qglVertex3f(v[0], v[1], v[2]);
11401                                         }
11402                                 }
11403                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11404                                 {
11405                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11406                                         {
11407                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11408                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11409                                                 qglVertex3f(v[0], v[1], v[2]);
11410                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11411                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11412                                                 qglVertex3f(v[0], v[1], v[2]);
11413                                         }
11414                                 }
11415                                 qglEnd();
11416                                 CHECKGLERROR
11417                         }
11418                 }
11419                 rsurface.texture = NULL;
11420         }
11421 }
11422
11423 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11424 int r_maxsurfacelist = 0;
11425 const msurface_t **r_surfacelist = NULL;
11426 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11427 {
11428         int i, j, endj, flagsmask;
11429         dp_model_t *model = r_refdef.scene.worldmodel;
11430         msurface_t *surfaces;
11431         unsigned char *update;
11432         int numsurfacelist = 0;
11433         if (model == NULL)
11434                 return;
11435
11436         if (r_maxsurfacelist < model->num_surfaces)
11437         {
11438                 r_maxsurfacelist = model->num_surfaces;
11439                 if (r_surfacelist)
11440                         Mem_Free((msurface_t**)r_surfacelist);
11441                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11442         }
11443
11444         RSurf_ActiveWorldEntity();
11445
11446         surfaces = model->data_surfaces;
11447         update = model->brushq1.lightmapupdateflags;
11448
11449         // update light styles on this submodel
11450         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11451         {
11452                 model_brush_lightstyleinfo_t *style;
11453                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11454                 {
11455                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11456                         {
11457                                 int *list = style->surfacelist;
11458                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11459                                 for (j = 0;j < style->numsurfaces;j++)
11460                                         update[list[j]] = true;
11461                         }
11462                 }
11463         }
11464
11465         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11466
11467         if (debug)
11468         {
11469                 R_DrawDebugModel();
11470                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11471                 return;
11472         }
11473
11474         rsurface.lightmaptexture = NULL;
11475         rsurface.deluxemaptexture = NULL;
11476         rsurface.uselightmaptexture = false;
11477         rsurface.texture = NULL;
11478         rsurface.rtlight = NULL;
11479         numsurfacelist = 0;
11480         // add visible surfaces to draw list
11481         for (i = 0;i < model->nummodelsurfaces;i++)
11482         {
11483                 j = model->sortedmodelsurfaces[i];
11484                 if (r_refdef.viewcache.world_surfacevisible[j])
11485                         r_surfacelist[numsurfacelist++] = surfaces + j;
11486         }
11487         // update lightmaps if needed
11488         if (model->brushq1.firstrender)
11489         {
11490                 model->brushq1.firstrender = false;
11491                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11492                         if (update[j])
11493                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11494         }
11495         else if (update)
11496         {
11497                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11498                         if (r_refdef.viewcache.world_surfacevisible[j])
11499                                 if (update[j])
11500                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11501         }
11502         // don't do anything if there were no surfaces
11503         if (!numsurfacelist)
11504         {
11505                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11506                 return;
11507         }
11508         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11509
11510         // add to stats if desired
11511         if (r_speeds.integer && !skysurfaces && !depthonly)
11512         {
11513                 r_refdef.stats.world_surfaces += numsurfacelist;
11514                 for (j = 0;j < numsurfacelist;j++)
11515                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11516         }
11517
11518         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11519 }
11520
11521 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11522 {
11523         int i, j, endj, flagsmask;
11524         dp_model_t *model = ent->model;
11525         msurface_t *surfaces;
11526         unsigned char *update;
11527         int numsurfacelist = 0;
11528         if (model == NULL)
11529                 return;
11530
11531         if (r_maxsurfacelist < model->num_surfaces)
11532         {
11533                 r_maxsurfacelist = model->num_surfaces;
11534                 if (r_surfacelist)
11535                         Mem_Free((msurface_t **)r_surfacelist);
11536                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11537         }
11538
11539         // if the model is static it doesn't matter what value we give for
11540         // wantnormals and wanttangents, so this logic uses only rules applicable
11541         // to a model, knowing that they are meaningless otherwise
11542         if (ent == r_refdef.scene.worldentity)
11543                 RSurf_ActiveWorldEntity();
11544         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11545                 RSurf_ActiveModelEntity(ent, false, false, false);
11546         else if (prepass)
11547                 RSurf_ActiveModelEntity(ent, true, true, true);
11548         else if (depthonly)
11549         {
11550                 switch (vid.renderpath)
11551                 {
11552                 case RENDERPATH_GL20:
11553                 case RENDERPATH_D3D9:
11554                 case RENDERPATH_D3D10:
11555                 case RENDERPATH_D3D11:
11556                 case RENDERPATH_SOFT:
11557                 case RENDERPATH_GLES2:
11558                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11559                         break;
11560                 case RENDERPATH_GL11:
11561                 case RENDERPATH_GL13:
11562                 case RENDERPATH_GLES1:
11563                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11564                         break;
11565                 }
11566         }
11567         else
11568         {
11569                 switch (vid.renderpath)
11570                 {
11571                 case RENDERPATH_GL20:
11572                 case RENDERPATH_D3D9:
11573                 case RENDERPATH_D3D10:
11574                 case RENDERPATH_D3D11:
11575                 case RENDERPATH_SOFT:
11576                 case RENDERPATH_GLES2:
11577                         RSurf_ActiveModelEntity(ent, true, true, false);
11578                         break;
11579                 case RENDERPATH_GL11:
11580                 case RENDERPATH_GL13:
11581                 case RENDERPATH_GLES1:
11582                         RSurf_ActiveModelEntity(ent, true, false, false);
11583                         break;
11584                 }
11585         }
11586
11587         surfaces = model->data_surfaces;
11588         update = model->brushq1.lightmapupdateflags;
11589
11590         // update light styles
11591         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11592         {
11593                 model_brush_lightstyleinfo_t *style;
11594                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11595                 {
11596                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11597                         {
11598                                 int *list = style->surfacelist;
11599                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11600                                 for (j = 0;j < style->numsurfaces;j++)
11601                                         update[list[j]] = true;
11602                         }
11603                 }
11604         }
11605
11606         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11607
11608         if (debug)
11609         {
11610                 R_DrawDebugModel();
11611                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11612                 return;
11613         }
11614
11615         rsurface.lightmaptexture = NULL;
11616         rsurface.deluxemaptexture = NULL;
11617         rsurface.uselightmaptexture = false;
11618         rsurface.texture = NULL;
11619         rsurface.rtlight = NULL;
11620         numsurfacelist = 0;
11621         // add visible surfaces to draw list
11622         for (i = 0;i < model->nummodelsurfaces;i++)
11623                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11624         // don't do anything if there were no surfaces
11625         if (!numsurfacelist)
11626         {
11627                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11628                 return;
11629         }
11630         // update lightmaps if needed
11631         if (update)
11632         {
11633                 int updated = 0;
11634                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11635                 {
11636                         if (update[j])
11637                         {
11638                                 updated++;
11639                                 R_BuildLightMap(ent, surfaces + j);
11640                         }
11641                 }
11642         }
11643         if (update)
11644                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11645                         if (update[j])
11646                                 R_BuildLightMap(ent, surfaces + j);
11647         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11648
11649         // add to stats if desired
11650         if (r_speeds.integer && !skysurfaces && !depthonly)
11651         {
11652                 r_refdef.stats.entities_surfaces += numsurfacelist;
11653                 for (j = 0;j < numsurfacelist;j++)
11654                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11655         }
11656
11657         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11658 }
11659
11660 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11661 {
11662         static texture_t texture;
11663         static msurface_t surface;
11664         const msurface_t *surfacelist = &surface;
11665
11666         // fake enough texture and surface state to render this geometry
11667
11668         texture.update_lastrenderframe = -1; // regenerate this texture
11669         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11670         texture.currentskinframe = skinframe;
11671         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11672         texture.offsetmapping = OFFSETMAPPING_OFF;
11673         texture.offsetscale = 1;
11674         texture.specularscalemod = 1;
11675         texture.specularpowermod = 1;
11676
11677         surface.texture = &texture;
11678         surface.num_triangles = numtriangles;
11679         surface.num_firsttriangle = firsttriangle;
11680         surface.num_vertices = numvertices;
11681         surface.num_firstvertex = firstvertex;
11682
11683         // now render it
11684         rsurface.texture = R_GetCurrentTexture(surface.texture);
11685         rsurface.lightmaptexture = NULL;
11686         rsurface.deluxemaptexture = NULL;
11687         rsurface.uselightmaptexture = false;
11688         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11689 }
11690
11691 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)
11692 {
11693         static msurface_t surface;
11694         const msurface_t *surfacelist = &surface;
11695
11696         // fake enough texture and surface state to render this geometry
11697         surface.texture = texture;
11698         surface.num_triangles = numtriangles;
11699         surface.num_firsttriangle = firsttriangle;
11700         surface.num_vertices = numvertices;
11701         surface.num_firstvertex = firstvertex;
11702
11703         // now render it
11704         rsurface.texture = R_GetCurrentTexture(surface.texture);
11705         rsurface.lightmaptexture = NULL;
11706         rsurface.deluxemaptexture = NULL;
11707         rsurface.uselightmaptexture = false;
11708         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11709 }