]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Change how the factor is calculated and set it up to be finished
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "motionblur value scale - 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "motionblur based on damage"};
55 cvar_t r_motionblur_vmin = {CVAR_SAVE, "r_motionblur_vmin", "300", "minimum influence from velocity"};
56 cvar_t r_motionblur_vmax = {CVAR_SAVE, "r_motionblur_vmax", "600", "maximum influence from velocity"};
57 cvar_t r_motionblur_bmin = {CVAR_SAVE, "r_motionblur_bmin", "0.5", "velocity at which there is no blur yet (may be negative to always have some blur)"};
58 cvar_t r_motionblur_vcoeff = {CVAR_SAVE, "r_motionblur_vcoeff", "0.05", "sliding average reaction time for velocity"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.88", "cap for motionblur alpha value"};
60 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
61
62 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
63 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
64 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
65 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
66 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
67
68 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
69 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
70 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
71 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
72 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
73 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
74 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
75 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
76 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
77 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
78 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
79 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
80 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
81 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
82 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
83 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
84 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
85 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
86 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
87 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
88 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
89 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
90 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
91 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
92 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
93 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
94 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
95 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
96 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
97 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
98 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
99 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
100
101 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
102 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
103 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
104
105 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
106 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
107 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
108 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
109 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
110 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
111 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
112 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
113 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
114 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
115 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
116 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
117 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
118 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
119 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
120 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
121 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
122 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
123 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
124 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
125 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
126 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
127
128 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
129 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
130 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
131 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
132 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
133 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
134 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
135 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
136
137 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
138 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
139
140 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
141 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
142 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
143
144 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
145 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
146 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
147 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
148 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
149 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
150 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
151 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
152
153 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
154 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
155 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
156 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
157 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
158 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
159 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
160 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
161 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
162 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
163 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
164 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
165 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
169
170 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
171 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
172 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
173 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
174 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
175 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
176 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
177
178 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
179 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
180 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
181 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
182
183 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
184 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
185 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
186 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
187 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
188 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
189 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
190
191 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
192 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
193 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
194 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
195 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
196 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
197 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
198 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
199 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
200 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
201 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
202
203 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
204
205 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
206
207 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
208
209 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
210
211 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
212 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
213
214 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
215
216 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
217
218 extern cvar_t v_glslgamma;
219
220 extern qboolean v_flipped_state;
221
222 static struct r_bloomstate_s
223 {
224         qboolean enabled;
225         qboolean hdr;
226
227         int bloomwidth, bloomheight;
228
229         textype_t texturetype;
230         int viewfbo; // used to check if r_viewfbo cvar has changed
231
232         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
233         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
234         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
235
236         int screentexturewidth, screentextureheight;
237         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
238
239         int bloomtexturewidth, bloomtextureheight;
240         rtexture_t *texture_bloom;
241
242         // arrays for rendering the screen passes
243         float screentexcoord2f[8];
244         float bloomtexcoord2f[8];
245         float offsettexcoord2f[8];
246
247         r_viewport_t viewport;
248 }
249 r_bloomstate;
250
251 r_waterstate_t r_waterstate;
252
253 /// shadow volume bsp struct with automatically growing nodes buffer
254 svbsp_t r_svbsp;
255
256 rtexture_t *r_texture_blanknormalmap;
257 rtexture_t *r_texture_white;
258 rtexture_t *r_texture_grey128;
259 rtexture_t *r_texture_black;
260 rtexture_t *r_texture_notexture;
261 rtexture_t *r_texture_whitecube;
262 rtexture_t *r_texture_normalizationcube;
263 rtexture_t *r_texture_fogattenuation;
264 rtexture_t *r_texture_fogheighttexture;
265 rtexture_t *r_texture_gammaramps;
266 unsigned int r_texture_gammaramps_serial;
267 //rtexture_t *r_texture_fogintensity;
268 rtexture_t *r_texture_reflectcube;
269
270 // TODO: hash lookups?
271 typedef struct cubemapinfo_s
272 {
273         char basename[64];
274         rtexture_t *texture;
275 }
276 cubemapinfo_t;
277
278 int r_texture_numcubemaps;
279 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
280
281 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
282 unsigned int r_numqueries;
283 unsigned int r_maxqueries;
284
285 typedef struct r_qwskincache_s
286 {
287         char name[MAX_QPATH];
288         skinframe_t *skinframe;
289 }
290 r_qwskincache_t;
291
292 static r_qwskincache_t *r_qwskincache;
293 static int r_qwskincache_size;
294
295 /// vertex coordinates for a quad that covers the screen exactly
296 extern const float r_screenvertex3f[12];
297 extern const float r_d3dscreenvertex3f[12];
298 const float r_screenvertex3f[12] =
299 {
300         0, 0, 0,
301         1, 0, 0,
302         1, 1, 0,
303         0, 1, 0
304 };
305 const float r_d3dscreenvertex3f[12] =
306 {
307         0, 1, 0,
308         1, 1, 0,
309         1, 0, 0,
310         0, 0, 0
311 };
312
313 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
314 {
315         int i;
316         for (i = 0;i < verts;i++)
317         {
318                 out[0] = in[0] * r;
319                 out[1] = in[1] * g;
320                 out[2] = in[2] * b;
321                 out[3] = in[3];
322                 in += 4;
323                 out += 4;
324         }
325 }
326
327 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
328 {
329         int i;
330         for (i = 0;i < verts;i++)
331         {
332                 out[0] = r;
333                 out[1] = g;
334                 out[2] = b;
335                 out[3] = a;
336                 out += 4;
337         }
338 }
339
340 // FIXME: move this to client?
341 void FOG_clear(void)
342 {
343         if (gamemode == GAME_NEHAHRA)
344         {
345                 Cvar_Set("gl_fogenable", "0");
346                 Cvar_Set("gl_fogdensity", "0.2");
347                 Cvar_Set("gl_fogred", "0.3");
348                 Cvar_Set("gl_foggreen", "0.3");
349                 Cvar_Set("gl_fogblue", "0.3");
350         }
351         r_refdef.fog_density = 0;
352         r_refdef.fog_red = 0;
353         r_refdef.fog_green = 0;
354         r_refdef.fog_blue = 0;
355         r_refdef.fog_alpha = 1;
356         r_refdef.fog_start = 0;
357         r_refdef.fog_end = 16384;
358         r_refdef.fog_height = 1<<30;
359         r_refdef.fog_fadedepth = 128;
360         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
361 }
362
363 static void R_BuildBlankTextures(void)
364 {
365         unsigned char data[4];
366         data[2] = 128; // normal X
367         data[1] = 128; // normal Y
368         data[0] = 255; // normal Z
369         data[3] = 128; // height
370         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
371         data[0] = 255;
372         data[1] = 255;
373         data[2] = 255;
374         data[3] = 255;
375         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 128;
377         data[1] = 128;
378         data[2] = 128;
379         data[3] = 255;
380         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 0;
382         data[1] = 0;
383         data[2] = 0;
384         data[3] = 255;
385         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386 }
387
388 static void R_BuildNoTexture(void)
389 {
390         int x, y;
391         unsigned char pix[16][16][4];
392         // this makes a light grey/dark grey checkerboard texture
393         for (y = 0;y < 16;y++)
394         {
395                 for (x = 0;x < 16;x++)
396                 {
397                         if ((y < 8) ^ (x < 8))
398                         {
399                                 pix[y][x][0] = 128;
400                                 pix[y][x][1] = 128;
401                                 pix[y][x][2] = 128;
402                                 pix[y][x][3] = 255;
403                         }
404                         else
405                         {
406                                 pix[y][x][0] = 64;
407                                 pix[y][x][1] = 64;
408                                 pix[y][x][2] = 64;
409                                 pix[y][x][3] = 255;
410                         }
411                 }
412         }
413         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
414 }
415
416 static void R_BuildWhiteCube(void)
417 {
418         unsigned char data[6*1*1*4];
419         memset(data, 255, sizeof(data));
420         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
421 }
422
423 static void R_BuildNormalizationCube(void)
424 {
425         int x, y, side;
426         vec3_t v;
427         vec_t s, t, intensity;
428 #define NORMSIZE 64
429         unsigned char *data;
430         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
431         for (side = 0;side < 6;side++)
432         {
433                 for (y = 0;y < NORMSIZE;y++)
434                 {
435                         for (x = 0;x < NORMSIZE;x++)
436                         {
437                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
438                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
439                                 switch(side)
440                                 {
441                                 default:
442                                 case 0:
443                                         v[0] = 1;
444                                         v[1] = -t;
445                                         v[2] = -s;
446                                         break;
447                                 case 1:
448                                         v[0] = -1;
449                                         v[1] = -t;
450                                         v[2] = s;
451                                         break;
452                                 case 2:
453                                         v[0] = s;
454                                         v[1] = 1;
455                                         v[2] = t;
456                                         break;
457                                 case 3:
458                                         v[0] = s;
459                                         v[1] = -1;
460                                         v[2] = -t;
461                                         break;
462                                 case 4:
463                                         v[0] = s;
464                                         v[1] = -t;
465                                         v[2] = 1;
466                                         break;
467                                 case 5:
468                                         v[0] = -s;
469                                         v[1] = -t;
470                                         v[2] = -1;
471                                         break;
472                                 }
473                                 intensity = 127.0f / sqrt(DotProduct(v, v));
474                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
475                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
476                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
477                                 data[((side*64+y)*64+x)*4+3] = 255;
478                         }
479                 }
480         }
481         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
482         Mem_Free(data);
483 }
484
485 static void R_BuildFogTexture(void)
486 {
487         int x, b;
488 #define FOGWIDTH 256
489         unsigned char data1[FOGWIDTH][4];
490         //unsigned char data2[FOGWIDTH][4];
491         double d, r, alpha;
492
493         r_refdef.fogmasktable_start = r_refdef.fog_start;
494         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
495         r_refdef.fogmasktable_range = r_refdef.fogrange;
496         r_refdef.fogmasktable_density = r_refdef.fog_density;
497
498         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
499         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
500         {
501                 d = (x * r - r_refdef.fogmasktable_start);
502                 if(developer_extra.integer)
503                         Con_DPrintf("%f ", d);
504                 d = max(0, d);
505                 if (r_fog_exp2.integer)
506                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
507                 else
508                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
509                 if(developer_extra.integer)
510                         Con_DPrintf(" : %f ", alpha);
511                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
512                 if(developer_extra.integer)
513                         Con_DPrintf(" = %f\n", alpha);
514                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
515         }
516
517         for (x = 0;x < FOGWIDTH;x++)
518         {
519                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
520                 data1[x][0] = b;
521                 data1[x][1] = b;
522                 data1[x][2] = b;
523                 data1[x][3] = 255;
524                 //data2[x][0] = 255 - b;
525                 //data2[x][1] = 255 - b;
526                 //data2[x][2] = 255 - b;
527                 //data2[x][3] = 255;
528         }
529         if (r_texture_fogattenuation)
530         {
531                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
532                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
533         }
534         else
535         {
536                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
537                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
538         }
539 }
540
541 static void R_BuildFogHeightTexture(void)
542 {
543         unsigned char *inpixels;
544         int size;
545         int x;
546         int y;
547         int j;
548         float c[4];
549         float f;
550         inpixels = NULL;
551         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
552         if (r_refdef.fogheighttexturename[0])
553                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
554         if (!inpixels)
555         {
556                 r_refdef.fog_height_tablesize = 0;
557                 if (r_texture_fogheighttexture)
558                         R_FreeTexture(r_texture_fogheighttexture);
559                 r_texture_fogheighttexture = NULL;
560                 if (r_refdef.fog_height_table2d)
561                         Mem_Free(r_refdef.fog_height_table2d);
562                 r_refdef.fog_height_table2d = NULL;
563                 if (r_refdef.fog_height_table1d)
564                         Mem_Free(r_refdef.fog_height_table1d);
565                 r_refdef.fog_height_table1d = NULL;
566                 return;
567         }
568         size = image_width;
569         r_refdef.fog_height_tablesize = size;
570         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
571         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
572         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
573         Mem_Free(inpixels);
574         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
575         // average fog color table accounting for every fog layer between a point
576         // and the camera.  (Note: attenuation is handled separately!)
577         for (y = 0;y < size;y++)
578         {
579                 for (x = 0;x < size;x++)
580                 {
581                         Vector4Clear(c);
582                         f = 0;
583                         if (x < y)
584                         {
585                                 for (j = x;j <= y;j++)
586                                 {
587                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
588                                         f++;
589                                 }
590                         }
591                         else
592                         {
593                                 for (j = x;j >= y;j--)
594                                 {
595                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
596                                         f++;
597                                 }
598                         }
599                         f = 1.0f / f;
600                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
601                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
602                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
603                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
604                 }
605         }
606         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
607 }
608
609 //=======================================================================================================================================================
610
611 static const char *builtinshaderstring =
612 #include "shader_glsl.h"
613 ;
614
615 const char *builtinhlslshaderstring =
616 #include "shader_hlsl.h"
617 ;
618
619 char *glslshaderstring = NULL;
620 char *hlslshaderstring = NULL;
621
622 //=======================================================================================================================================================
623
624 typedef struct shaderpermutationinfo_s
625 {
626         const char *pretext;
627         const char *name;
628 }
629 shaderpermutationinfo_t;
630
631 typedef struct shadermodeinfo_s
632 {
633         const char *vertexfilename;
634         const char *geometryfilename;
635         const char *fragmentfilename;
636         const char *pretext;
637         const char *name;
638 }
639 shadermodeinfo_t;
640
641 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
642 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
643 {
644         {"#define USEDIFFUSE\n", " diffuse"},
645         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
646         {"#define USEVIEWTINT\n", " viewtint"},
647         {"#define USECOLORMAPPING\n", " colormapping"},
648         {"#define USESATURATION\n", " saturation"},
649         {"#define USEFOGINSIDE\n", " foginside"},
650         {"#define USEFOGOUTSIDE\n", " fogoutside"},
651         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
652         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
653         {"#define USEGAMMARAMPS\n", " gammaramps"},
654         {"#define USECUBEFILTER\n", " cubefilter"},
655         {"#define USEGLOW\n", " glow"},
656         {"#define USEBLOOM\n", " bloom"},
657         {"#define USESPECULAR\n", " specular"},
658         {"#define USEPOSTPROCESSING\n", " postprocessing"},
659         {"#define USEREFLECTION\n", " reflection"},
660         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
661         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
662         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
663         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
664         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
665         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
666         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
667         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
668         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
669         {"#define USEALPHAKILL\n", " alphakill"},
670         {"#define USEREFLECTCUBE\n", " reflectcube"},
671         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
672         {"#define USEBOUNCEGRID\n", " bouncegrid"},
673         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
674         {"#define USETRIPPY\n", " trippy"},
675 };
676
677 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
678 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
679 {
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
682         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
696 };
697
698 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
699 {
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
716 };
717
718 struct r_glsl_permutation_s;
719 typedef struct r_glsl_permutation_s
720 {
721         /// hash lookup data
722         struct r_glsl_permutation_s *hashnext;
723         unsigned int mode;
724         unsigned int permutation;
725
726         /// indicates if we have tried compiling this permutation already
727         qboolean compiled;
728         /// 0 if compilation failed
729         int program;
730         // texture units assigned to each detected uniform
731         int tex_Texture_First;
732         int tex_Texture_Second;
733         int tex_Texture_GammaRamps;
734         int tex_Texture_Normal;
735         int tex_Texture_Color;
736         int tex_Texture_Gloss;
737         int tex_Texture_Glow;
738         int tex_Texture_SecondaryNormal;
739         int tex_Texture_SecondaryColor;
740         int tex_Texture_SecondaryGloss;
741         int tex_Texture_SecondaryGlow;
742         int tex_Texture_Pants;
743         int tex_Texture_Shirt;
744         int tex_Texture_FogHeightTexture;
745         int tex_Texture_FogMask;
746         int tex_Texture_Lightmap;
747         int tex_Texture_Deluxemap;
748         int tex_Texture_Attenuation;
749         int tex_Texture_Cube;
750         int tex_Texture_Refraction;
751         int tex_Texture_Reflection;
752         int tex_Texture_ShadowMap2D;
753         int tex_Texture_CubeProjection;
754         int tex_Texture_ScreenDepth;
755         int tex_Texture_ScreenNormalMap;
756         int tex_Texture_ScreenDiffuse;
757         int tex_Texture_ScreenSpecular;
758         int tex_Texture_ReflectMask;
759         int tex_Texture_ReflectCube;
760         int tex_Texture_BounceGrid;
761         /// locations of detected uniforms in program object, or -1 if not found
762         int loc_Texture_First;
763         int loc_Texture_Second;
764         int loc_Texture_GammaRamps;
765         int loc_Texture_Normal;
766         int loc_Texture_Color;
767         int loc_Texture_Gloss;
768         int loc_Texture_Glow;
769         int loc_Texture_SecondaryNormal;
770         int loc_Texture_SecondaryColor;
771         int loc_Texture_SecondaryGloss;
772         int loc_Texture_SecondaryGlow;
773         int loc_Texture_Pants;
774         int loc_Texture_Shirt;
775         int loc_Texture_FogHeightTexture;
776         int loc_Texture_FogMask;
777         int loc_Texture_Lightmap;
778         int loc_Texture_Deluxemap;
779         int loc_Texture_Attenuation;
780         int loc_Texture_Cube;
781         int loc_Texture_Refraction;
782         int loc_Texture_Reflection;
783         int loc_Texture_ShadowMap2D;
784         int loc_Texture_CubeProjection;
785         int loc_Texture_ScreenDepth;
786         int loc_Texture_ScreenNormalMap;
787         int loc_Texture_ScreenDiffuse;
788         int loc_Texture_ScreenSpecular;
789         int loc_Texture_ReflectMask;
790         int loc_Texture_ReflectCube;
791         int loc_Texture_BounceGrid;
792         int loc_Alpha;
793         int loc_BloomBlur_Parameters;
794         int loc_ClientTime;
795         int loc_Color_Ambient;
796         int loc_Color_Diffuse;
797         int loc_Color_Specular;
798         int loc_Color_Glow;
799         int loc_Color_Pants;
800         int loc_Color_Shirt;
801         int loc_DeferredColor_Ambient;
802         int loc_DeferredColor_Diffuse;
803         int loc_DeferredColor_Specular;
804         int loc_DeferredMod_Diffuse;
805         int loc_DeferredMod_Specular;
806         int loc_DistortScaleRefractReflect;
807         int loc_EyePosition;
808         int loc_FogColor;
809         int loc_FogHeightFade;
810         int loc_FogPlane;
811         int loc_FogPlaneViewDist;
812         int loc_FogRangeRecip;
813         int loc_LightColor;
814         int loc_LightDir;
815         int loc_LightPosition;
816         int loc_OffsetMapping_ScaleSteps;
817         int loc_PixelSize;
818         int loc_ReflectColor;
819         int loc_ReflectFactor;
820         int loc_ReflectOffset;
821         int loc_RefractColor;
822         int loc_Saturation;
823         int loc_ScreenCenterRefractReflect;
824         int loc_ScreenScaleRefractReflect;
825         int loc_ScreenToDepth;
826         int loc_ShadowMap_Parameters;
827         int loc_ShadowMap_TextureScale;
828         int loc_SpecularPower;
829         int loc_UserVec1;
830         int loc_UserVec2;
831         int loc_UserVec3;
832         int loc_UserVec4;
833         int loc_ViewTintColor;
834         int loc_ViewToLight;
835         int loc_ModelToLight;
836         int loc_TexMatrix;
837         int loc_BackgroundTexMatrix;
838         int loc_ModelViewProjectionMatrix;
839         int loc_ModelViewMatrix;
840         int loc_PixelToScreenTexCoord;
841         int loc_ModelToReflectCube;
842         int loc_ShadowMapMatrix;
843         int loc_BloomColorSubtract;
844         int loc_NormalmapScrollBlend;
845         int loc_BounceGridMatrix;
846         int loc_BounceGridIntensity;
847 }
848 r_glsl_permutation_t;
849
850 #define SHADERPERMUTATION_HASHSIZE 256
851
852
853 // non-degradable "lightweight" shader parameters to keep the permutations simpler
854 // these can NOT degrade! only use for simple stuff
855 enum
856 {
857         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
858         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
859         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
861         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
862         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
863         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
864 };
865 #define SHADERSTATICPARMS_COUNT 7
866
867 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
868 static int shaderstaticparms_count = 0;
869
870 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
871 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
872 qboolean R_CompileShader_CheckStaticParms(void)
873 {
874         static int r_compileshader_staticparms_save[1];
875         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
876         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
877
878         // detect all
879         if (r_glsl_saturation_redcompensate.integer)
880                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
881         if (r_glsl_vertextextureblend_usebothalphas.integer)
882                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
883         if (r_shadow_glossexact.integer)
884                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
885         if (r_glsl_postprocess.integer)
886         {
887                 if (r_glsl_postprocess_uservec1_enable.integer)
888                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
889                 if (r_glsl_postprocess_uservec2_enable.integer)
890                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
891                 if (r_glsl_postprocess_uservec3_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
893                 if (r_glsl_postprocess_uservec4_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
895         }
896         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
897 }
898
899 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
900         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
901                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
902         else \
903                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
904 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
905 {
906         shaderstaticparms_count = 0;
907
908         // emit all
909         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
910         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
911         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
912         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
916 }
917
918 /// information about each possible shader permutation
919 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
920 /// currently selected permutation
921 r_glsl_permutation_t *r_glsl_permutation;
922 /// storage for permutations linked in the hash table
923 memexpandablearray_t r_glsl_permutationarray;
924
925 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
926 {
927         //unsigned int hashdepth = 0;
928         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
929         r_glsl_permutation_t *p;
930         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
931         {
932                 if (p->mode == mode && p->permutation == permutation)
933                 {
934                         //if (hashdepth > 10)
935                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
936                         return p;
937                 }
938                 //hashdepth++;
939         }
940         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
941         p->mode = mode;
942         p->permutation = permutation;
943         p->hashnext = r_glsl_permutationhash[mode][hashindex];
944         r_glsl_permutationhash[mode][hashindex] = p;
945         //if (hashdepth > 10)
946         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
947         return p;
948 }
949
950 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
951 {
952         char *shaderstring;
953         if (!filename || !filename[0])
954                 return NULL;
955         if (!strcmp(filename, "glsl/default.glsl"))
956         {
957                 if (!glslshaderstring)
958                 {
959                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
960                         if (glslshaderstring)
961                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
962                         else
963                                 glslshaderstring = (char *)builtinshaderstring;
964                 }
965                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
966                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
967                 return shaderstring;
968         }
969         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
970         if (shaderstring)
971         {
972                 if (printfromdisknotice)
973                         Con_DPrintf("from disk %s... ", filename);
974                 return shaderstring;
975         }
976         return shaderstring;
977 }
978
979 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
980 {
981         int i;
982         int sampler;
983         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
984         char *vertexstring, *geometrystring, *fragmentstring;
985         char permutationname[256];
986         int vertstrings_count = 0;
987         int geomstrings_count = 0;
988         int fragstrings_count = 0;
989         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
990         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
991         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
992
993         if (p->compiled)
994                 return;
995         p->compiled = true;
996         p->program = 0;
997
998         permutationname[0] = 0;
999         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1000         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1001         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1002
1003         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1004
1005         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1006         if(vid.support.gl20shaders130)
1007         {
1008                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1009                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1010                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1011                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1012                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1013                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1014         }
1015
1016         // the first pretext is which type of shader to compile as
1017         // (later these will all be bound together as a program object)
1018         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1019         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1020         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1021
1022         // the second pretext is the mode (for example a light source)
1023         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1024         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1025         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1026         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1027
1028         // now add all the permutation pretexts
1029         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1030         {
1031                 if (permutation & (1<<i))
1032                 {
1033                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1034                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1035                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1036                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1037                 }
1038                 else
1039                 {
1040                         // keep line numbers correct
1041                         vertstrings_list[vertstrings_count++] = "\n";
1042                         geomstrings_list[geomstrings_count++] = "\n";
1043                         fragstrings_list[fragstrings_count++] = "\n";
1044                 }
1045         }
1046
1047         // add static parms
1048         R_CompileShader_AddStaticParms(mode, permutation);
1049         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1050         vertstrings_count += shaderstaticparms_count;
1051         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1052         geomstrings_count += shaderstaticparms_count;
1053         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054         fragstrings_count += shaderstaticparms_count;
1055
1056         // now append the shader text itself
1057         vertstrings_list[vertstrings_count++] = vertexstring;
1058         geomstrings_list[geomstrings_count++] = geometrystring;
1059         fragstrings_list[fragstrings_count++] = fragmentstring;
1060
1061         // if any sources were NULL, clear the respective list
1062         if (!vertexstring)
1063                 vertstrings_count = 0;
1064         if (!geometrystring)
1065                 geomstrings_count = 0;
1066         if (!fragmentstring)
1067                 fragstrings_count = 0;
1068
1069         // compile the shader program
1070         if (vertstrings_count + geomstrings_count + fragstrings_count)
1071                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1072         if (p->program)
1073         {
1074                 CHECKGLERROR
1075                 qglUseProgram(p->program);CHECKGLERROR
1076                 // look up all the uniform variable names we care about, so we don't
1077                 // have to look them up every time we set them
1078
1079                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1080                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1081                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1082                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1083                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1084                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1085                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1086                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1087                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1088                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1089                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1090                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1091                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1092                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1093                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1094                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1095                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1096                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1097                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1098                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1099                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1100                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1101                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1102                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1103                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1104                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1105                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1106                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1107                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1108                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1109                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1110                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1111                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1112                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1113                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1114                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1115                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1116                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1117                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1118                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1119                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1120                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1121                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1122                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1123                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1124                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1125                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1126                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1127                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1128                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1129                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1130                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1131                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1132                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1133                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1134                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1135                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1136                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1137                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1138                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1139                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1140                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1141                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1142                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1143                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1144                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1145                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1146                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1147                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1148                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1149                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1150                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1151                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1152                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1153                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1154                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1155                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1156                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1157                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1158                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1159                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1160                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1161                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1162                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1163                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1164                 // initialize the samplers to refer to the texture units we use
1165                 p->tex_Texture_First = -1;
1166                 p->tex_Texture_Second = -1;
1167                 p->tex_Texture_GammaRamps = -1;
1168                 p->tex_Texture_Normal = -1;
1169                 p->tex_Texture_Color = -1;
1170                 p->tex_Texture_Gloss = -1;
1171                 p->tex_Texture_Glow = -1;
1172                 p->tex_Texture_SecondaryNormal = -1;
1173                 p->tex_Texture_SecondaryColor = -1;
1174                 p->tex_Texture_SecondaryGloss = -1;
1175                 p->tex_Texture_SecondaryGlow = -1;
1176                 p->tex_Texture_Pants = -1;
1177                 p->tex_Texture_Shirt = -1;
1178                 p->tex_Texture_FogHeightTexture = -1;
1179                 p->tex_Texture_FogMask = -1;
1180                 p->tex_Texture_Lightmap = -1;
1181                 p->tex_Texture_Deluxemap = -1;
1182                 p->tex_Texture_Attenuation = -1;
1183                 p->tex_Texture_Cube = -1;
1184                 p->tex_Texture_Refraction = -1;
1185                 p->tex_Texture_Reflection = -1;
1186                 p->tex_Texture_ShadowMap2D = -1;
1187                 p->tex_Texture_CubeProjection = -1;
1188                 p->tex_Texture_ScreenDepth = -1;
1189                 p->tex_Texture_ScreenNormalMap = -1;
1190                 p->tex_Texture_ScreenDiffuse = -1;
1191                 p->tex_Texture_ScreenSpecular = -1;
1192                 p->tex_Texture_ReflectMask = -1;
1193                 p->tex_Texture_ReflectCube = -1;
1194                 p->tex_Texture_BounceGrid = -1;
1195                 sampler = 0;
1196                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1197                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1198                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1199                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1200                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1201                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1202                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1203                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1204                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1205                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1206                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1207                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1208                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1209                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1210                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1211                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1212                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1213                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1214                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1215                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1216                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1217                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1218                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1219                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1220                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1221                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1222                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1223                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1224                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1225                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1226                 CHECKGLERROR
1227                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1228         }
1229         else
1230                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1231
1232         // free the strings
1233         if (vertexstring)
1234                 Mem_Free(vertexstring);
1235         if (geometrystring)
1236                 Mem_Free(geometrystring);
1237         if (fragmentstring)
1238                 Mem_Free(fragmentstring);
1239 }
1240
1241 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1242 {
1243         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1244         if (r_glsl_permutation != perm)
1245         {
1246                 r_glsl_permutation = perm;
1247                 if (!r_glsl_permutation->program)
1248                 {
1249                         if (!r_glsl_permutation->compiled)
1250                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1251                         if (!r_glsl_permutation->program)
1252                         {
1253                                 // remove features until we find a valid permutation
1254                                 int i;
1255                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1256                                 {
1257                                         // reduce i more quickly whenever it would not remove any bits
1258                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1259                                         if (!(permutation & j))
1260                                                 continue;
1261                                         permutation -= j;
1262                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1263                                         if (!r_glsl_permutation->compiled)
1264                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1265                                         if (r_glsl_permutation->program)
1266                                                 break;
1267                                 }
1268                                 if (i >= SHADERPERMUTATION_COUNT)
1269                                 {
1270                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1271                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1272                                         qglUseProgram(0);CHECKGLERROR
1273                                         return; // no bit left to clear, entire mode is broken
1274                                 }
1275                         }
1276                 }
1277                 CHECKGLERROR
1278                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1279         }
1280         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1281         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1282         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1283 }
1284
1285 #ifdef SUPPORTD3D
1286
1287 #ifdef SUPPORTD3D
1288 #include <d3d9.h>
1289 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1290 extern D3DCAPS9 vid_d3d9caps;
1291 #endif
1292
1293 struct r_hlsl_permutation_s;
1294 typedef struct r_hlsl_permutation_s
1295 {
1296         /// hash lookup data
1297         struct r_hlsl_permutation_s *hashnext;
1298         unsigned int mode;
1299         unsigned int permutation;
1300
1301         /// indicates if we have tried compiling this permutation already
1302         qboolean compiled;
1303         /// NULL if compilation failed
1304         IDirect3DVertexShader9 *vertexshader;
1305         IDirect3DPixelShader9 *pixelshader;
1306 }
1307 r_hlsl_permutation_t;
1308
1309 typedef enum D3DVSREGISTER_e
1310 {
1311         D3DVSREGISTER_TexMatrix = 0, // float4x4
1312         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1313         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1314         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1315         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1316         D3DVSREGISTER_ModelToLight = 20, // float4x4
1317         D3DVSREGISTER_EyePosition = 24,
1318         D3DVSREGISTER_FogPlane = 25,
1319         D3DVSREGISTER_LightDir = 26,
1320         D3DVSREGISTER_LightPosition = 27,
1321 }
1322 D3DVSREGISTER_t;
1323
1324 typedef enum D3DPSREGISTER_e
1325 {
1326         D3DPSREGISTER_Alpha = 0,
1327         D3DPSREGISTER_BloomBlur_Parameters = 1,
1328         D3DPSREGISTER_ClientTime = 2,
1329         D3DPSREGISTER_Color_Ambient = 3,
1330         D3DPSREGISTER_Color_Diffuse = 4,
1331         D3DPSREGISTER_Color_Specular = 5,
1332         D3DPSREGISTER_Color_Glow = 6,
1333         D3DPSREGISTER_Color_Pants = 7,
1334         D3DPSREGISTER_Color_Shirt = 8,
1335         D3DPSREGISTER_DeferredColor_Ambient = 9,
1336         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1337         D3DPSREGISTER_DeferredColor_Specular = 11,
1338         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1339         D3DPSREGISTER_DeferredMod_Specular = 13,
1340         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1341         D3DPSREGISTER_EyePosition = 15, // unused
1342         D3DPSREGISTER_FogColor = 16,
1343         D3DPSREGISTER_FogHeightFade = 17,
1344         D3DPSREGISTER_FogPlane = 18,
1345         D3DPSREGISTER_FogPlaneViewDist = 19,
1346         D3DPSREGISTER_FogRangeRecip = 20,
1347         D3DPSREGISTER_LightColor = 21,
1348         D3DPSREGISTER_LightDir = 22, // unused
1349         D3DPSREGISTER_LightPosition = 23,
1350         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1351         D3DPSREGISTER_PixelSize = 25,
1352         D3DPSREGISTER_ReflectColor = 26,
1353         D3DPSREGISTER_ReflectFactor = 27,
1354         D3DPSREGISTER_ReflectOffset = 28,
1355         D3DPSREGISTER_RefractColor = 29,
1356         D3DPSREGISTER_Saturation = 30,
1357         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1358         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1359         D3DPSREGISTER_ScreenToDepth = 33,
1360         D3DPSREGISTER_ShadowMap_Parameters = 34,
1361         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1362         D3DPSREGISTER_SpecularPower = 36,
1363         D3DPSREGISTER_UserVec1 = 37,
1364         D3DPSREGISTER_UserVec2 = 38,
1365         D3DPSREGISTER_UserVec3 = 39,
1366         D3DPSREGISTER_UserVec4 = 40,
1367         D3DPSREGISTER_ViewTintColor = 41,
1368         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1369         D3DPSREGISTER_BloomColorSubtract = 43,
1370         D3DPSREGISTER_ViewToLight = 44, // float4x4
1371         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1372         D3DPSREGISTER_NormalmapScrollBlend = 52,
1373         // next at 53
1374 }
1375 D3DPSREGISTER_t;
1376
1377 /// information about each possible shader permutation
1378 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1379 /// currently selected permutation
1380 r_hlsl_permutation_t *r_hlsl_permutation;
1381 /// storage for permutations linked in the hash table
1382 memexpandablearray_t r_hlsl_permutationarray;
1383
1384 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1385 {
1386         //unsigned int hashdepth = 0;
1387         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1388         r_hlsl_permutation_t *p;
1389         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1390         {
1391                 if (p->mode == mode && p->permutation == permutation)
1392                 {
1393                         //if (hashdepth > 10)
1394                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1395                         return p;
1396                 }
1397                 //hashdepth++;
1398         }
1399         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1400         p->mode = mode;
1401         p->permutation = permutation;
1402         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1403         r_hlsl_permutationhash[mode][hashindex] = p;
1404         //if (hashdepth > 10)
1405         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1406         return p;
1407 }
1408
1409 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1410 {
1411         char *shaderstring;
1412         if (!filename || !filename[0])
1413                 return NULL;
1414         if (!strcmp(filename, "hlsl/default.hlsl"))
1415         {
1416                 if (!hlslshaderstring)
1417                 {
1418                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1419                         if (hlslshaderstring)
1420                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1421                         else
1422                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1423                 }
1424                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1425                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1426                 return shaderstring;
1427         }
1428         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429         if (shaderstring)
1430         {
1431                 if (printfromdisknotice)
1432                         Con_DPrintf("from disk %s... ", filename);
1433                 return shaderstring;
1434         }
1435         return shaderstring;
1436 }
1437
1438 #include <d3dx9.h>
1439 //#include <d3dx9shader.h>
1440 //#include <d3dx9mesh.h>
1441
1442 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1443 {
1444         DWORD *vsbin = NULL;
1445         DWORD *psbin = NULL;
1446         fs_offset_t vsbinsize;
1447         fs_offset_t psbinsize;
1448 //      IDirect3DVertexShader9 *vs = NULL;
1449 //      IDirect3DPixelShader9 *ps = NULL;
1450         ID3DXBuffer *vslog = NULL;
1451         ID3DXBuffer *vsbuffer = NULL;
1452         ID3DXConstantTable *vsconstanttable = NULL;
1453         ID3DXBuffer *pslog = NULL;
1454         ID3DXBuffer *psbuffer = NULL;
1455         ID3DXConstantTable *psconstanttable = NULL;
1456         int vsresult = 0;
1457         int psresult = 0;
1458         char temp[MAX_INPUTLINE];
1459         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1460         qboolean debugshader = gl_paranoid.integer != 0;
1461         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1462         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1463         if (!debugshader)
1464         {
1465                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1466                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1467         }
1468         if ((!vsbin && vertstring) || (!psbin && fragstring))
1469         {
1470                 const char* dllnames_d3dx9 [] =
1471                 {
1472                         "d3dx9_43.dll",
1473                         "d3dx9_42.dll",
1474                         "d3dx9_41.dll",
1475                         "d3dx9_40.dll",
1476                         "d3dx9_39.dll",
1477                         "d3dx9_38.dll",
1478                         "d3dx9_37.dll",
1479                         "d3dx9_36.dll",
1480                         "d3dx9_35.dll",
1481                         "d3dx9_34.dll",
1482                         "d3dx9_33.dll",
1483                         "d3dx9_32.dll",
1484                         "d3dx9_31.dll",
1485                         "d3dx9_30.dll",
1486                         "d3dx9_29.dll",
1487                         "d3dx9_28.dll",
1488                         "d3dx9_27.dll",
1489                         "d3dx9_26.dll",
1490                         "d3dx9_25.dll",
1491                         "d3dx9_24.dll",
1492                         NULL
1493                 };
1494                 dllhandle_t d3dx9_dll = NULL;
1495                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1496                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1497                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1498                 dllfunction_t d3dx9_dllfuncs[] =
1499                 {
1500                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1501                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1502                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1503                         {NULL, NULL}
1504                 };
1505                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1506                 {
1507                         DWORD shaderflags = 0;
1508                         if (debugshader)
1509                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1510                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1511                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1512                         if (vertstring && vertstring[0])
1513                         {
1514                                 if (debugshader)
1515                                 {
1516 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1517 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1518                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1519                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1520                                 }
1521                                 else
1522                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1523                                 if (vsbuffer)
1524                                 {
1525                                         vsbinsize = vsbuffer->GetBufferSize();
1526                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1527                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1528                                         vsbuffer->Release();
1529                                 }
1530                                 if (vslog)
1531                                 {
1532                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1533                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1534                                         vslog->Release();
1535                                 }
1536                         }
1537                         if (fragstring && fragstring[0])
1538                         {
1539                                 if (debugshader)
1540                                 {
1541 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1542 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1543                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1544                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1545                                 }
1546                                 else
1547                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1548                                 if (psbuffer)
1549                                 {
1550                                         psbinsize = psbuffer->GetBufferSize();
1551                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1552                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1553                                         psbuffer->Release();
1554                                 }
1555                                 if (pslog)
1556                                 {
1557                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1558                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1559                                         pslog->Release();
1560                                 }
1561                         }
1562                         Sys_UnloadLibrary(&d3dx9_dll);
1563                 }
1564                 else
1565                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1566         }
1567         if (vsbin && psbin)
1568         {
1569                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1570                 if (FAILED(vsresult))
1571                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1572                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1573                 if (FAILED(psresult))
1574                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1575         }
1576         // free the shader data
1577         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1578         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1579 }
1580
1581 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1582 {
1583         int i;
1584         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1585         int vertstring_length = 0;
1586         int geomstring_length = 0;
1587         int fragstring_length = 0;
1588         char *t;
1589         char *vertexstring, *geometrystring, *fragmentstring;
1590         char *vertstring, *geomstring, *fragstring;
1591         char permutationname[256];
1592         char cachename[256];
1593         int vertstrings_count = 0;
1594         int geomstrings_count = 0;
1595         int fragstrings_count = 0;
1596         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1597         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1598         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1599
1600         if (p->compiled)
1601                 return;
1602         p->compiled = true;
1603         p->vertexshader = NULL;
1604         p->pixelshader = NULL;
1605
1606         permutationname[0] = 0;
1607         cachename[0] = 0;
1608         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1609         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1610         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1611
1612         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1613         strlcat(cachename, "hlsl/", sizeof(cachename));
1614
1615         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1616         vertstrings_count = 0;
1617         geomstrings_count = 0;
1618         fragstrings_count = 0;
1619         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1620         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1621         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1622
1623         // the first pretext is which type of shader to compile as
1624         // (later these will all be bound together as a program object)
1625         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1626         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1627         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1628
1629         // the second pretext is the mode (for example a light source)
1630         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1631         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1632         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1633         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1634         strlcat(cachename, modeinfo->name, sizeof(cachename));
1635
1636         // now add all the permutation pretexts
1637         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1638         {
1639                 if (permutation & (1<<i))
1640                 {
1641                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1642                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1643                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1644                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1645                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1646                 }
1647                 else
1648                 {
1649                         // keep line numbers correct
1650                         vertstrings_list[vertstrings_count++] = "\n";
1651                         geomstrings_list[geomstrings_count++] = "\n";
1652                         fragstrings_list[fragstrings_count++] = "\n";
1653                 }
1654         }
1655
1656         // add static parms
1657         R_CompileShader_AddStaticParms(mode, permutation);
1658         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1659         vertstrings_count += shaderstaticparms_count;
1660         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1661         geomstrings_count += shaderstaticparms_count;
1662         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663         fragstrings_count += shaderstaticparms_count;
1664
1665         // replace spaces in the cachename with _ characters
1666         for (i = 0;cachename[i];i++)
1667                 if (cachename[i] == ' ')
1668                         cachename[i] = '_';
1669
1670         // now append the shader text itself
1671         vertstrings_list[vertstrings_count++] = vertexstring;
1672         geomstrings_list[geomstrings_count++] = geometrystring;
1673         fragstrings_list[fragstrings_count++] = fragmentstring;
1674
1675         // if any sources were NULL, clear the respective list
1676         if (!vertexstring)
1677                 vertstrings_count = 0;
1678         if (!geometrystring)
1679                 geomstrings_count = 0;
1680         if (!fragmentstring)
1681                 fragstrings_count = 0;
1682
1683         vertstring_length = 0;
1684         for (i = 0;i < vertstrings_count;i++)
1685                 vertstring_length += strlen(vertstrings_list[i]);
1686         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1687         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1688                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1689
1690         geomstring_length = 0;
1691         for (i = 0;i < geomstrings_count;i++)
1692                 geomstring_length += strlen(geomstrings_list[i]);
1693         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1694         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1695                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1696
1697         fragstring_length = 0;
1698         for (i = 0;i < fragstrings_count;i++)
1699                 fragstring_length += strlen(fragstrings_list[i]);
1700         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1701         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1702                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1703
1704         // try to load the cached shader, or generate one
1705         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1706
1707         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1708                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1709         else
1710                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1711
1712         // free the strings
1713         if (vertstring)
1714                 Mem_Free(vertstring);
1715         if (geomstring)
1716                 Mem_Free(geomstring);
1717         if (fragstring)
1718                 Mem_Free(fragstring);
1719         if (vertexstring)
1720                 Mem_Free(vertexstring);
1721         if (geometrystring)
1722                 Mem_Free(geometrystring);
1723         if (fragmentstring)
1724                 Mem_Free(fragmentstring);
1725 }
1726
1727 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1728 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1729 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1730 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1731 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1732 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1733
1734 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1735 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1736 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1737 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1738 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1739 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1740
1741 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1742 {
1743         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1744         if (r_hlsl_permutation != perm)
1745         {
1746                 r_hlsl_permutation = perm;
1747                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1748                 {
1749                         if (!r_hlsl_permutation->compiled)
1750                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1751                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1752                         {
1753                                 // remove features until we find a valid permutation
1754                                 int i;
1755                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1756                                 {
1757                                         // reduce i more quickly whenever it would not remove any bits
1758                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1759                                         if (!(permutation & j))
1760                                                 continue;
1761                                         permutation -= j;
1762                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1763                                         if (!r_hlsl_permutation->compiled)
1764                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1765                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1766                                                 break;
1767                                 }
1768                                 if (i >= SHADERPERMUTATION_COUNT)
1769                                 {
1770                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1771                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1772                                         return; // no bit left to clear, entire mode is broken
1773                                 }
1774                         }
1775                 }
1776                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1777                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1778         }
1779         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1780         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1781         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1782 }
1783 #endif
1784
1785 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1786 {
1787         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1788         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1789         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1790         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1791 }
1792
1793 void R_GLSL_Restart_f(void)
1794 {
1795         unsigned int i, limit;
1796         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1797                 Mem_Free(glslshaderstring);
1798         glslshaderstring = NULL;
1799         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1800                 Mem_Free(hlslshaderstring);
1801         hlslshaderstring = NULL;
1802         switch(vid.renderpath)
1803         {
1804         case RENDERPATH_D3D9:
1805 #ifdef SUPPORTD3D
1806                 {
1807                         r_hlsl_permutation_t *p;
1808                         r_hlsl_permutation = NULL;
1809                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1810                         for (i = 0;i < limit;i++)
1811                         {
1812                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1813                                 {
1814                                         if (p->vertexshader)
1815                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1816                                         if (p->pixelshader)
1817                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1818                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1819                                 }
1820                         }
1821                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1822                 }
1823 #endif
1824                 break;
1825         case RENDERPATH_D3D10:
1826                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1827                 break;
1828         case RENDERPATH_D3D11:
1829                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1830                 break;
1831         case RENDERPATH_GL20:
1832         case RENDERPATH_GLES2:
1833                 {
1834                         r_glsl_permutation_t *p;
1835                         r_glsl_permutation = NULL;
1836                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1837                         for (i = 0;i < limit;i++)
1838                         {
1839                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1840                                 {
1841                                         GL_Backend_FreeProgram(p->program);
1842                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1843                                 }
1844                         }
1845                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1846                 }
1847                 break;
1848         case RENDERPATH_GL11:
1849         case RENDERPATH_GL13:
1850         case RENDERPATH_GLES1:
1851                 break;
1852         case RENDERPATH_SOFT:
1853                 break;
1854         }
1855 }
1856
1857 void R_GLSL_DumpShader_f(void)
1858 {
1859         int i;
1860         qfile_t *file;
1861
1862         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1863         if (file)
1864         {
1865                 FS_Print(file, "/* The engine may define the following macros:\n");
1866                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1867                 for (i = 0;i < SHADERMODE_COUNT;i++)
1868                         FS_Print(file, glslshadermodeinfo[i].pretext);
1869                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1870                         FS_Print(file, shaderpermutationinfo[i].pretext);
1871                 FS_Print(file, "*/\n");
1872                 FS_Print(file, builtinshaderstring);
1873                 FS_Close(file);
1874                 Con_Printf("glsl/default.glsl written\n");
1875         }
1876         else
1877                 Con_Printf("failed to write to glsl/default.glsl\n");
1878
1879         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1880         if (file)
1881         {
1882                 FS_Print(file, "/* The engine may define the following macros:\n");
1883                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1884                 for (i = 0;i < SHADERMODE_COUNT;i++)
1885                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1886                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1887                         FS_Print(file, shaderpermutationinfo[i].pretext);
1888                 FS_Print(file, "*/\n");
1889                 FS_Print(file, builtinhlslshaderstring);
1890                 FS_Close(file);
1891                 Con_Printf("hlsl/default.hlsl written\n");
1892         }
1893         else
1894                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1895 }
1896
1897 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean notrippy)
1898 {
1899         unsigned int permutation = 0;
1900         if (r_trippy.integer && !notrippy)
1901                 permutation |= SHADERPERMUTATION_TRIPPY;
1902         permutation |= SHADERPERMUTATION_VIEWTINT;
1903         if (first)
1904                 permutation |= SHADERPERMUTATION_DIFFUSE;
1905         if (second)
1906                 permutation |= SHADERPERMUTATION_SPECULAR;
1907         if (texturemode == GL_MODULATE)
1908                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1909         else if (texturemode == GL_ADD)
1910                 permutation |= SHADERPERMUTATION_GLOW;
1911         else if (texturemode == GL_DECAL)
1912                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1913         if (!second)
1914                 texturemode = GL_MODULATE;
1915         if (vid.allowalphatocoverage)
1916                 GL_AlphaToCoverage(false);
1917         switch (vid.renderpath)
1918         {
1919         case RENDERPATH_D3D9:
1920 #ifdef SUPPORTD3D
1921                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1922                 R_Mesh_TexBind(GL20TU_FIRST , first );
1923                 R_Mesh_TexBind(GL20TU_SECOND, second);
1924 #endif
1925                 break;
1926         case RENDERPATH_D3D10:
1927                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1928                 break;
1929         case RENDERPATH_D3D11:
1930                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1931                 break;
1932         case RENDERPATH_GL20:
1933         case RENDERPATH_GLES2:
1934                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1935                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1936                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1937                 break;
1938         case RENDERPATH_GL13:
1939         case RENDERPATH_GLES1:
1940                 R_Mesh_TexBind(0, first );
1941                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1942                 R_Mesh_TexBind(1, second);
1943                 if (second)
1944                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1945                 break;
1946         case RENDERPATH_GL11:
1947                 R_Mesh_TexBind(0, first );
1948                 break;
1949         case RENDERPATH_SOFT:
1950                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1951                 R_Mesh_TexBind(GL20TU_FIRST , first );
1952                 R_Mesh_TexBind(GL20TU_SECOND, second);
1953                 break;
1954         }
1955 }
1956
1957 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1958 {
1959         unsigned int permutation = 0;
1960         if (r_trippy.integer && !notrippy)
1961                 permutation |= SHADERPERMUTATION_TRIPPY;
1962         if (vid.allowalphatocoverage)
1963                 GL_AlphaToCoverage(false);
1964         switch (vid.renderpath)
1965         {
1966         case RENDERPATH_D3D9:
1967 #ifdef SUPPORTD3D
1968                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1969 #endif
1970                 break;
1971         case RENDERPATH_D3D10:
1972                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1973                 break;
1974         case RENDERPATH_D3D11:
1975                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1976                 break;
1977         case RENDERPATH_GL20:
1978         case RENDERPATH_GLES2:
1979                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1980                 break;
1981         case RENDERPATH_GL13:
1982         case RENDERPATH_GLES1:
1983                 R_Mesh_TexBind(0, 0);
1984                 R_Mesh_TexBind(1, 0);
1985                 break;
1986         case RENDERPATH_GL11:
1987                 R_Mesh_TexBind(0, 0);
1988                 break;
1989         case RENDERPATH_SOFT:
1990                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1991                 break;
1992         }
1993 }
1994
1995 void R_SetupShader_ShowDepth(qboolean notrippy)
1996 {
1997         int permutation = 0;
1998         if (r_trippy.integer && !notrippy)
1999                 permutation |= SHADERPERMUTATION_TRIPPY;
2000         if (r_trippy.integer)
2001                 permutation |= SHADERPERMUTATION_TRIPPY;
2002         if (vid.allowalphatocoverage)
2003                 GL_AlphaToCoverage(false);
2004         switch (vid.renderpath)
2005         {
2006         case RENDERPATH_D3D9:
2007 #ifdef SUPPORTHLSL
2008                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2009 #endif
2010                 break;
2011         case RENDERPATH_D3D10:
2012                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2013                 break;
2014         case RENDERPATH_D3D11:
2015                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2016                 break;
2017         case RENDERPATH_GL20:
2018         case RENDERPATH_GLES2:
2019                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2020                 break;
2021         case RENDERPATH_GL13:
2022         case RENDERPATH_GLES1:
2023                 break;
2024         case RENDERPATH_GL11:
2025                 break;
2026         case RENDERPATH_SOFT:
2027                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2028                 break;
2029         }
2030 }
2031
2032 extern qboolean r_shadow_usingdeferredprepass;
2033 extern cvar_t r_shadow_deferred_8bitrange;
2034 extern rtexture_t *r_shadow_attenuationgradienttexture;
2035 extern rtexture_t *r_shadow_attenuation2dtexture;
2036 extern rtexture_t *r_shadow_attenuation3dtexture;
2037 extern qboolean r_shadow_usingshadowmap2d;
2038 extern qboolean r_shadow_usingshadowmaportho;
2039 extern float r_shadow_shadowmap_texturescale[2];
2040 extern float r_shadow_shadowmap_parameters[4];
2041 extern qboolean r_shadow_shadowmapvsdct;
2042 extern qboolean r_shadow_shadowmapsampler;
2043 extern int r_shadow_shadowmappcf;
2044 extern rtexture_t *r_shadow_shadowmap2dtexture;
2045 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2046 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2047 extern matrix4x4_t r_shadow_shadowmapmatrix;
2048 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2049 extern int r_shadow_prepass_width;
2050 extern int r_shadow_prepass_height;
2051 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2052 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2053 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2054 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2055 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2056
2057 #define BLENDFUNC_ALLOWS_COLORMOD      1
2058 #define BLENDFUNC_ALLOWS_FOG           2
2059 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2060 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2061 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2062 static int R_BlendFuncFlags(int src, int dst)
2063 {
2064         int r = 0;
2065
2066         // a blendfunc allows colormod if:
2067         // a) it can never keep the destination pixel invariant, or
2068         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2069         // this is to prevent unintended side effects from colormod
2070
2071         // a blendfunc allows fog if:
2072         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2073         // this is to prevent unintended side effects from fog
2074
2075         // these checks are the output of fogeval.pl
2076
2077         r |= BLENDFUNC_ALLOWS_COLORMOD;
2078         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2079         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2080         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2081         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2082         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2084         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2085         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2086         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2087         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2088         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2089         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2090         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2091         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2094         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2095         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2096         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2098         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099
2100         return r;
2101 }
2102
2103 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2104 {
2105         // select a permutation of the lighting shader appropriate to this
2106         // combination of texture, entity, light source, and fogging, only use the
2107         // minimum features necessary to avoid wasting rendering time in the
2108         // fragment shader on features that are not being used
2109         unsigned int permutation = 0;
2110         unsigned int mode = 0;
2111         int blendfuncflags;
2112         static float dummy_colormod[3] = {1, 1, 1};
2113         float *colormod = rsurface.colormod;
2114         float m16f[16];
2115         matrix4x4_t tempmatrix;
2116         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2117         if (r_trippy.integer && !notrippy)
2118                 permutation |= SHADERPERMUTATION_TRIPPY;
2119         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2120                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2121         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2122                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2123         if (rsurfacepass == RSURFPASS_BACKGROUND)
2124         {
2125                 // distorted background
2126                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2127                 {
2128                         mode = SHADERMODE_WATER;
2129                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2130                         {
2131                                 // this is the right thing to do for wateralpha
2132                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2133                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2134                         }
2135                         else
2136                         {
2137                                 // this is the right thing to do for entity alpha
2138                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2139                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2140                         }
2141                 }
2142                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2143                 {
2144                         mode = SHADERMODE_REFRACTION;
2145                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2146                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2147                 }
2148                 else
2149                 {
2150                         mode = SHADERMODE_GENERIC;
2151                         permutation |= SHADERPERMUTATION_DIFFUSE;
2152                         GL_BlendFunc(GL_ONE, GL_ZERO);
2153                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2154                 }
2155                 if (vid.allowalphatocoverage)
2156                         GL_AlphaToCoverage(false);
2157         }
2158         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2159         {
2160                 if (r_glsl_offsetmapping.integer)
2161                 {
2162                         switch(rsurface.texture->offsetmapping)
2163                         {
2164                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2165                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2166                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2167                         case OFFSETMAPPING_OFF: break;
2168                         }
2169                 }
2170                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2171                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2172                 // normalmap (deferred prepass), may use alpha test on diffuse
2173                 mode = SHADERMODE_DEFERREDGEOMETRY;
2174                 GL_BlendFunc(GL_ONE, GL_ZERO);
2175                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2176                 if (vid.allowalphatocoverage)
2177                         GL_AlphaToCoverage(false);
2178         }
2179         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2180         {
2181                 if (r_glsl_offsetmapping.integer)
2182                 {
2183                         switch(rsurface.texture->offsetmapping)
2184                         {
2185                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2186                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2187                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2188                         case OFFSETMAPPING_OFF: break;
2189                         }
2190                 }
2191                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2192                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2193                 // light source
2194                 mode = SHADERMODE_LIGHTSOURCE;
2195                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2196                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2197                 if (diffusescale > 0)
2198                         permutation |= SHADERPERMUTATION_DIFFUSE;
2199                 if (specularscale > 0)
2200                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2201                 if (r_refdef.fogenabled)
2202                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2203                 if (rsurface.texture->colormapping)
2204                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2205                 if (r_shadow_usingshadowmap2d)
2206                 {
2207                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2208                         if(r_shadow_shadowmapvsdct)
2209                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2210
2211                         if (r_shadow_shadowmapsampler)
2212                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2213                         if (r_shadow_shadowmappcf > 1)
2214                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2215                         else if (r_shadow_shadowmappcf)
2216                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2217                 }
2218                 if (rsurface.texture->reflectmasktexture)
2219                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2220                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2221                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2222                 if (vid.allowalphatocoverage)
2223                         GL_AlphaToCoverage(false);
2224         }
2225         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2226         {
2227                 if (r_glsl_offsetmapping.integer)
2228                 {
2229                         switch(rsurface.texture->offsetmapping)
2230                         {
2231                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2232                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2233                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2234                         case OFFSETMAPPING_OFF: break;
2235                         }
2236                 }
2237                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2238                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2239                 // unshaded geometry (fullbright or ambient model lighting)
2240                 mode = SHADERMODE_FLATCOLOR;
2241                 ambientscale = diffusescale = specularscale = 0;
2242                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2243                         permutation |= SHADERPERMUTATION_GLOW;
2244                 if (r_refdef.fogenabled)
2245                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2246                 if (rsurface.texture->colormapping)
2247                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2248                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2249                 {
2250                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2251                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2252
2253                         if (r_shadow_shadowmapsampler)
2254                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2255                         if (r_shadow_shadowmappcf > 1)
2256                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2257                         else if (r_shadow_shadowmappcf)
2258                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2259                 }
2260                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2261                         permutation |= SHADERPERMUTATION_REFLECTION;
2262                 if (rsurface.texture->reflectmasktexture)
2263                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2264                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2265                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2266                 // when using alphatocoverage, we don't need alphakill
2267                 if (vid.allowalphatocoverage)
2268                 {
2269                         if (r_transparent_alphatocoverage.integer)
2270                         {
2271                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2272                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2273                         }
2274                         else
2275                                 GL_AlphaToCoverage(false);
2276                 }
2277         }
2278         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2279         {
2280                 if (r_glsl_offsetmapping.integer)
2281                 {
2282                         switch(rsurface.texture->offsetmapping)
2283                         {
2284                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2285                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2286                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2287                         case OFFSETMAPPING_OFF: break;
2288                         }
2289                 }
2290                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2291                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2292                 // directional model lighting
2293                 mode = SHADERMODE_LIGHTDIRECTION;
2294                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2295                         permutation |= SHADERPERMUTATION_GLOW;
2296                 permutation |= SHADERPERMUTATION_DIFFUSE;
2297                 if (specularscale > 0)
2298                         permutation |= SHADERPERMUTATION_SPECULAR;
2299                 if (r_refdef.fogenabled)
2300                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2301                 if (rsurface.texture->colormapping)
2302                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2303                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2304                 {
2305                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2306                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2307
2308                         if (r_shadow_shadowmapsampler)
2309                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2310                         if (r_shadow_shadowmappcf > 1)
2311                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2312                         else if (r_shadow_shadowmappcf)
2313                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2314                 }
2315                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2316                         permutation |= SHADERPERMUTATION_REFLECTION;
2317                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2318                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2319                 if (rsurface.texture->reflectmasktexture)
2320                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2321                 if (r_shadow_bouncegridtexture)
2322                 {
2323                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2324                         if (r_shadow_bouncegriddirectional)
2325                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2326                 }
2327                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2328                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2329                 // when using alphatocoverage, we don't need alphakill
2330                 if (vid.allowalphatocoverage)
2331                 {
2332                         if (r_transparent_alphatocoverage.integer)
2333                         {
2334                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2335                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2336                         }
2337                         else
2338                                 GL_AlphaToCoverage(false);
2339                 }
2340         }
2341         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2342         {
2343                 if (r_glsl_offsetmapping.integer)
2344                 {
2345                         switch(rsurface.texture->offsetmapping)
2346                         {
2347                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2348                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2349                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2350                         case OFFSETMAPPING_OFF: break;
2351                         }
2352                 }
2353                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2354                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2355                 // ambient model lighting
2356                 mode = SHADERMODE_LIGHTDIRECTION;
2357                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2358                         permutation |= SHADERPERMUTATION_GLOW;
2359                 if (r_refdef.fogenabled)
2360                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2361                 if (rsurface.texture->colormapping)
2362                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2363                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2364                 {
2365                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2366                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2367
2368                         if (r_shadow_shadowmapsampler)
2369                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2370                         if (r_shadow_shadowmappcf > 1)
2371                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2372                         else if (r_shadow_shadowmappcf)
2373                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2374                 }
2375                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2376                         permutation |= SHADERPERMUTATION_REFLECTION;
2377                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2378                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2379                 if (rsurface.texture->reflectmasktexture)
2380                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2381                 if (r_shadow_bouncegridtexture)
2382                 {
2383                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2384                         if (r_shadow_bouncegriddirectional)
2385                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2386                 }
2387                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2388                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2389                 // when using alphatocoverage, we don't need alphakill
2390                 if (vid.allowalphatocoverage)
2391                 {
2392                         if (r_transparent_alphatocoverage.integer)
2393                         {
2394                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2395                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2396                         }
2397                         else
2398                                 GL_AlphaToCoverage(false);
2399                 }
2400         }
2401         else
2402         {
2403                 if (r_glsl_offsetmapping.integer)
2404                 {
2405                         switch(rsurface.texture->offsetmapping)
2406                         {
2407                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2408                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2409                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2410                         case OFFSETMAPPING_OFF: break;
2411                         }
2412                 }
2413                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2414                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2415                 // lightmapped wall
2416                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2417                         permutation |= SHADERPERMUTATION_GLOW;
2418                 if (r_refdef.fogenabled)
2419                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2420                 if (rsurface.texture->colormapping)
2421                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2422                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2423                 {
2424                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2425                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2426
2427                         if (r_shadow_shadowmapsampler)
2428                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2429                         if (r_shadow_shadowmappcf > 1)
2430                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2431                         else if (r_shadow_shadowmappcf)
2432                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2433                 }
2434                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2435                         permutation |= SHADERPERMUTATION_REFLECTION;
2436                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2437                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2438                 if (rsurface.texture->reflectmasktexture)
2439                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2440                 if (FAKELIGHT_ENABLED)
2441                 {
2442                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2443                         mode = SHADERMODE_FAKELIGHT;
2444                         permutation |= SHADERPERMUTATION_DIFFUSE;
2445                         if (specularscale > 0)
2446                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2447                 }
2448                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2449                 {
2450                         // deluxemapping (light direction texture)
2451                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2452                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2453                         else
2454                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2455                         permutation |= SHADERPERMUTATION_DIFFUSE;
2456                         if (specularscale > 0)
2457                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2458                 }
2459                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2460                 {
2461                         // fake deluxemapping (uniform light direction in tangentspace)
2462                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2463                         permutation |= SHADERPERMUTATION_DIFFUSE;
2464                         if (specularscale > 0)
2465                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2466                 }
2467                 else if (rsurface.uselightmaptexture)
2468                 {
2469                         // ordinary lightmapping (q1bsp, q3bsp)
2470                         mode = SHADERMODE_LIGHTMAP;
2471                 }
2472                 else
2473                 {
2474                         // ordinary vertex coloring (q3bsp)
2475                         mode = SHADERMODE_VERTEXCOLOR;
2476                 }
2477                 if (r_shadow_bouncegridtexture)
2478                 {
2479                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2480                         if (r_shadow_bouncegriddirectional)
2481                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2482                 }
2483                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2484                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2485                 // when using alphatocoverage, we don't need alphakill
2486                 if (vid.allowalphatocoverage)
2487                 {
2488                         if (r_transparent_alphatocoverage.integer)
2489                         {
2490                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2491                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2492                         }
2493                         else
2494                                 GL_AlphaToCoverage(false);
2495                 }
2496         }
2497         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2498                 colormod = dummy_colormod;
2499         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2500                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2501         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2502                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2503         switch(vid.renderpath)
2504         {
2505         case RENDERPATH_D3D9:
2506 #ifdef SUPPORTD3D
2507                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2508                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2509                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2510                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2511                 if (mode == SHADERMODE_LIGHTSOURCE)
2512                 {
2513                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2514                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2515                 }
2516                 else
2517                 {
2518                         if (mode == SHADERMODE_LIGHTDIRECTION)
2519                         {
2520                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2521                         }
2522                 }
2523                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2524                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2525                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2526                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2527                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2528
2529                 if (mode == SHADERMODE_LIGHTSOURCE)
2530                 {
2531                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2532                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2533                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2536
2537                         // additive passes are only darkened by fog, not tinted
2538                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2539                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2540                 }
2541                 else
2542                 {
2543                         if (mode == SHADERMODE_FLATCOLOR)
2544                         {
2545                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2546                         }
2547                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2548                         {
2549                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2550                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2551                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2556                         }
2557                         else
2558                         {
2559                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2560                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2564                         }
2565                         // additive passes are only darkened by fog, not tinted
2566                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2567                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2568                         else
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2570                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2571                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2572                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2574                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2575                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2576                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2577                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2578                         if (mode == SHADERMODE_WATER)
2579                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2580                 }
2581                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2582                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2583                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2584                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2585                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2586                 if (rsurface.texture->pantstexture)
2587                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2588                 else
2589                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2590                 if (rsurface.texture->shirttexture)
2591                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2592                 else
2593                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2594                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2595                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2596                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2597                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2598                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2599                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2600                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2601                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2602                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2603                         );
2604                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2605                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2606
2607                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2608                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2609                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2610                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2611                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2612                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2613                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2614                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2615                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2616                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2617                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2618                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2619                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2620                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2621                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2622                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2623                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2624                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2625                 {
2626                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2627                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2628                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2629                 }
2630                 else
2631                 {
2632                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2633                 }
2634 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2635 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2636                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2637                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2638                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2639                 {
2640                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2641                         if (rsurface.rtlight)
2642                         {
2643                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2644                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2645                         }
2646                 }
2647 #endif
2648                 break;
2649         case RENDERPATH_D3D10:
2650                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2651                 break;
2652         case RENDERPATH_D3D11:
2653                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2654                 break;
2655         case RENDERPATH_GL20:
2656         case RENDERPATH_GLES2:
2657                 if (!vid.useinterleavedarrays)
2658                 {
2659                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2660                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2661                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2662                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2663                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2664                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2665                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2666                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2667                 }
2668                 else
2669                 {
2670                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2671                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2672                 }
2673                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2674                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2675                 if (mode == SHADERMODE_LIGHTSOURCE)
2676                 {
2677                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2678                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2679                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2680                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2681                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2682                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2683         
2684                         // additive passes are only darkened by fog, not tinted
2685                         if (r_glsl_permutation->loc_FogColor >= 0)
2686                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2687                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2688                 }
2689                 else
2690                 {
2691                         if (mode == SHADERMODE_FLATCOLOR)
2692                         {
2693                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2694                         }
2695                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2696                         {
2697                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2698                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2699                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2700                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2701                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2702                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2703                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2704                         }
2705                         else
2706                         {
2707                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2708                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2709                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2710                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2711                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2712                         }
2713                         // additive passes are only darkened by fog, not tinted
2714                         if (r_glsl_permutation->loc_FogColor >= 0)
2715                         {
2716                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2717                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2718                                 else
2719                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2720                         }
2721                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2722                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2723                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2724                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2725                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2726                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2727                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2728                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2729                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2730                 }
2731                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2732                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2733                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2734                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2735                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2736
2737                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2738                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2739                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2740                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2741                 {
2742                         if (rsurface.texture->pantstexture)
2743                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2744                         else
2745                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2746                 }
2747                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2748                 {
2749                         if (rsurface.texture->shirttexture)
2750                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2751                         else
2752                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2753                 }
2754                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2755                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2756                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2757                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2758                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2759                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2760                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2761                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2762                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2763                         );
2764                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2765                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2766                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2767                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2768
2769                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2770                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2771                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2772                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2773                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2774                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2775                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2776                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2777                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2778                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2779                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2780                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2781                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2782                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2783                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2784                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2785                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2786                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2787                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2788                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2789                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2790                 {
2791                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2792                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2793                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2794                 }
2795                 else
2796                 {
2797                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2798                 }
2799                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2800                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2801                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2802                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2803                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2804                 {
2805                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2806                         if (rsurface.rtlight)
2807                         {
2808                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2809                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2810                         }
2811                 }
2812                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2813                 CHECKGLERROR
2814                 break;
2815         case RENDERPATH_GL11:
2816         case RENDERPATH_GL13:
2817         case RENDERPATH_GLES1:
2818                 break;
2819         case RENDERPATH_SOFT:
2820                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0), texturenumsurfaces, texturesurfacelist);
2821                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2822                 R_SetupShader_SetPermutationSoft(mode, permutation);
2823                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2824                 if (mode == SHADERMODE_LIGHTSOURCE)
2825                 {
2826                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2827                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2828                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2829                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2830                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2831                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2832         
2833                         // additive passes are only darkened by fog, not tinted
2834                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2835                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2836                 }
2837                 else
2838                 {
2839                         if (mode == SHADERMODE_FLATCOLOR)
2840                         {
2841                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2842                         }
2843                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2844                         {
2845                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2846                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2847                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2848                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * r_shadow_deferred_8bitrange.value, colormod[1] * r_shadow_deferred_8bitrange.value, colormod[2] * r_shadow_deferred_8bitrange.value);
2849                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2850                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2851                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2852                         }
2853                         else
2854                         {
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2856                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2858                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[1] * diffusescale * r_shadow_deferred_8bitrange.value, colormod[2] * diffusescale * r_shadow_deferred_8bitrange.value);
2859                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2860                         }
2861                         // additive passes are only darkened by fog, not tinted
2862                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2864                         else
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2866                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2867                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2868                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2869                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2870                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2871                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2872                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2873                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2874                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2875                 }
2876                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2877                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2878                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2879                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2880                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2881
2882                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2883                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2884                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2885                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2886                 {
2887                         if (rsurface.texture->pantstexture)
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2889                         else
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2891                 }
2892                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2893                 {
2894                         if (rsurface.texture->shirttexture)
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2896                         else
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2898                 }
2899                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2900                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2901                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2902                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2903                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2904                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2905                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2906                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2907                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2908                         );
2909                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2910                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2911
2912                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2913                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2914                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2915                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2916                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2917                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2918                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2919                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2920                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2921                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2922                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2923                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2924                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2925                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2926                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2927                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2928                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2929                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2930                 {
2931                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2932                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2933                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2934                 }
2935                 else
2936                 {
2937                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2938                 }
2939 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2940 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2941                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2942                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2943                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2944                 {
2945                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2946                         if (rsurface.rtlight)
2947                         {
2948                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2949                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2950                         }
2951                 }
2952                 break;
2953         }
2954 }
2955
2956 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2957 {
2958         // select a permutation of the lighting shader appropriate to this
2959         // combination of texture, entity, light source, and fogging, only use the
2960         // minimum features necessary to avoid wasting rendering time in the
2961         // fragment shader on features that are not being used
2962         unsigned int permutation = 0;
2963         unsigned int mode = 0;
2964         const float *lightcolorbase = rtlight->currentcolor;
2965         float ambientscale = rtlight->ambientscale;
2966         float diffusescale = rtlight->diffusescale;
2967         float specularscale = rtlight->specularscale;
2968         // this is the location of the light in view space
2969         vec3_t viewlightorigin;
2970         // this transforms from view space (camera) to light space (cubemap)
2971         matrix4x4_t viewtolight;
2972         matrix4x4_t lighttoview;
2973         float viewtolight16f[16];
2974         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2975         // light source
2976         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2977         if (rtlight->currentcubemap != r_texture_whitecube)
2978                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2979         if (diffusescale > 0)
2980                 permutation |= SHADERPERMUTATION_DIFFUSE;
2981         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2982                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2983         if (r_shadow_usingshadowmap2d)
2984         {
2985                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2986                 if (r_shadow_shadowmapvsdct)
2987                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2988
2989                 if (r_shadow_shadowmapsampler)
2990                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2991                 if (r_shadow_shadowmappcf > 1)
2992                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2993                 else if (r_shadow_shadowmappcf)
2994                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2995         }
2996         if (vid.allowalphatocoverage)
2997                 GL_AlphaToCoverage(false);
2998         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
2999         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3000         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3001         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3002         switch(vid.renderpath)
3003         {
3004         case RENDERPATH_D3D9:
3005 #ifdef SUPPORTD3D
3006                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3007                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3008                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3009                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3010                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3011                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3012                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3013                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3014                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3015                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3016                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3017
3018                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3019                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3020                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3021                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3022                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3023                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3024 #endif
3025                 break;
3026         case RENDERPATH_D3D10:
3027                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3028                 break;
3029         case RENDERPATH_D3D11:
3030                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3031                 break;
3032         case RENDERPATH_GL20:
3033         case RENDERPATH_GLES2:
3034                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3035                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3036                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3037                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3038                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3039                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3040                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3041                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3042                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3043                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3044                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3045
3046                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3047                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3048                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3049                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3050                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3051                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3052                 break;
3053         case RENDERPATH_GL11:
3054         case RENDERPATH_GL13:
3055         case RENDERPATH_GLES1:
3056                 break;
3057         case RENDERPATH_SOFT:
3058                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3059                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3060                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3061                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3062                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3063                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3064                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3065                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3066                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3067                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3068                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3069
3070                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3071                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3072                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3073                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3074                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3075                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3076                 break;
3077         }
3078 }
3079
3080 #define SKINFRAME_HASH 1024
3081
3082 typedef struct
3083 {
3084         int loadsequence; // incremented each level change
3085         memexpandablearray_t array;
3086         skinframe_t *hash[SKINFRAME_HASH];
3087 }
3088 r_skinframe_t;
3089 r_skinframe_t r_skinframe;
3090
3091 void R_SkinFrame_PrepareForPurge(void)
3092 {
3093         r_skinframe.loadsequence++;
3094         // wrap it without hitting zero
3095         if (r_skinframe.loadsequence >= 200)
3096                 r_skinframe.loadsequence = 1;
3097 }
3098
3099 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3100 {
3101         if (!skinframe)
3102                 return;
3103         // mark the skinframe as used for the purging code
3104         skinframe->loadsequence = r_skinframe.loadsequence;
3105 }
3106
3107 void R_SkinFrame_Purge(void)
3108 {
3109         int i;
3110         skinframe_t *s;
3111         for (i = 0;i < SKINFRAME_HASH;i++)
3112         {
3113                 for (s = r_skinframe.hash[i];s;s = s->next)
3114                 {
3115                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3116                         {
3117                                 if (s->merged == s->base)
3118                                         s->merged = NULL;
3119                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3120                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3121                                 R_PurgeTexture(s->merged);s->merged = NULL;
3122                                 R_PurgeTexture(s->base  );s->base   = NULL;
3123                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3124                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3125                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3126                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3127                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3128                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3129                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3130                                 s->loadsequence = 0;
3131                         }
3132                 }
3133         }
3134 }
3135
3136 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3137         skinframe_t *item;
3138         char basename[MAX_QPATH];
3139
3140         Image_StripImageExtension(name, basename, sizeof(basename));
3141
3142         if( last == NULL ) {
3143                 int hashindex;
3144                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3145                 item = r_skinframe.hash[hashindex];
3146         } else {
3147                 item = last->next;
3148         }
3149
3150         // linearly search through the hash bucket
3151         for( ; item ; item = item->next ) {
3152                 if( !strcmp( item->basename, basename ) ) {
3153                         return item;
3154                 }
3155         }
3156         return NULL;
3157 }
3158
3159 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3160 {
3161         skinframe_t *item;
3162         int hashindex;
3163         char basename[MAX_QPATH];
3164
3165         Image_StripImageExtension(name, basename, sizeof(basename));
3166
3167         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3168         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3169                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3170                         break;
3171
3172         if (!item) {
3173                 rtexture_t *dyntexture;
3174                 // check whether its a dynamic texture
3175                 dyntexture = CL_GetDynTexture( basename );
3176                 if (!add && !dyntexture)
3177                         return NULL;
3178                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3179                 memset(item, 0, sizeof(*item));
3180                 strlcpy(item->basename, basename, sizeof(item->basename));
3181                 item->base = dyntexture; // either NULL or dyntexture handle
3182                 item->textureflags = textureflags;
3183                 item->comparewidth = comparewidth;
3184                 item->compareheight = compareheight;
3185                 item->comparecrc = comparecrc;
3186                 item->next = r_skinframe.hash[hashindex];
3187                 r_skinframe.hash[hashindex] = item;
3188         }
3189         else if( item->base == NULL )
3190         {
3191                 rtexture_t *dyntexture;
3192                 // check whether its a dynamic texture
3193                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3194                 dyntexture = CL_GetDynTexture( basename );
3195                 item->base = dyntexture; // either NULL or dyntexture handle
3196         }
3197
3198         R_SkinFrame_MarkUsed(item);
3199         return item;
3200 }
3201
3202 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3203         { \
3204                 unsigned long long avgcolor[5], wsum; \
3205                 int pix, comp, w; \
3206                 avgcolor[0] = 0; \
3207                 avgcolor[1] = 0; \
3208                 avgcolor[2] = 0; \
3209                 avgcolor[3] = 0; \
3210                 avgcolor[4] = 0; \
3211                 wsum = 0; \
3212                 for(pix = 0; pix < cnt; ++pix) \
3213                 { \
3214                         w = 0; \
3215                         for(comp = 0; comp < 3; ++comp) \
3216                                 w += getpixel; \
3217                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3218                         { \
3219                                 ++wsum; \
3220                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3221                                 w = getpixel; \
3222                                 for(comp = 0; comp < 3; ++comp) \
3223                                         avgcolor[comp] += getpixel * w; \
3224                                 avgcolor[3] += w; \
3225                         } \
3226                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3227                         avgcolor[4] += getpixel; \
3228                 } \
3229                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3230                         avgcolor[3] = 1; \
3231                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3232                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3233                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3234                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3235         }
3236
3237 extern cvar_t gl_picmip;
3238 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3239 {
3240         int j;
3241         unsigned char *pixels;
3242         unsigned char *bumppixels;
3243         unsigned char *basepixels = NULL;
3244         int basepixels_width = 0;
3245         int basepixels_height = 0;
3246         skinframe_t *skinframe;
3247         rtexture_t *ddsbase = NULL;
3248         qboolean ddshasalpha = false;
3249         float ddsavgcolor[4];
3250         char basename[MAX_QPATH];
3251         int miplevel = R_PicmipForFlags(textureflags);
3252         int savemiplevel = miplevel;
3253         int mymiplevel;
3254
3255         if (cls.state == ca_dedicated)
3256                 return NULL;
3257
3258         // return an existing skinframe if already loaded
3259         // if loading of the first image fails, don't make a new skinframe as it
3260         // would cause all future lookups of this to be missing
3261         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3262         if (skinframe && skinframe->base)
3263                 return skinframe;
3264
3265         Image_StripImageExtension(name, basename, sizeof(basename));
3266
3267         // check for DDS texture file first
3268         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3269         {
3270                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3271                 if (basepixels == NULL)
3272                         return NULL;
3273         }
3274
3275         // FIXME handle miplevel
3276
3277         if (developer_loading.integer)
3278                 Con_Printf("loading skin \"%s\"\n", name);
3279
3280         // we've got some pixels to store, so really allocate this new texture now
3281         if (!skinframe)
3282                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3283         skinframe->stain = NULL;
3284         skinframe->merged = NULL;
3285         skinframe->base = NULL;
3286         skinframe->pants = NULL;
3287         skinframe->shirt = NULL;
3288         skinframe->nmap = NULL;
3289         skinframe->gloss = NULL;
3290         skinframe->glow = NULL;
3291         skinframe->fog = NULL;
3292         skinframe->reflect = NULL;
3293         skinframe->hasalpha = false;
3294
3295         if (ddsbase)
3296         {
3297                 skinframe->base = ddsbase;
3298                 skinframe->hasalpha = ddshasalpha;
3299                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3300                 if (r_loadfog && skinframe->hasalpha)
3301                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3302                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3303         }
3304         else
3305         {
3306                 basepixels_width = image_width;
3307                 basepixels_height = image_height;
3308                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3309                 if (textureflags & TEXF_ALPHA)
3310                 {
3311                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3312                         {
3313                                 if (basepixels[j] < 255)
3314                                 {
3315                                         skinframe->hasalpha = true;
3316                                         break;
3317                                 }
3318                         }
3319                         if (r_loadfog && skinframe->hasalpha)
3320                         {
3321                                 // has transparent pixels
3322                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3323                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3324                                 {
3325                                         pixels[j+0] = 255;
3326                                         pixels[j+1] = 255;
3327                                         pixels[j+2] = 255;
3328                                         pixels[j+3] = basepixels[j+3];
3329                                 }
3330                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va("%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3331                                 Mem_Free(pixels);
3332                         }
3333                 }
3334                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3335                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3336                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3337                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3338                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3339                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3340         }
3341
3342         if (r_loaddds)
3343         {
3344                 mymiplevel = savemiplevel;
3345                 if (r_loadnormalmap)
3346                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_norm.dds", skinframe->basename), (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel);
3347                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3348                 if (r_loadgloss)
3349                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3350                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3351                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3352                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3353         }
3354
3355         // _norm is the name used by tenebrae and has been adopted as standard
3356         if (r_loadnormalmap && skinframe->nmap == NULL)
3357         {
3358                 mymiplevel = savemiplevel;
3359                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3360                 {
3361                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3362                         Mem_Free(pixels);
3363                         pixels = NULL;
3364                 }
3365                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3366                 {
3367                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3368                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3369                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3370                         Mem_Free(pixels);
3371                         Mem_Free(bumppixels);
3372                 }
3373                 else if (r_shadow_bumpscale_basetexture.value > 0)
3374                 {
3375                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3376                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3377                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va("%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3378                         Mem_Free(pixels);
3379                 }
3380                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3381                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3382         }
3383
3384         // _luma is supported only for tenebrae compatibility
3385         // _glow is the preferred name
3386         mymiplevel = savemiplevel;
3387         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va("%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va("%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3388         {
3389                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va("%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3390                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3391                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3392                 Mem_Free(pixels);pixels = NULL;
3393         }
3394
3395         mymiplevel = savemiplevel;
3396         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3397         {
3398                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3399                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3400                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3401                 Mem_Free(pixels);
3402                 pixels = NULL;
3403         }
3404
3405         mymiplevel = savemiplevel;
3406         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3407         {
3408                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va("%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3409                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3410                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3411                 Mem_Free(pixels);
3412                 pixels = NULL;
3413         }
3414
3415         mymiplevel = savemiplevel;
3416         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3417         {
3418                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va("%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3419                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3420                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3421                 Mem_Free(pixels);
3422                 pixels = NULL;
3423         }
3424
3425         mymiplevel = savemiplevel;
3426         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3427         {
3428                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va("%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3429                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3430                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3431                 Mem_Free(pixels);
3432                 pixels = NULL;
3433         }
3434
3435         if (basepixels)
3436                 Mem_Free(basepixels);
3437
3438         return skinframe;
3439 }
3440
3441 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3442 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3443 {
3444         int i;
3445         unsigned char *temp1, *temp2;
3446         skinframe_t *skinframe;
3447
3448         if (cls.state == ca_dedicated)
3449                 return NULL;
3450
3451         // if already loaded just return it, otherwise make a new skinframe
3452         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3453         if (skinframe && skinframe->base)
3454                 return skinframe;
3455
3456         skinframe->stain = NULL;
3457         skinframe->merged = NULL;
3458         skinframe->base = NULL;
3459         skinframe->pants = NULL;
3460         skinframe->shirt = NULL;
3461         skinframe->nmap = NULL;
3462         skinframe->gloss = NULL;
3463         skinframe->glow = NULL;
3464         skinframe->fog = NULL;
3465         skinframe->reflect = NULL;
3466         skinframe->hasalpha = false;
3467
3468         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3469         if (!skindata)
3470                 return NULL;
3471
3472         if (developer_loading.integer)
3473                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3474
3475         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3476         {
3477                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3478                 temp2 = temp1 + width * height * 4;
3479                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3480                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3481                 Mem_Free(temp1);
3482         }
3483         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3484         if (textureflags & TEXF_ALPHA)
3485         {
3486                 for (i = 3;i < width * height * 4;i += 4)
3487                 {
3488                         if (skindata[i] < 255)
3489                         {
3490                                 skinframe->hasalpha = true;
3491                                 break;
3492                         }
3493                 }
3494                 if (r_loadfog && skinframe->hasalpha)
3495                 {
3496                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3497                         memcpy(fogpixels, skindata, width * height * 4);
3498                         for (i = 0;i < width * height * 4;i += 4)
3499                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3500                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3501                         Mem_Free(fogpixels);
3502                 }
3503         }
3504
3505         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3506         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3507
3508         return skinframe;
3509 }
3510
3511 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3512 {
3513         int i;
3514         int featuresmask;
3515         skinframe_t *skinframe;
3516
3517         if (cls.state == ca_dedicated)
3518                 return NULL;
3519
3520         // if already loaded just return it, otherwise make a new skinframe
3521         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3522         if (skinframe && skinframe->base)
3523                 return skinframe;
3524
3525         skinframe->stain = NULL;
3526         skinframe->merged = NULL;
3527         skinframe->base = NULL;
3528         skinframe->pants = NULL;
3529         skinframe->shirt = NULL;
3530         skinframe->nmap = NULL;
3531         skinframe->gloss = NULL;
3532         skinframe->glow = NULL;
3533         skinframe->fog = NULL;
3534         skinframe->reflect = NULL;
3535         skinframe->hasalpha = false;
3536
3537         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3538         if (!skindata)
3539                 return NULL;
3540
3541         if (developer_loading.integer)
3542                 Con_Printf("loading quake skin \"%s\"\n", name);
3543
3544         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3545         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3546         memcpy(skinframe->qpixels, skindata, width*height);
3547         skinframe->qwidth = width;
3548         skinframe->qheight = height;
3549
3550         featuresmask = 0;
3551         for (i = 0;i < width * height;i++)
3552                 featuresmask |= palette_featureflags[skindata[i]];
3553
3554         skinframe->hasalpha = false;
3555         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3556         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3557         skinframe->qgeneratemerged = true;
3558         skinframe->qgeneratebase = skinframe->qhascolormapping;
3559         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3560
3561         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3562         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3563
3564         return skinframe;
3565 }
3566
3567 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3568 {
3569         int width;
3570         int height;
3571         unsigned char *skindata;
3572
3573         if (!skinframe->qpixels)
3574                 return;
3575
3576         if (!skinframe->qhascolormapping)
3577                 colormapped = false;
3578
3579         if (colormapped)
3580         {
3581                 if (!skinframe->qgeneratebase)
3582                         return;
3583         }
3584         else
3585         {
3586                 if (!skinframe->qgeneratemerged)
3587                         return;
3588         }
3589
3590         width = skinframe->qwidth;
3591         height = skinframe->qheight;
3592         skindata = skinframe->qpixels;
3593
3594         if (skinframe->qgeneratenmap)
3595         {
3596                 unsigned char *temp1, *temp2;
3597                 skinframe->qgeneratenmap = false;
3598                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3599                 temp2 = temp1 + width * height * 4;
3600                 // use either a custom palette or the quake palette
3601                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3602                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3603                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va("%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (skinframe->textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3604                 Mem_Free(temp1);
3605         }
3606
3607         if (skinframe->qgenerateglow)
3608         {
3609                 skinframe->qgenerateglow = false;
3610                 skinframe->glow = R_LoadTexture2D(r_main_texturepool, va("%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_onlyfullbrights); // glow
3611         }
3612
3613         if (colormapped)
3614         {
3615                 skinframe->qgeneratebase = false;
3616                 skinframe->base  = R_LoadTexture2D(r_main_texturepool, va("%s_nospecial", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nocolormapnofullbrights : palette_bgra_nocolormap);
3617                 skinframe->pants = R_LoadTexture2D(r_main_texturepool, va("%s_pants", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_pantsaswhite);
3618                 skinframe->shirt = R_LoadTexture2D(r_main_texturepool, va("%s_shirt", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, palette_bgra_shirtaswhite);
3619         }
3620         else
3621         {
3622                 skinframe->qgeneratemerged = false;
3623                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3624         }
3625
3626         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3627         {
3628                 Mem_Free(skinframe->qpixels);
3629                 skinframe->qpixels = NULL;
3630         }
3631 }
3632
3633 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3634 {
3635         int i;
3636         skinframe_t *skinframe;
3637
3638         if (cls.state == ca_dedicated)
3639                 return NULL;
3640
3641         // if already loaded just return it, otherwise make a new skinframe
3642         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3643         if (skinframe && skinframe->base)
3644                 return skinframe;
3645
3646         skinframe->stain = NULL;
3647         skinframe->merged = NULL;
3648         skinframe->base = NULL;
3649         skinframe->pants = NULL;
3650         skinframe->shirt = NULL;
3651         skinframe->nmap = NULL;
3652         skinframe->gloss = NULL;
3653         skinframe->glow = NULL;
3654         skinframe->fog = NULL;
3655         skinframe->reflect = NULL;
3656         skinframe->hasalpha = false;
3657
3658         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3659         if (!skindata)
3660                 return NULL;
3661
3662         if (developer_loading.integer)
3663                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3664
3665         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3666         if (textureflags & TEXF_ALPHA)
3667         {
3668                 for (i = 0;i < width * height;i++)
3669                 {
3670                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3671                         {
3672                                 skinframe->hasalpha = true;
3673                                 break;
3674                         }
3675                 }
3676                 if (r_loadfog && skinframe->hasalpha)
3677                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3678         }
3679
3680         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3681         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3682
3683         return skinframe;
3684 }
3685
3686 skinframe_t *R_SkinFrame_LoadMissing(void)
3687 {
3688         skinframe_t *skinframe;
3689
3690         if (cls.state == ca_dedicated)
3691                 return NULL;
3692
3693         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3694         skinframe->stain = NULL;
3695         skinframe->merged = NULL;
3696         skinframe->base = NULL;
3697         skinframe->pants = NULL;
3698         skinframe->shirt = NULL;
3699         skinframe->nmap = NULL;
3700         skinframe->gloss = NULL;
3701         skinframe->glow = NULL;
3702         skinframe->fog = NULL;
3703         skinframe->reflect = NULL;
3704         skinframe->hasalpha = false;
3705
3706         skinframe->avgcolor[0] = rand() / RAND_MAX;
3707         skinframe->avgcolor[1] = rand() / RAND_MAX;
3708         skinframe->avgcolor[2] = rand() / RAND_MAX;
3709         skinframe->avgcolor[3] = 1;
3710
3711         return skinframe;
3712 }
3713
3714 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3715 typedef struct suffixinfo_s
3716 {
3717         const char *suffix;
3718         qboolean flipx, flipy, flipdiagonal;
3719 }
3720 suffixinfo_t;
3721 static suffixinfo_t suffix[3][6] =
3722 {
3723         {
3724                 {"px",   false, false, false},
3725                 {"nx",   false, false, false},
3726                 {"py",   false, false, false},
3727                 {"ny",   false, false, false},
3728                 {"pz",   false, false, false},
3729                 {"nz",   false, false, false}
3730         },
3731         {
3732                 {"posx", false, false, false},
3733                 {"negx", false, false, false},
3734                 {"posy", false, false, false},
3735                 {"negy", false, false, false},
3736                 {"posz", false, false, false},
3737                 {"negz", false, false, false}
3738         },
3739         {
3740                 {"rt",    true, false,  true},
3741                 {"lf",   false,  true,  true},
3742                 {"ft",    true,  true, false},
3743                 {"bk",   false, false, false},
3744                 {"up",    true, false,  true},
3745                 {"dn",    true, false,  true}
3746         }
3747 };
3748
3749 static int componentorder[4] = {0, 1, 2, 3};
3750
3751 rtexture_t *R_LoadCubemap(const char *basename)
3752 {
3753         int i, j, cubemapsize;
3754         unsigned char *cubemappixels, *image_buffer;
3755         rtexture_t *cubemaptexture;
3756         char name[256];
3757         // must start 0 so the first loadimagepixels has no requested width/height
3758         cubemapsize = 0;
3759         cubemappixels = NULL;
3760         cubemaptexture = NULL;
3761         // keep trying different suffix groups (posx, px, rt) until one loads
3762         for (j = 0;j < 3 && !cubemappixels;j++)
3763         {
3764                 // load the 6 images in the suffix group
3765                 for (i = 0;i < 6;i++)
3766                 {
3767                         // generate an image name based on the base and and suffix
3768                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3769                         // load it
3770                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3771                         {
3772                                 // an image loaded, make sure width and height are equal
3773                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3774                                 {
3775                                         // if this is the first image to load successfully, allocate the cubemap memory
3776                                         if (!cubemappixels && image_width >= 1)
3777                                         {
3778                                                 cubemapsize = image_width;
3779                                                 // note this clears to black, so unavailable sides are black
3780                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3781                                         }
3782                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3783                                         if (cubemappixels)
3784                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3785                                 }
3786                                 else
3787                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3788                                 // free the image
3789                                 Mem_Free(image_buffer);
3790                         }
3791                 }
3792         }
3793         // if a cubemap loaded, upload it
3794         if (cubemappixels)
3795         {
3796                 if (developer_loading.integer)
3797                         Con_Printf("loading cubemap \"%s\"\n", basename);
3798
3799                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3800                 Mem_Free(cubemappixels);
3801         }
3802         else
3803         {
3804                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3805                 if (developer_loading.integer)
3806                 {
3807                         Con_Printf("(tried tried images ");
3808                         for (j = 0;j < 3;j++)
3809                                 for (i = 0;i < 6;i++)
3810                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3811                         Con_Print(" and was unable to find any of them).\n");
3812                 }
3813         }
3814         return cubemaptexture;
3815 }
3816
3817 rtexture_t *R_GetCubemap(const char *basename)
3818 {
3819         int i;
3820         for (i = 0;i < r_texture_numcubemaps;i++)
3821                 if (r_texture_cubemaps[i] != NULL)
3822                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3823                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3824         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3825                 return r_texture_whitecube;
3826         r_texture_numcubemaps++;
3827         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3828         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3829         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3830         return r_texture_cubemaps[i]->texture;
3831 }
3832
3833 void R_FreeCubemap(const char *basename)
3834 {
3835         int i;
3836
3837         for (i = 0;i < r_texture_numcubemaps;i++)
3838         {
3839                 if (r_texture_cubemaps[i] != NULL)
3840                 {
3841                         if (r_texture_cubemaps[i]->texture)
3842                         {
3843                                 if (developer_loading.integer)
3844                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3845                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3846                                 Mem_Free(r_texture_cubemaps[i]);
3847                                 r_texture_cubemaps[i] = NULL;
3848                         }
3849                 }
3850         }
3851 }
3852
3853 void R_FreeCubemaps(void)
3854 {
3855         int i;
3856         for (i = 0;i < r_texture_numcubemaps;i++)
3857         {
3858                 if (developer_loading.integer)
3859                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3860                 if (r_texture_cubemaps[i] != NULL)
3861                 {
3862                         if (r_texture_cubemaps[i]->texture)
3863                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3864                         Mem_Free(r_texture_cubemaps[i]);
3865                 }
3866         }
3867         r_texture_numcubemaps = 0;
3868 }
3869
3870 void R_Main_FreeViewCache(void)
3871 {
3872         if (r_refdef.viewcache.entityvisible)
3873                 Mem_Free(r_refdef.viewcache.entityvisible);
3874         if (r_refdef.viewcache.world_pvsbits)
3875                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3876         if (r_refdef.viewcache.world_leafvisible)
3877                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3878         if (r_refdef.viewcache.world_surfacevisible)
3879                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3880         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3881 }
3882
3883 void R_Main_ResizeViewCache(void)
3884 {
3885         int numentities = r_refdef.scene.numentities;
3886         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3887         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3888         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3889         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3890         if (r_refdef.viewcache.maxentities < numentities)
3891         {
3892                 r_refdef.viewcache.maxentities = numentities;
3893                 if (r_refdef.viewcache.entityvisible)
3894                         Mem_Free(r_refdef.viewcache.entityvisible);
3895                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3896         }
3897         if (r_refdef.viewcache.world_numclusters != numclusters)
3898         {
3899                 r_refdef.viewcache.world_numclusters = numclusters;
3900                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3901                 if (r_refdef.viewcache.world_pvsbits)
3902                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3903                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3904         }
3905         if (r_refdef.viewcache.world_numleafs != numleafs)
3906         {
3907                 r_refdef.viewcache.world_numleafs = numleafs;
3908                 if (r_refdef.viewcache.world_leafvisible)
3909                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3910                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3911         }
3912         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3913         {
3914                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3915                 if (r_refdef.viewcache.world_surfacevisible)
3916                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3917                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3918         }
3919 }
3920
3921 extern rtexture_t *loadingscreentexture;
3922 void gl_main_start(void)
3923 {
3924         loadingscreentexture = NULL;
3925         r_texture_blanknormalmap = NULL;
3926         r_texture_white = NULL;
3927         r_texture_grey128 = NULL;
3928         r_texture_black = NULL;
3929         r_texture_whitecube = NULL;
3930         r_texture_normalizationcube = NULL;
3931         r_texture_fogattenuation = NULL;
3932         r_texture_fogheighttexture = NULL;
3933         r_texture_gammaramps = NULL;
3934         r_texture_numcubemaps = 0;
3935
3936         r_loaddds = r_texture_dds_load.integer != 0;
3937         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3938
3939         switch(vid.renderpath)
3940         {
3941         case RENDERPATH_GL20:
3942         case RENDERPATH_D3D9:
3943         case RENDERPATH_D3D10:
3944         case RENDERPATH_D3D11:
3945         case RENDERPATH_SOFT:
3946         case RENDERPATH_GLES2:
3947                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3948                 Cvar_SetValueQuick(&gl_combine, 1);
3949                 Cvar_SetValueQuick(&r_glsl, 1);
3950                 r_loadnormalmap = true;
3951                 r_loadgloss = true;
3952                 r_loadfog = false;
3953                 break;
3954         case RENDERPATH_GL13:
3955         case RENDERPATH_GLES1:
3956                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3957                 Cvar_SetValueQuick(&gl_combine, 1);
3958                 Cvar_SetValueQuick(&r_glsl, 0);
3959                 r_loadnormalmap = false;
3960                 r_loadgloss = false;
3961                 r_loadfog = true;
3962                 break;
3963         case RENDERPATH_GL11:
3964                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3965                 Cvar_SetValueQuick(&gl_combine, 0);
3966                 Cvar_SetValueQuick(&r_glsl, 0);
3967                 r_loadnormalmap = false;
3968                 r_loadgloss = false;
3969                 r_loadfog = true;
3970                 break;
3971         }
3972
3973         R_AnimCache_Free();
3974         R_FrameData_Reset();
3975
3976         r_numqueries = 0;
3977         r_maxqueries = 0;
3978         memset(r_queries, 0, sizeof(r_queries));
3979
3980         r_qwskincache = NULL;
3981         r_qwskincache_size = 0;
3982
3983         // due to caching of texture_t references, the collision cache must be reset
3984         Collision_Cache_Reset(true);
3985
3986         // set up r_skinframe loading system for textures
3987         memset(&r_skinframe, 0, sizeof(r_skinframe));
3988         r_skinframe.loadsequence = 1;
3989         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3990
3991         r_main_texturepool = R_AllocTexturePool();
3992         R_BuildBlankTextures();
3993         R_BuildNoTexture();
3994         if (vid.support.arb_texture_cube_map)
3995         {
3996                 R_BuildWhiteCube();
3997                 R_BuildNormalizationCube();
3998         }
3999         r_texture_fogattenuation = NULL;
4000         r_texture_fogheighttexture = NULL;
4001         r_texture_gammaramps = NULL;
4002         //r_texture_fogintensity = NULL;
4003         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4004         memset(&r_waterstate, 0, sizeof(r_waterstate));
4005         r_glsl_permutation = NULL;
4006         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4007         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4008         glslshaderstring = NULL;
4009 #ifdef SUPPORTD3D
4010         r_hlsl_permutation = NULL;
4011         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4012         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4013 #endif
4014         hlslshaderstring = NULL;
4015         memset(&r_svbsp, 0, sizeof (r_svbsp));
4016
4017         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4018         r_texture_numcubemaps = 0;
4019
4020         r_refdef.fogmasktable_density = 0;
4021 }
4022
4023 void gl_main_shutdown(void)
4024 {
4025         R_AnimCache_Free();
4026         R_FrameData_Reset();
4027
4028         R_Main_FreeViewCache();
4029
4030         switch(vid.renderpath)
4031         {
4032         case RENDERPATH_GL11:
4033         case RENDERPATH_GL13:
4034         case RENDERPATH_GL20:
4035         case RENDERPATH_GLES1:
4036         case RENDERPATH_GLES2:
4037                 if (r_maxqueries)
4038                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4039                 break;
4040         case RENDERPATH_D3D9:
4041                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4042                 break;
4043         case RENDERPATH_D3D10:
4044                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4045                 break;
4046         case RENDERPATH_D3D11:
4047                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4048                 break;
4049         case RENDERPATH_SOFT:
4050                 break;
4051         }
4052
4053         r_numqueries = 0;
4054         r_maxqueries = 0;
4055         memset(r_queries, 0, sizeof(r_queries));
4056
4057         r_qwskincache = NULL;
4058         r_qwskincache_size = 0;
4059
4060         // clear out the r_skinframe state
4061         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4062         memset(&r_skinframe, 0, sizeof(r_skinframe));
4063
4064         if (r_svbsp.nodes)
4065                 Mem_Free(r_svbsp.nodes);
4066         memset(&r_svbsp, 0, sizeof (r_svbsp));
4067         R_FreeTexturePool(&r_main_texturepool);
4068         loadingscreentexture = NULL;
4069         r_texture_blanknormalmap = NULL;
4070         r_texture_white = NULL;
4071         r_texture_grey128 = NULL;
4072         r_texture_black = NULL;
4073         r_texture_whitecube = NULL;
4074         r_texture_normalizationcube = NULL;
4075         r_texture_fogattenuation = NULL;
4076         r_texture_fogheighttexture = NULL;
4077         r_texture_gammaramps = NULL;
4078         r_texture_numcubemaps = 0;
4079         //r_texture_fogintensity = NULL;
4080         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4081         memset(&r_waterstate, 0, sizeof(r_waterstate));
4082         R_GLSL_Restart_f();
4083
4084         r_glsl_permutation = NULL;
4085         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4086         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4087         glslshaderstring = NULL;
4088 #ifdef SUPPORTD3D
4089         r_hlsl_permutation = NULL;
4090         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4091         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4092 #endif
4093         hlslshaderstring = NULL;
4094 }
4095
4096 extern void CL_ParseEntityLump(char *entitystring);
4097 void gl_main_newmap(void)
4098 {
4099         // FIXME: move this code to client
4100         char *entities, entname[MAX_QPATH];
4101         if (r_qwskincache)
4102                 Mem_Free(r_qwskincache);
4103         r_qwskincache = NULL;
4104         r_qwskincache_size = 0;
4105         if (cl.worldmodel)
4106         {
4107                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4108                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4109                 {
4110                         CL_ParseEntityLump(entities);
4111                         Mem_Free(entities);
4112                         return;
4113                 }
4114                 if (cl.worldmodel->brush.entities)
4115                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4116         }
4117         R_Main_FreeViewCache();
4118
4119         R_FrameData_Reset();
4120 }
4121
4122 void GL_Main_Init(void)
4123 {
4124         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4125
4126         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4127         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4128         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4129         if (gamemode == GAME_NEHAHRA)
4130         {
4131                 Cvar_RegisterVariable (&gl_fogenable);
4132                 Cvar_RegisterVariable (&gl_fogdensity);
4133                 Cvar_RegisterVariable (&gl_fogred);
4134                 Cvar_RegisterVariable (&gl_foggreen);
4135                 Cvar_RegisterVariable (&gl_fogblue);
4136                 Cvar_RegisterVariable (&gl_fogstart);
4137                 Cvar_RegisterVariable (&gl_fogend);
4138                 Cvar_RegisterVariable (&gl_skyclip);
4139         }
4140         Cvar_RegisterVariable(&r_motionblur);
4141         Cvar_RegisterVariable(&r_motionblur_maxblur);
4142         Cvar_RegisterVariable(&r_motionblur_bmin);
4143         Cvar_RegisterVariable(&r_motionblur_vmin);
4144         Cvar_RegisterVariable(&r_motionblur_vmax);
4145         Cvar_RegisterVariable(&r_motionblur_vcoeff);
4146         Cvar_RegisterVariable(&r_motionblur_randomize);
4147         Cvar_RegisterVariable(&r_damageblur);
4148         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4149         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4150         Cvar_RegisterVariable(&r_equalize_entities_by);
4151         Cvar_RegisterVariable(&r_equalize_entities_to);
4152         Cvar_RegisterVariable(&r_depthfirst);
4153         Cvar_RegisterVariable(&r_useinfinitefarclip);
4154         Cvar_RegisterVariable(&r_farclip_base);
4155         Cvar_RegisterVariable(&r_farclip_world);
4156         Cvar_RegisterVariable(&r_nearclip);
4157         Cvar_RegisterVariable(&r_deformvertexes);
4158         Cvar_RegisterVariable(&r_transparent);
4159         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4160         Cvar_RegisterVariable(&r_showoverdraw);
4161         Cvar_RegisterVariable(&r_showbboxes);
4162         Cvar_RegisterVariable(&r_showsurfaces);
4163         Cvar_RegisterVariable(&r_showtris);
4164         Cvar_RegisterVariable(&r_shownormals);
4165         Cvar_RegisterVariable(&r_showlighting);
4166         Cvar_RegisterVariable(&r_showshadowvolumes);
4167         Cvar_RegisterVariable(&r_showcollisionbrushes);
4168         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4169         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4170         Cvar_RegisterVariable(&r_showdisabledepthtest);
4171         Cvar_RegisterVariable(&r_drawportals);
4172         Cvar_RegisterVariable(&r_drawentities);
4173         Cvar_RegisterVariable(&r_draw2d);
4174         Cvar_RegisterVariable(&r_drawworld);
4175         Cvar_RegisterVariable(&r_cullentities_trace);
4176         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4177         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4178         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4179         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4180         Cvar_RegisterVariable(&r_drawviewmodel);
4181         Cvar_RegisterVariable(&r_drawexteriormodel);
4182         Cvar_RegisterVariable(&r_speeds);
4183         Cvar_RegisterVariable(&r_fullbrights);
4184         Cvar_RegisterVariable(&r_wateralpha);
4185         Cvar_RegisterVariable(&r_dynamic);
4186         Cvar_RegisterVariable(&r_fakelight);
4187         Cvar_RegisterVariable(&r_fakelight_intensity);
4188         Cvar_RegisterVariable(&r_fullbright);
4189         Cvar_RegisterVariable(&r_shadows);
4190         Cvar_RegisterVariable(&r_shadows_darken);
4191         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4192         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4193         Cvar_RegisterVariable(&r_shadows_throwdistance);
4194         Cvar_RegisterVariable(&r_shadows_throwdirection);
4195         Cvar_RegisterVariable(&r_shadows_focus);
4196         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4197         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4198         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4199         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4200         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4201         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4202         Cvar_RegisterVariable(&r_fog_exp2);
4203         Cvar_RegisterVariable(&r_fog_clear);
4204         Cvar_RegisterVariable(&r_drawfog);
4205         Cvar_RegisterVariable(&r_transparentdepthmasking);
4206         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4207         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4208         Cvar_RegisterVariable(&r_texture_dds_load);
4209         Cvar_RegisterVariable(&r_texture_dds_save);
4210         Cvar_RegisterVariable(&r_textureunits);
4211         Cvar_RegisterVariable(&gl_combine);
4212         Cvar_RegisterVariable(&r_viewfbo);
4213         Cvar_RegisterVariable(&r_viewscale);
4214         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4215         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4216         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4217         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4218         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4219         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4220         Cvar_RegisterVariable(&r_glsl);
4221         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4222         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4223         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4224         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4225         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4226         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4227         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4228         Cvar_RegisterVariable(&r_glsl_postprocess);
4229         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4230         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4231         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4232         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4233         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4234         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4235         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4236         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4237
4238         Cvar_RegisterVariable(&r_water);
4239         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4240         Cvar_RegisterVariable(&r_water_clippingplanebias);
4241         Cvar_RegisterVariable(&r_water_refractdistort);
4242         Cvar_RegisterVariable(&r_water_reflectdistort);
4243         Cvar_RegisterVariable(&r_water_scissormode);
4244         Cvar_RegisterVariable(&r_water_lowquality);
4245
4246         Cvar_RegisterVariable(&r_lerpsprites);
4247         Cvar_RegisterVariable(&r_lerpmodels);
4248         Cvar_RegisterVariable(&r_lerplightstyles);
4249         Cvar_RegisterVariable(&r_waterscroll);
4250         Cvar_RegisterVariable(&r_bloom);
4251         Cvar_RegisterVariable(&r_bloom_colorscale);
4252         Cvar_RegisterVariable(&r_bloom_brighten);
4253         Cvar_RegisterVariable(&r_bloom_blur);
4254         Cvar_RegisterVariable(&r_bloom_resolution);
4255         Cvar_RegisterVariable(&r_bloom_colorexponent);
4256         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4257         Cvar_RegisterVariable(&r_hdr);
4258         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4259         Cvar_RegisterVariable(&r_hdr_glowintensity);
4260         Cvar_RegisterVariable(&r_hdr_range);
4261         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4262         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4263         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4264         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4265         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4266         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4267         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4268         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4269         Cvar_RegisterVariable(&developer_texturelogging);
4270         Cvar_RegisterVariable(&gl_lightmaps);
4271         Cvar_RegisterVariable(&r_test);
4272         Cvar_RegisterVariable(&r_glsl_saturation);
4273         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4274         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4275         Cvar_RegisterVariable(&r_framedatasize);
4276         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4277                 Cvar_SetValue("r_fullbrights", 0);
4278         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4279 }
4280
4281 extern void R_Textures_Init(void);
4282 extern void GL_Draw_Init(void);
4283 extern void GL_Main_Init(void);
4284 extern void R_Shadow_Init(void);
4285 extern void R_Sky_Init(void);
4286 extern void GL_Surf_Init(void);
4287 extern void R_Particles_Init(void);
4288 extern void R_Explosion_Init(void);
4289 extern void gl_backend_init(void);
4290 extern void Sbar_Init(void);
4291 extern void R_LightningBeams_Init(void);
4292 extern void Mod_RenderInit(void);
4293 extern void Font_Init(void);
4294
4295 void Render_Init(void)
4296 {
4297         gl_backend_init();
4298         R_Textures_Init();
4299         GL_Main_Init();
4300         Font_Init();
4301         GL_Draw_Init();
4302         R_Shadow_Init();
4303         R_Sky_Init();
4304         GL_Surf_Init();
4305         Sbar_Init();
4306         R_Particles_Init();
4307         R_Explosion_Init();
4308         R_LightningBeams_Init();
4309         Mod_RenderInit();
4310 }
4311
4312 /*
4313 ===============
4314 GL_Init
4315 ===============
4316 */
4317 extern char *ENGINE_EXTENSIONS;
4318 void GL_Init (void)
4319 {
4320         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4321         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4322         gl_version = (const char *)qglGetString(GL_VERSION);
4323         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4324
4325         if (!gl_extensions)
4326                 gl_extensions = "";
4327         if (!gl_platformextensions)
4328                 gl_platformextensions = "";
4329
4330         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4331         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4332         Con_Printf("GL_VERSION: %s\n", gl_version);
4333         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4334         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4335
4336         VID_CheckExtensions();
4337
4338         // LordHavoc: report supported extensions
4339         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4340
4341         // clear to black (loading plaque will be seen over this)
4342         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4343 }
4344
4345 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4346 {
4347         int i;
4348         mplane_t *p;
4349         if (r_trippy.integer)
4350                 return false;
4351         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4352         {
4353                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4354                 if (i == 4)
4355                         continue;
4356                 p = r_refdef.view.frustum + i;
4357                 switch(p->signbits)
4358                 {
4359                 default:
4360                 case 0:
4361                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4362                                 return true;
4363                         break;
4364                 case 1:
4365                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4366                                 return true;
4367                         break;
4368                 case 2:
4369                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4370                                 return true;
4371                         break;
4372                 case 3:
4373                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4374                                 return true;
4375                         break;
4376                 case 4:
4377                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4378                                 return true;
4379                         break;
4380                 case 5:
4381                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4382                                 return true;
4383                         break;
4384                 case 6:
4385                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4386                                 return true;
4387                         break;
4388                 case 7:
4389                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4390                                 return true;
4391                         break;
4392                 }
4393         }
4394         return false;
4395 }
4396
4397 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4398 {
4399         int i;
4400         const mplane_t *p;
4401         if (r_trippy.integer)
4402                 return false;
4403         for (i = 0;i < numplanes;i++)
4404         {
4405                 p = planes + i;
4406                 switch(p->signbits)
4407                 {
4408                 default:
4409                 case 0:
4410                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4411                                 return true;
4412                         break;
4413                 case 1:
4414                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4415                                 return true;
4416                         break;
4417                 case 2:
4418                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4419                                 return true;
4420                         break;
4421                 case 3:
4422                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4423                                 return true;
4424                         break;
4425                 case 4:
4426                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4427                                 return true;
4428                         break;
4429                 case 5:
4430                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4431                                 return true;
4432                         break;
4433                 case 6:
4434                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 7:
4438                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 }
4442         }
4443         return false;
4444 }
4445
4446 //==================================================================================
4447
4448 // LordHavoc: this stores temporary data used within the same frame
4449
4450 typedef struct r_framedata_mem_s
4451 {
4452         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4453         size_t size; // how much usable space
4454         size_t current; // how much space in use
4455         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4456         size_t wantedsize; // how much space was allocated
4457         unsigned char *data; // start of real data (16byte aligned)
4458 }
4459 r_framedata_mem_t;
4460
4461 static r_framedata_mem_t *r_framedata_mem;
4462
4463 void R_FrameData_Reset(void)
4464 {
4465         while (r_framedata_mem)
4466         {
4467                 r_framedata_mem_t *next = r_framedata_mem->purge;
4468                 Mem_Free(r_framedata_mem);
4469                 r_framedata_mem = next;
4470         }
4471 }
4472
4473 void R_FrameData_Resize(void)
4474 {
4475         size_t wantedsize;
4476         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4477         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4478         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4479         {
4480                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4481                 newmem->wantedsize = wantedsize;
4482                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4483                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4484                 newmem->current = 0;
4485                 newmem->mark = 0;
4486                 newmem->purge = r_framedata_mem;
4487                 r_framedata_mem = newmem;
4488         }
4489 }
4490
4491 void R_FrameData_NewFrame(void)
4492 {
4493         R_FrameData_Resize();
4494         if (!r_framedata_mem)
4495                 return;
4496         // if we ran out of space on the last frame, free the old memory now
4497         while (r_framedata_mem->purge)
4498         {
4499                 // repeatedly remove the second item in the list, leaving only head
4500                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4501                 Mem_Free(r_framedata_mem->purge);
4502                 r_framedata_mem->purge = next;
4503         }
4504         // reset the current mem pointer
4505         r_framedata_mem->current = 0;
4506         r_framedata_mem->mark = 0;
4507 }
4508
4509 void *R_FrameData_Alloc(size_t size)
4510 {
4511         void *data;
4512
4513         // align to 16 byte boundary - the data pointer is already aligned, so we
4514         // only need to ensure the size of every allocation is also aligned
4515         size = (size + 15) & ~15;
4516
4517         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4518         {
4519                 // emergency - we ran out of space, allocate more memory
4520                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4521                 R_FrameData_Resize();
4522         }
4523
4524         data = r_framedata_mem->data + r_framedata_mem->current;
4525         r_framedata_mem->current += size;
4526
4527         // count the usage for stats
4528         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4529         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4530
4531         return (void *)data;
4532 }
4533
4534 void *R_FrameData_Store(size_t size, void *data)
4535 {
4536         void *d = R_FrameData_Alloc(size);
4537         if (d && data)
4538                 memcpy(d, data, size);
4539         return d;
4540 }
4541
4542 void R_FrameData_SetMark(void)
4543 {
4544         if (!r_framedata_mem)
4545                 return;
4546         r_framedata_mem->mark = r_framedata_mem->current;
4547 }
4548
4549 void R_FrameData_ReturnToMark(void)
4550 {
4551         if (!r_framedata_mem)
4552                 return;
4553         r_framedata_mem->current = r_framedata_mem->mark;
4554 }
4555
4556 //==================================================================================
4557
4558 // LordHavoc: animcache originally written by Echon, rewritten since then
4559
4560 /**
4561  * Animation cache prevents re-generating mesh data for an animated model
4562  * multiple times in one frame for lighting, shadowing, reflections, etc.
4563  */
4564
4565 void R_AnimCache_Free(void)
4566 {
4567 }
4568
4569 void R_AnimCache_ClearCache(void)
4570 {
4571         int i;
4572         entity_render_t *ent;
4573
4574         for (i = 0;i < r_refdef.scene.numentities;i++)
4575         {
4576                 ent = r_refdef.scene.entities[i];
4577                 ent->animcache_vertex3f = NULL;
4578                 ent->animcache_normal3f = NULL;
4579                 ent->animcache_svector3f = NULL;
4580                 ent->animcache_tvector3f = NULL;
4581                 ent->animcache_vertexmesh = NULL;
4582                 ent->animcache_vertex3fbuffer = NULL;
4583                 ent->animcache_vertexmeshbuffer = NULL;
4584         }
4585 }
4586
4587 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4588 {
4589         int i;
4590
4591         // check if we need the meshbuffers
4592         if (!vid.useinterleavedarrays)
4593                 return;
4594
4595         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4596                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4597         // TODO: upload vertex3f buffer?
4598         if (ent->animcache_vertexmesh)
4599         {
4600                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4601                 for (i = 0;i < numvertices;i++)
4602                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4603                 if (ent->animcache_svector3f)
4604                         for (i = 0;i < numvertices;i++)
4605                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4606                 if (ent->animcache_tvector3f)
4607                         for (i = 0;i < numvertices;i++)
4608                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4609                 if (ent->animcache_normal3f)
4610                         for (i = 0;i < numvertices;i++)
4611                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4612                 // TODO: upload vertexmeshbuffer?
4613         }
4614 }
4615
4616 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4617 {
4618         dp_model_t *model = ent->model;
4619         int numvertices;
4620         // see if it's already cached this frame
4621         if (ent->animcache_vertex3f)
4622         {
4623                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4624                 if (wantnormals || wanttangents)
4625                 {
4626                         if (ent->animcache_normal3f)
4627                                 wantnormals = false;
4628                         if (ent->animcache_svector3f)
4629                                 wanttangents = false;
4630                         if (wantnormals || wanttangents)
4631                         {
4632                                 numvertices = model->surfmesh.num_vertices;
4633                                 if (wantnormals)
4634                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4635                                 if (wanttangents)
4636                                 {
4637                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4638                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4639                                 }
4640                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4641                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4642                         }
4643                 }
4644         }
4645         else
4646         {
4647                 // see if this ent is worth caching
4648                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4649                         return false;
4650                 // get some memory for this entity and generate mesh data
4651                 numvertices = model->surfmesh.num_vertices;
4652                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4653                 if (wantnormals)
4654                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4655                 if (wanttangents)
4656                 {
4657                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4658                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4659                 }
4660                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4661                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4662         }
4663         return true;
4664 }
4665
4666 void R_AnimCache_CacheVisibleEntities(void)
4667 {
4668         int i;
4669         qboolean wantnormals = true;
4670         qboolean wanttangents = !r_showsurfaces.integer;
4671
4672         switch(vid.renderpath)
4673         {
4674         case RENDERPATH_GL20:
4675         case RENDERPATH_D3D9:
4676         case RENDERPATH_D3D10:
4677         case RENDERPATH_D3D11:
4678         case RENDERPATH_GLES2:
4679                 break;
4680         case RENDERPATH_GL11:
4681         case RENDERPATH_GL13:
4682         case RENDERPATH_GLES1:
4683                 wanttangents = false;
4684                 break;
4685         case RENDERPATH_SOFT:
4686                 break;
4687         }
4688
4689         if (r_shownormals.integer)
4690                 wanttangents = wantnormals = true;
4691
4692         // TODO: thread this
4693         // NOTE: R_PrepareRTLights() also caches entities
4694
4695         for (i = 0;i < r_refdef.scene.numentities;i++)
4696                 if (r_refdef.viewcache.entityvisible[i])
4697                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4698 }
4699
4700 //==================================================================================
4701
4702 extern cvar_t r_overheadsprites_pushback;
4703
4704 static void R_View_UpdateEntityLighting (void)
4705 {
4706         int i;
4707         entity_render_t *ent;
4708         vec3_t tempdiffusenormal, avg;
4709         vec_t f, fa, fd, fdd;
4710         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4711
4712         for (i = 0;i < r_refdef.scene.numentities;i++)
4713         {
4714                 ent = r_refdef.scene.entities[i];
4715
4716                 // skip unseen models
4717                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4718                         continue;
4719
4720                 // skip bsp models
4721                 if (ent->model && ent->model->brush.num_leafs)
4722                 {
4723                         // TODO: use modellight for r_ambient settings on world?
4724                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4725                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4726                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4727                         continue;
4728                 }
4729
4730                 // fetch the lighting from the worldmodel data
4731                 VectorClear(ent->modellight_ambient);
4732                 VectorClear(ent->modellight_diffuse);
4733                 VectorClear(tempdiffusenormal);
4734                 if (ent->flags & RENDER_LIGHT)
4735                 {
4736                         vec3_t org;
4737                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4738
4739                         // complete lightning for lit sprites
4740                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4741                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4742                         {
4743                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4744                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4745                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4746                         }
4747                         else
4748                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4749
4750                         if(ent->flags & RENDER_EQUALIZE)
4751                         {
4752                                 // first fix up ambient lighting...
4753                                 if(r_equalize_entities_minambient.value > 0)
4754                                 {
4755                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4756                                         if(fd > 0)
4757                                         {
4758                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4759                                                 if(fa < r_equalize_entities_minambient.value * fd)
4760                                                 {
4761                                                         // solve:
4762                                                         //   fa'/fd' = minambient
4763                                                         //   fa'+0.25*fd' = fa+0.25*fd
4764                                                         //   ...
4765                                                         //   fa' = fd' * minambient
4766                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4767                                                         //   ...
4768                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4769                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4770                                                         //   ...
4771                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4772                                                         f = fdd / fd; // f>0 because all this is additive; f<1 because fdd<fd because this follows from fa < r_equalize_entities_minambient.value * fd
4773                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4774                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4775                                                 }
4776                                         }
4777                                 }
4778
4779                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4780                                 {
4781                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4782                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4783                                         f = fa + 0.25 * fd;
4784                                         if(f > 0)
4785                                         {
4786                                                 // adjust brightness and saturation to target
4787                                                 avg[0] = avg[1] = avg[2] = fa / f;
4788                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4789                                                 avg[0] = avg[1] = avg[2] = fd / f;
4790                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4791                                         }
4792                                 }
4793                         }
4794                 }
4795                 else // highly rare
4796                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4797
4798                 // move the light direction into modelspace coordinates for lighting code
4799                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4800                 if(VectorLength2(ent->modellight_lightdir) == 0)
4801                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4802                 VectorNormalize(ent->modellight_lightdir);
4803         }
4804 }
4805
4806 #define MAX_LINEOFSIGHTTRACES 64
4807
4808 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4809 {
4810         int i;
4811         vec3_t boxmins, boxmaxs;
4812         vec3_t start;
4813         vec3_t end;
4814         dp_model_t *model = r_refdef.scene.worldmodel;
4815
4816         if (!model || !model->brush.TraceLineOfSight)
4817                 return true;
4818
4819         // expand the box a little
4820         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4821         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4822         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4823         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4824         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4825         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4826
4827         // return true if eye is inside enlarged box
4828         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4829                 return true;
4830
4831         // try center
4832         VectorCopy(eye, start);
4833         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4834         if (model->brush.TraceLineOfSight(model, start, end))
4835                 return true;
4836
4837         // try various random positions
4838         for (i = 0;i < numsamples;i++)
4839         {
4840                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4841                 if (model->brush.TraceLineOfSight(model, start, end))
4842                         return true;
4843         }
4844
4845         return false;
4846 }
4847
4848
4849 static void R_View_UpdateEntityVisible (void)
4850 {
4851         int i;
4852         int renderimask;
4853         int samples;
4854         entity_render_t *ent;
4855
4856         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4857                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4858                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4859                 :                                                          RENDER_EXTERIORMODEL;
4860         if (!r_drawviewmodel.integer)
4861                 renderimask |= RENDER_VIEWMODEL;
4862         if (!r_drawexteriormodel.integer)
4863                 renderimask |= RENDER_EXTERIORMODEL;
4864         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4865         {
4866                 // worldmodel can check visibility
4867                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4868                 for (i = 0;i < r_refdef.scene.numentities;i++)
4869                 {
4870                         ent = r_refdef.scene.entities[i];
4871                         if (!(ent->flags & renderimask))
4872                         if (!R_CullBox(ent->mins, ent->maxs) || (ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)))
4873                         if ((ent->flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL)) || r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs(r_refdef.scene.worldmodel, r_refdef.viewcache.world_leafvisible, ent->mins, ent->maxs))
4874                                 r_refdef.viewcache.entityvisible[i] = true;
4875                 }
4876         }
4877         else
4878         {
4879                 // no worldmodel or it can't check visibility
4880                 for (i = 0;i < r_refdef.scene.numentities;i++)
4881                 {
4882                         ent = r_refdef.scene.entities[i];
4883                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
4884                 }
4885         }
4886         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4887                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4888         {
4889                 for (i = 0;i < r_refdef.scene.numentities;i++)
4890                 {
4891                         if (!r_refdef.viewcache.entityvisible[i])
4892                                 continue;
4893                         ent = r_refdef.scene.entities[i];
4894                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4895                         {
4896                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4897                                 if (samples < 0)
4898                                         continue; // temp entities do pvs only
4899                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4900                                         ent->last_trace_visibility = realtime;
4901                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4902                                         r_refdef.viewcache.entityvisible[i] = 0;
4903                         }
4904                 }
4905         }
4906 }
4907
4908 /// only used if skyrendermasked, and normally returns false
4909 int R_DrawBrushModelsSky (void)
4910 {
4911         int i, sky;
4912         entity_render_t *ent;
4913
4914         sky = false;
4915         for (i = 0;i < r_refdef.scene.numentities;i++)
4916         {
4917                 if (!r_refdef.viewcache.entityvisible[i])
4918                         continue;
4919                 ent = r_refdef.scene.entities[i];
4920                 if (!ent->model || !ent->model->DrawSky)
4921                         continue;
4922                 ent->model->DrawSky(ent);
4923                 sky = true;
4924         }
4925         return sky;
4926 }
4927
4928 static void R_DrawNoModel(entity_render_t *ent);
4929 static void R_DrawModels(void)
4930 {
4931         int i;
4932         entity_render_t *ent;
4933
4934         for (i = 0;i < r_refdef.scene.numentities;i++)
4935         {
4936                 if (!r_refdef.viewcache.entityvisible[i])
4937                         continue;
4938                 ent = r_refdef.scene.entities[i];
4939                 r_refdef.stats.entities++;
4940                 /*
4941                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4942                 {
4943                         vec3_t f, l, u, o;
4944                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4945                         Con_Printf("R_DrawModels\n");
4946                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
4947                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
4948                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
4949                 }
4950                 */
4951                 if (ent->model && ent->model->Draw != NULL)
4952                         ent->model->Draw(ent);
4953                 else
4954                         R_DrawNoModel(ent);
4955         }
4956 }
4957
4958 static void R_DrawModelsDepth(void)
4959 {
4960         int i;
4961         entity_render_t *ent;
4962
4963         for (i = 0;i < r_refdef.scene.numentities;i++)
4964         {
4965                 if (!r_refdef.viewcache.entityvisible[i])
4966                         continue;
4967                 ent = r_refdef.scene.entities[i];
4968                 if (ent->model && ent->model->DrawDepth != NULL)
4969                         ent->model->DrawDepth(ent);
4970         }
4971 }
4972
4973 static void R_DrawModelsDebug(void)
4974 {
4975         int i;
4976         entity_render_t *ent;
4977
4978         for (i = 0;i < r_refdef.scene.numentities;i++)
4979         {
4980                 if (!r_refdef.viewcache.entityvisible[i])
4981                         continue;
4982                 ent = r_refdef.scene.entities[i];
4983                 if (ent->model && ent->model->DrawDebug != NULL)
4984                         ent->model->DrawDebug(ent);
4985         }
4986 }
4987
4988 static void R_DrawModelsAddWaterPlanes(void)
4989 {
4990         int i;
4991         entity_render_t *ent;
4992
4993         for (i = 0;i < r_refdef.scene.numentities;i++)
4994         {
4995                 if (!r_refdef.viewcache.entityvisible[i])
4996                         continue;
4997                 ent = r_refdef.scene.entities[i];
4998                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
4999                         ent->model->DrawAddWaterPlanes(ent);
5000         }
5001 }
5002
5003 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5004 {
5005         if (r_hdr_irisadaptation.integer)
5006         {
5007                 vec3_t ambient;
5008                 vec3_t diffuse;
5009                 vec3_t diffusenormal;
5010                 vec_t brightness;
5011                 vec_t goal;
5012                 vec_t current;
5013                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5014                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5015                 brightness = max(0.0000001f, brightness);
5016                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5017                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5018                 current = r_hdr_irisadaptation_value.value;
5019                 if (current < goal)
5020                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5021                 else if (current > goal)
5022                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5023                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5024                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5025         }
5026         else if (r_hdr_irisadaptation_value.value != 1.0f)
5027                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5028 }
5029
5030 static void R_View_SetFrustum(const int *scissor)
5031 {
5032         int i;
5033         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5034         vec3_t forward, left, up, origin, v;
5035
5036         if(scissor)
5037         {
5038                 // flipped x coordinates (because x points left here)
5039                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5040                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5041
5042                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5043                 switch(vid.renderpath)
5044                 {
5045                         case RENDERPATH_D3D9:
5046                         case RENDERPATH_D3D10:
5047                         case RENDERPATH_D3D11:
5048                                 // non-flipped y coordinates
5049                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5050                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5051                                 break;
5052                         case RENDERPATH_SOFT:
5053                         case RENDERPATH_GL11:
5054                         case RENDERPATH_GL13:
5055                         case RENDERPATH_GL20:
5056                         case RENDERPATH_GLES1:
5057                         case RENDERPATH_GLES2:
5058                                 // non-flipped y coordinates
5059                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5060                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5061                                 break;
5062                 }
5063         }
5064
5065         // we can't trust r_refdef.view.forward and friends in reflected scenes
5066         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5067
5068 #if 0
5069         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5070         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5071         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5072         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5073         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5074         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5075         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5076         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5077         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5078         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5079         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5080         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5081 #endif
5082
5083 #if 0
5084         zNear = r_refdef.nearclip;
5085         nudge = 1.0 - 1.0 / (1<<23);
5086         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5087         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5088         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5089         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5090         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5091         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5092         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5093         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5094 #endif
5095
5096
5097
5098 #if 0
5099         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5100         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5101         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5102         r_refdef.view.frustum[0].dist = m[15] - m[12];
5103
5104         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5105         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5106         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5107         r_refdef.view.frustum[1].dist = m[15] + m[12];
5108
5109         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5110         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5111         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5112         r_refdef.view.frustum[2].dist = m[15] - m[13];
5113
5114         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5115         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5116         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5117         r_refdef.view.frustum[3].dist = m[15] + m[13];
5118
5119         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5120         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5121         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5122         r_refdef.view.frustum[4].dist = m[15] - m[14];
5123
5124         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5125         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5126         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5127         r_refdef.view.frustum[5].dist = m[15] + m[14];
5128 #endif
5129
5130         if (r_refdef.view.useperspective)
5131         {
5132                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5133                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5134                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5135                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5136                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5137
5138                 // then the normals from the corners relative to origin
5139                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5140                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5141                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5142                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5143
5144                 // in a NORMAL view, forward cross left == up
5145                 // in a REFLECTED view, forward cross left == down
5146                 // so our cross products above need to be adjusted for a left handed coordinate system
5147                 CrossProduct(forward, left, v);
5148                 if(DotProduct(v, up) < 0)
5149                 {
5150                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5151                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5152                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5153                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5154                 }
5155
5156                 // Leaving those out was a mistake, those were in the old code, and they
5157                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5158                 // I couldn't reproduce it after adding those normalizations. --blub
5159                 VectorNormalize(r_refdef.view.frustum[0].normal);
5160                 VectorNormalize(r_refdef.view.frustum[1].normal);
5161                 VectorNormalize(r_refdef.view.frustum[2].normal);
5162                 VectorNormalize(r_refdef.view.frustum[3].normal);
5163
5164                 // make the corners absolute
5165                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5166                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5167                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5168                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5169
5170                 // one more normal
5171                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5172
5173                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5174                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5175                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5176                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5177                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5178         }
5179         else
5180         {
5181                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5182                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5183                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5184                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5185                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5186                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5187                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5188                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5189                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5190                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5191         }
5192         r_refdef.view.numfrustumplanes = 5;
5193
5194         if (r_refdef.view.useclipplane)
5195         {
5196                 r_refdef.view.numfrustumplanes = 6;
5197                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5198         }
5199
5200         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5201                 PlaneClassify(r_refdef.view.frustum + i);
5202
5203         // LordHavoc: note to all quake engine coders, Quake had a special case
5204         // for 90 degrees which assumed a square view (wrong), so I removed it,
5205         // Quake2 has it disabled as well.
5206
5207         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5208         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5209         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5210         //PlaneClassify(&frustum[0]);
5211
5212         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5213         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5214         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5215         //PlaneClassify(&frustum[1]);
5216
5217         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5218         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5219         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5220         //PlaneClassify(&frustum[2]);
5221
5222         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5223         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5224         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5225         //PlaneClassify(&frustum[3]);
5226
5227         // nearclip plane
5228         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5229         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5230         //PlaneClassify(&frustum[4]);
5231 }
5232
5233 void R_View_UpdateWithScissor(const int *myscissor)
5234 {
5235         R_Main_ResizeViewCache();
5236         R_View_SetFrustum(myscissor);
5237         R_View_WorldVisibility(r_refdef.view.useclipplane);
5238         R_View_UpdateEntityVisible();
5239         R_View_UpdateEntityLighting();
5240 }
5241
5242 void R_View_Update(void)
5243 {
5244         R_Main_ResizeViewCache();
5245         R_View_SetFrustum(NULL);
5246         R_View_WorldVisibility(r_refdef.view.useclipplane);
5247         R_View_UpdateEntityVisible();
5248         R_View_UpdateEntityLighting();
5249 }
5250
5251 float viewscalefpsadjusted = 1.0f;
5252
5253 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5254 {
5255         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5256         scale = bound(0.03125f, scale, 1.0f);
5257         *outwidth = (int)ceil(width * scale);
5258         *outheight = (int)ceil(height * scale);
5259 }
5260
5261 void R_Mesh_SetMainRenderTargets(void)
5262 {
5263         if (r_bloomstate.fbo_framebuffer)
5264                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5265         else
5266                 R_Mesh_ResetRenderTargets();
5267 }
5268
5269 void R_SetupView(qboolean allowwaterclippingplane)
5270 {
5271         const float *customclipplane = NULL;
5272         float plane[4];
5273         int scaledwidth, scaledheight;
5274         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5275         {
5276                 // LordHavoc: couldn't figure out how to make this approach the
5277                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5278                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5279                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5280                         dist = r_refdef.view.clipplane.dist;
5281                 plane[0] = r_refdef.view.clipplane.normal[0];
5282                 plane[1] = r_refdef.view.clipplane.normal[1];
5283                 plane[2] = r_refdef.view.clipplane.normal[2];
5284                 plane[3] = -dist;
5285                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5286         }
5287
5288         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5289         if (!r_refdef.view.useperspective)
5290                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5291         else if (vid.stencil && r_useinfinitefarclip.integer)
5292                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5293         else
5294                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, vid.height - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5295         R_Mesh_SetMainRenderTargets();
5296         R_SetViewport(&r_refdef.view.viewport);
5297         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5298         {
5299                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5300                 float screenplane[4];
5301                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5302                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5303                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5304                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5305                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5306         }
5307 }
5308
5309 void R_EntityMatrix(const matrix4x4_t *matrix)
5310 {
5311         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5312         {
5313                 gl_modelmatrixchanged = false;
5314                 gl_modelmatrix = *matrix;
5315                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5316                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5317                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5318                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5319                 CHECKGLERROR
5320                 switch(vid.renderpath)
5321                 {
5322                 case RENDERPATH_D3D9:
5323 #ifdef SUPPORTD3D
5324                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5325                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5326 #endif
5327                         break;
5328                 case RENDERPATH_D3D10:
5329                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5330                         break;
5331                 case RENDERPATH_D3D11:
5332                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5333                         break;
5334                 case RENDERPATH_GL11:
5335                 case RENDERPATH_GL13:
5336                 case RENDERPATH_GLES1:
5337                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5338                         break;
5339                 case RENDERPATH_SOFT:
5340                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5341                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5342                         break;
5343                 case RENDERPATH_GL20:
5344                 case RENDERPATH_GLES2:
5345                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5346                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5347                         break;
5348                 }
5349         }
5350 }
5351
5352 void R_ResetViewRendering2D(void)
5353 {
5354         r_viewport_t viewport;
5355         DrawQ_Finish();
5356
5357         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5358         R_Viewport_InitOrtho(&viewport, &identitymatrix, r_refdef.view.x, vid.height - r_refdef.view.height - r_refdef.view.y, r_refdef.view.width, r_refdef.view.height, 0, 0, 1, 1, -10, 100, NULL);
5359         R_Mesh_ResetRenderTargets();
5360         R_SetViewport(&viewport);
5361         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5362         GL_Color(1, 1, 1, 1);
5363         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5364         GL_BlendFunc(GL_ONE, GL_ZERO);
5365         GL_ScissorTest(false);
5366         GL_DepthMask(false);
5367         GL_DepthRange(0, 1);
5368         GL_DepthTest(false);
5369         GL_DepthFunc(GL_LEQUAL);
5370         R_EntityMatrix(&identitymatrix);
5371         R_Mesh_ResetTextureState();
5372         GL_PolygonOffset(0, 0);
5373         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5374         switch(vid.renderpath)
5375         {
5376         case RENDERPATH_GL11:
5377         case RENDERPATH_GL13:
5378         case RENDERPATH_GL20:
5379         case RENDERPATH_GLES1:
5380         case RENDERPATH_GLES2:
5381                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5382                 break;
5383         case RENDERPATH_D3D9:
5384         case RENDERPATH_D3D10:
5385         case RENDERPATH_D3D11:
5386         case RENDERPATH_SOFT:
5387                 break;
5388         }
5389         GL_CullFace(GL_NONE);
5390 }
5391
5392 void R_ResetViewRendering3D(void)
5393 {
5394         DrawQ_Finish();
5395
5396         R_SetupView(true);
5397         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5398         GL_Color(1, 1, 1, 1);
5399         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5400         GL_BlendFunc(GL_ONE, GL_ZERO);
5401         GL_ScissorTest(true);
5402         GL_DepthMask(true);
5403         GL_DepthRange(0, 1);
5404         GL_DepthTest(true);
5405         GL_DepthFunc(GL_LEQUAL);
5406         R_EntityMatrix(&identitymatrix);
5407         R_Mesh_ResetTextureState();
5408         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5409         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5410         switch(vid.renderpath)
5411         {
5412         case RENDERPATH_GL11:
5413         case RENDERPATH_GL13:
5414         case RENDERPATH_GL20:
5415         case RENDERPATH_GLES1:
5416         case RENDERPATH_GLES2:
5417                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5418                 break;
5419         case RENDERPATH_D3D9:
5420         case RENDERPATH_D3D10:
5421         case RENDERPATH_D3D11:
5422         case RENDERPATH_SOFT:
5423                 break;
5424         }
5425         GL_CullFace(r_refdef.view.cullface_back);
5426 }
5427
5428 /*
5429 ================
5430 R_RenderView_UpdateViewVectors
5431 ================
5432 */
5433 static void R_RenderView_UpdateViewVectors(void)
5434 {
5435         // break apart the view matrix into vectors for various purposes
5436         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5437         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5438         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5439         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5440         // make an inverted copy of the view matrix for tracking sprites
5441         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5442 }
5443
5444 void R_RenderScene(void);
5445 void R_RenderWaterPlanes(void);
5446
5447 static void R_Water_StartFrame(void)
5448 {
5449         int i;
5450         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5451         r_waterstate_waterplane_t *p;
5452
5453         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5454                 return;
5455
5456         switch(vid.renderpath)
5457         {
5458         case RENDERPATH_GL20:
5459         case RENDERPATH_D3D9:
5460         case RENDERPATH_D3D10:
5461         case RENDERPATH_D3D11:
5462         case RENDERPATH_SOFT:
5463         case RENDERPATH_GLES2:
5464                 break;
5465         case RENDERPATH_GL11:
5466         case RENDERPATH_GL13:
5467         case RENDERPATH_GLES1:
5468                 return;
5469         }
5470
5471         // set waterwidth and waterheight to the water resolution that will be
5472         // used (often less than the screen resolution for faster rendering)
5473         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5474
5475         // calculate desired texture sizes
5476         // can't use water if the card does not support the texture size
5477         if (!r_water.integer || r_showsurfaces.integer)
5478                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5479         else if (vid.support.arb_texture_non_power_of_two)
5480         {
5481                 texturewidth = waterwidth;
5482                 textureheight = waterheight;
5483                 camerawidth = waterwidth;
5484                 cameraheight = waterheight;
5485         }
5486         else
5487         {
5488                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5489                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5490                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5491                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5492         }
5493
5494         // allocate textures as needed
5495         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5496         {
5497                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5498                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5499                 {
5500                         if (p->texture_refraction)
5501                                 R_FreeTexture(p->texture_refraction);
5502                         p->texture_refraction = NULL;
5503                         if (p->texture_reflection)
5504                                 R_FreeTexture(p->texture_reflection);
5505                         p->texture_reflection = NULL;
5506                         if (p->texture_camera)
5507                                 R_FreeTexture(p->texture_camera);
5508                         p->texture_camera = NULL;
5509                 }
5510                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5511                 r_waterstate.texturewidth = texturewidth;
5512                 r_waterstate.textureheight = textureheight;
5513                 r_waterstate.camerawidth = camerawidth;
5514                 r_waterstate.cameraheight = cameraheight;
5515         }
5516
5517         if (r_waterstate.texturewidth)
5518         {
5519                 int scaledwidth, scaledheight;
5520
5521                 r_waterstate.enabled = true;
5522
5523                 // when doing a reduced render (HDR) we want to use a smaller area
5524                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5525                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5526                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5527
5528                 // set up variables that will be used in shader setup
5529                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5530                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5531                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5532                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5533         }
5534
5535         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5536         r_waterstate.numwaterplanes = 0;
5537 }
5538
5539 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5540 {
5541         int triangleindex, planeindex;
5542         const int *e;
5543         vec3_t vert[3];
5544         vec3_t normal;
5545         vec3_t center;
5546         mplane_t plane;
5547         r_waterstate_waterplane_t *p;
5548         texture_t *t = R_GetCurrentTexture(surface->texture);
5549
5550         // just use the first triangle with a valid normal for any decisions
5551         VectorClear(normal);
5552         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5553         {
5554                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5555                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5556                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5557                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5558                 if (VectorLength2(normal) >= 0.001)
5559                         break;
5560         }
5561
5562         VectorCopy(normal, plane.normal);
5563         VectorNormalize(plane.normal);
5564         plane.dist = DotProduct(vert[0], plane.normal);
5565         PlaneClassify(&plane);
5566         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5567         {
5568                 // skip backfaces (except if nocullface is set)
5569                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5570                         return;
5571                 VectorNegate(plane.normal, plane.normal);
5572                 plane.dist *= -1;
5573                 PlaneClassify(&plane);
5574         }
5575
5576
5577         // find a matching plane if there is one
5578         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5579                 if(p->camera_entity == t->camera_entity)
5580                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5581                                 break;
5582         if (planeindex >= r_waterstate.maxwaterplanes)
5583                 return; // nothing we can do, out of planes
5584
5585         // if this triangle does not fit any known plane rendered this frame, add one
5586         if (planeindex >= r_waterstate.numwaterplanes)
5587         {
5588                 // store the new plane
5589                 r_waterstate.numwaterplanes++;
5590                 p->plane = plane;
5591                 // clear materialflags and pvs
5592                 p->materialflags = 0;
5593                 p->pvsvalid = false;
5594                 p->camera_entity = t->camera_entity;
5595                 VectorCopy(surface->mins, p->mins);
5596                 VectorCopy(surface->maxs, p->maxs);
5597         }
5598         else
5599         {
5600                 // merge mins/maxs
5601                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5602                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5603                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5604                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5605                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5606                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5607         }
5608         // merge this surface's materialflags into the waterplane
5609         p->materialflags |= t->currentmaterialflags;
5610         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5611         {
5612                 // merge this surface's PVS into the waterplane
5613                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5614                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5615                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5616                 {
5617                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5618                         p->pvsvalid = true;
5619                 }
5620         }
5621 }
5622
5623 extern cvar_t r_drawparticles;
5624 extern cvar_t r_drawdecals;
5625
5626 static void R_Water_ProcessPlanes(void)
5627 {
5628         int myscissor[4];
5629         r_refdef_view_t originalview;
5630         r_refdef_view_t myview;
5631         int planeindex, qualityreduction = 0, old_r_dynamic = 0, old_r_shadows = 0, old_r_worldrtlight = 0, old_r_dlight = 0, old_r_particles = 0, old_r_decals = 0;
5632         r_waterstate_waterplane_t *p;
5633         vec3_t visorigin;
5634
5635         originalview = r_refdef.view;
5636
5637         // lowquality hack, temporarily shut down some cvars and restore afterwards
5638         qualityreduction = r_water_lowquality.integer;
5639         if (qualityreduction > 0)
5640         {
5641                 if (qualityreduction >= 1)
5642                 {
5643                         old_r_shadows = r_shadows.integer;
5644                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5645                         old_r_dlight = r_shadow_realtime_dlight.integer;
5646                         Cvar_SetValueQuick(&r_shadows, 0);
5647                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5648                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5649                 }
5650                 if (qualityreduction >= 2)
5651                 {
5652                         old_r_dynamic = r_dynamic.integer;
5653                         old_r_particles = r_drawparticles.integer;
5654                         old_r_decals = r_drawdecals.integer;
5655                         Cvar_SetValueQuick(&r_dynamic, 0);
5656                         Cvar_SetValueQuick(&r_drawparticles, 0);
5657                         Cvar_SetValueQuick(&r_drawdecals, 0);
5658                 }
5659         }
5660
5661         // make sure enough textures are allocated
5662         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5663         {
5664                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5665                 {
5666                         if (!p->texture_refraction)
5667                                 p->texture_refraction = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_refraction", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5668                         if (!p->texture_refraction)
5669                                 goto error;
5670                 }
5671                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5672                 {
5673                         if (!p->texture_camera)
5674                                 p->texture_camera = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_camera", planeindex), r_waterstate.camerawidth, r_waterstate.cameraheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR, -1, NULL);
5675                         if (!p->texture_camera)
5676                                 goto error;
5677                 }
5678
5679                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5680                 {
5681                         if (!p->texture_reflection)
5682                                 p->texture_reflection = R_LoadTexture2D(r_main_texturepool, va("waterplane%i_reflection", planeindex), r_waterstate.texturewidth, r_waterstate.textureheight, NULL, TEXTYPE_COLORBUFFER, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5683                         if (!p->texture_reflection)
5684                                 goto error;
5685                 }
5686         }
5687
5688         // render views
5689         r_refdef.view = originalview;
5690         r_refdef.view.showdebug = false;
5691         r_refdef.view.width = r_waterstate.waterwidth;
5692         r_refdef.view.height = r_waterstate.waterheight;
5693         r_refdef.view.useclipplane = true;
5694         myview = r_refdef.view;
5695         r_waterstate.renderingscene = true;
5696         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5697         {
5698                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5699                 {
5700                         r_refdef.view = myview;
5701                         if(r_water_scissormode.integer)
5702                         {
5703                                 R_SetupView(true);
5704                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5705                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5706                         }
5707
5708                         // render reflected scene and copy into texture
5709                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5710                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5711                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5712                         r_refdef.view.clipplane = p->plane;
5713                         // reverse the cullface settings for this render
5714                         r_refdef.view.cullface_front = GL_FRONT;
5715                         r_refdef.view.cullface_back = GL_BACK;
5716                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5717                         {
5718                                 r_refdef.view.usecustompvs = true;
5719                                 if (p->pvsvalid)
5720                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5721                                 else
5722                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5723                         }
5724
5725                         R_ResetViewRendering3D();
5726                         R_ClearScreen(r_refdef.fogenabled);
5727                         if(r_water_scissormode.integer & 2)
5728                                 R_View_UpdateWithScissor(myscissor);
5729                         else
5730                                 R_View_Update();
5731                         if(r_water_scissormode.integer & 1)
5732                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5733                         R_RenderScene();
5734
5735                         R_Mesh_CopyToTexture(p->texture_reflection, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5736                 }
5737
5738                 // render the normal view scene and copy into texture
5739                 // (except that a clipping plane should be used to hide everything on one side of the water, and the viewer's weapon model should be omitted)
5740                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5741                 {
5742                         r_refdef.view = myview;
5743                         if(r_water_scissormode.integer)
5744                         {
5745                                 R_SetupView(true);
5746                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5747                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5748                         }
5749
5750                         r_waterstate.renderingrefraction = true;
5751
5752                         r_refdef.view.clipplane = p->plane;
5753                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5754                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5755
5756                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5757                         {
5758                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5759                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5760                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5761                                 R_RenderView_UpdateViewVectors();
5762                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5763                                 {
5764                                         r_refdef.view.usecustompvs = true;
5765                                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5766                                 }
5767                         }
5768
5769                         PlaneClassify(&r_refdef.view.clipplane);
5770
5771                         R_ResetViewRendering3D();
5772                         R_ClearScreen(r_refdef.fogenabled);
5773                         if(r_water_scissormode.integer & 2)
5774                                 R_View_UpdateWithScissor(myscissor);
5775                         else
5776                                 R_View_Update();
5777                         if(r_water_scissormode.integer & 1)
5778                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5779                         R_RenderScene();
5780
5781                         R_Mesh_CopyToTexture(p->texture_refraction, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5782                         r_waterstate.renderingrefraction = false;
5783                 }
5784                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5785                 {
5786                         r_refdef.view = myview;
5787
5788                         r_refdef.view.clipplane = p->plane;
5789                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5790                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5791
5792                         r_refdef.view.width = r_waterstate.camerawidth;
5793                         r_refdef.view.height = r_waterstate.cameraheight;
5794                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5795                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5796
5797                         if(p->camera_entity)
5798                         {
5799                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5800                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5801                         }
5802
5803                         // note: all of the view is used for displaying... so
5804                         // there is no use in scissoring
5805
5806                         // reverse the cullface settings for this render
5807                         r_refdef.view.cullface_front = GL_FRONT;
5808                         r_refdef.view.cullface_back = GL_BACK;
5809                         // also reverse the view matrix
5810                         Matrix4x4_ConcatScale3(&r_refdef.view.matrix, 1, 1, -1); // this serves to invert texcoords in the result, as the copied texture is mapped the wrong way round
5811                         R_RenderView_UpdateViewVectors();
5812                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5813                         {
5814                                 r_refdef.view.usecustompvs = true;
5815                                 r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, visorigin, 2, r_refdef.viewcache.world_pvsbits, (r_refdef.viewcache.world_numclusters+7)>>3, false);
5816                         }
5817                         
5818                         // camera needs no clipplane
5819                         r_refdef.view.useclipplane = false;
5820
5821                         PlaneClassify(&r_refdef.view.clipplane);
5822
5823                         R_ResetViewRendering3D();
5824                         R_ClearScreen(r_refdef.fogenabled);
5825                         R_View_Update();
5826                         R_RenderScene();
5827
5828                         R_Mesh_CopyToTexture(p->texture_camera, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5829                         r_waterstate.renderingrefraction = false;
5830                 }
5831
5832         }
5833         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5834         r_waterstate.renderingscene = false;
5835         r_refdef.view = originalview;
5836         R_ResetViewRendering3D();
5837         R_ClearScreen(r_refdef.fogenabled);
5838         R_View_Update();
5839         goto finish;
5840 error:
5841         r_refdef.view = originalview;
5842         r_waterstate.renderingscene = false;
5843         Cvar_SetValueQuick(&r_water, 0);
5844         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5845 finish:
5846         // lowquality hack, restore cvars
5847         if (qualityreduction > 0)
5848         {
5849                 if (qualityreduction >= 1)
5850                 {
5851                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5852                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5853                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5854                 }
5855                 if (qualityreduction >= 2)
5856                 {
5857                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5858                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5859                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5860                 }
5861         }
5862 }
5863
5864 void R_Bloom_StartFrame(void)
5865 {
5866         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5867         int viewwidth, viewheight;
5868         textype_t textype;
5869
5870         if (r_viewscale_fpsscaling.integer)
5871         {
5872                 double actualframetime;
5873                 double targetframetime;
5874                 double adjust;
5875                 actualframetime = r_refdef.lastdrawscreentime;
5876                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5877                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5878                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5879                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5880                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5881                 viewscalefpsadjusted += adjust;
5882                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5883         }
5884         else
5885                 viewscalefpsadjusted = 1.0f;
5886
5887         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5888
5889         switch(vid.renderpath)
5890         {
5891         case RENDERPATH_GL20:
5892         case RENDERPATH_D3D9:
5893         case RENDERPATH_D3D10:
5894         case RENDERPATH_D3D11:
5895         case RENDERPATH_SOFT:
5896         case RENDERPATH_GLES2:
5897                 break;
5898         case RENDERPATH_GL11:
5899         case RENDERPATH_GL13:
5900         case RENDERPATH_GLES1:
5901                 return;
5902         }
5903
5904         // set bloomwidth and bloomheight to the bloom resolution that will be
5905         // used (often less than the screen resolution for faster rendering)
5906         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5907         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5908         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5909         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5910         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5911
5912         // calculate desired texture sizes
5913         if (vid.support.arb_texture_non_power_of_two)
5914         {
5915                 screentexturewidth = vid.width;
5916                 screentextureheight = vid.height;
5917                 bloomtexturewidth = r_bloomstate.bloomwidth;
5918                 bloomtextureheight = r_bloomstate.bloomheight;
5919         }
5920         else
5921         {
5922                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5923                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5924                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5925                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5926         }
5927
5928         if ((r_hdr.integer || r_bloom.integer || (!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))) && ((r_bloom_resolution.integer < 4 || r_bloom_blur.value < 1 || r_bloom_blur.value >= 512) || r_refdef.view.width > (int)vid.maxtexturesize_2d || r_refdef.view.height > (int)vid.maxtexturesize_2d))
5929         {
5930                 Cvar_SetValueQuick(&r_hdr, 0);
5931                 Cvar_SetValueQuick(&r_bloom, 0);
5932                 Cvar_SetValueQuick(&r_motionblur, 0);
5933                 Cvar_SetValueQuick(&r_damageblur, 0);
5934         }
5935
5936         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial)) && !r_bloom.integer && !r_hdr.integer && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0)) && r_viewfbo.integer < 1 && r_viewscale.value == 1.0f && !r_viewscale_fpsscaling.integer)
5937                 screentexturewidth = screentextureheight = 0;
5938         if (!r_hdr.integer && !r_bloom.integer)
5939                 bloomtexturewidth = bloomtextureheight = 0;
5940
5941         textype = TEXTYPE_COLORBUFFER;
5942         switch (vid.renderpath)
5943         {
5944         case RENDERPATH_GL20:
5945         case RENDERPATH_GLES2:
5946                 if (vid.support.ext_framebuffer_object)
5947                 {
5948                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5949                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5950                 }
5951                 break;
5952         case RENDERPATH_GL11:
5953         case RENDERPATH_GL13:
5954         case RENDERPATH_GLES1:
5955         case RENDERPATH_D3D9:
5956         case RENDERPATH_D3D10:
5957         case RENDERPATH_D3D11:
5958         case RENDERPATH_SOFT:
5959                 break;
5960         }
5961
5962         // allocate textures as needed
5963         if (r_bloomstate.screentexturewidth != screentexturewidth
5964          || r_bloomstate.screentextureheight != screentextureheight
5965          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5966          || r_bloomstate.bloomtextureheight != bloomtextureheight
5967          || r_bloomstate.texturetype != textype
5968          || r_bloomstate.viewfbo != r_viewfbo.integer)
5969         {
5970                 if (r_bloomstate.texture_bloom)
5971                         R_FreeTexture(r_bloomstate.texture_bloom);
5972                 r_bloomstate.texture_bloom = NULL;
5973                 if (r_bloomstate.texture_screen)
5974                         R_FreeTexture(r_bloomstate.texture_screen);
5975                 r_bloomstate.texture_screen = NULL;
5976                 if (r_bloomstate.fbo_framebuffer)
5977                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5978                 r_bloomstate.fbo_framebuffer = 0;
5979                 if (r_bloomstate.texture_framebuffercolor)
5980                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5981                 r_bloomstate.texture_framebuffercolor = NULL;
5982                 if (r_bloomstate.texture_framebufferdepth)
5983                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5984                 r_bloomstate.texture_framebufferdepth = NULL;
5985                 r_bloomstate.screentexturewidth = screentexturewidth;
5986                 r_bloomstate.screentextureheight = screentextureheight;
5987                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5988                         r_bloomstate.texture_screen = R_LoadTexture2D(r_main_texturepool, "screen", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5989                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5990                 {
5991                         // FIXME: choose depth bits based on a cvar
5992                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5993                         r_bloomstate.texture_framebuffercolor = R_LoadTexture2D(r_main_texturepool, "framebuffercolor", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
5994                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5995                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5996                         // render depth into one texture and normalmap into the other
5997                         if (qglDrawBuffer)
5998                         {
5999                                 int status;
6000                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6001                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6002                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
6003                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
6004                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6005                         }
6006                 }
6007                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6008                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6009                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6010                         r_bloomstate.texture_bloom = R_LoadTexture2D(r_main_texturepool, "bloom", r_bloomstate.bloomtexturewidth, r_bloomstate.bloomtextureheight, NULL, textype, TEXF_RENDERTARGET | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
6011                 r_bloomstate.viewfbo = r_viewfbo.integer;
6012                 r_bloomstate.texturetype = textype;
6013         }
6014
6015         // when doing a reduced render (HDR) we want to use a smaller area
6016         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6017         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6018         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6019         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6020         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6021
6022         // set up a texcoord array for the full resolution screen image
6023         // (we have to keep this around to copy back during final render)
6024         r_bloomstate.screentexcoord2f[0] = 0;
6025         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6026         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6027         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6028         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6029         r_bloomstate.screentexcoord2f[5] = 0;
6030         r_bloomstate.screentexcoord2f[6] = 0;
6031         r_bloomstate.screentexcoord2f[7] = 0;
6032
6033         // set up a texcoord array for the reduced resolution bloom image
6034         // (which will be additive blended over the screen image)
6035         r_bloomstate.bloomtexcoord2f[0] = 0;
6036         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6037         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6038         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6039         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6040         r_bloomstate.bloomtexcoord2f[5] = 0;
6041         r_bloomstate.bloomtexcoord2f[6] = 0;
6042         r_bloomstate.bloomtexcoord2f[7] = 0;
6043
6044         switch(vid.renderpath)
6045         {
6046         case RENDERPATH_GL11:
6047         case RENDERPATH_GL13:
6048         case RENDERPATH_GL20:
6049         case RENDERPATH_SOFT:
6050         case RENDERPATH_GLES1:
6051         case RENDERPATH_GLES2:
6052                 break;
6053         case RENDERPATH_D3D9:
6054         case RENDERPATH_D3D10:
6055         case RENDERPATH_D3D11:
6056                 {
6057                         int i;
6058                         for (i = 0;i < 4;i++)
6059                         {
6060                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6061                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6062                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6063                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6064                         }
6065                 }
6066                 break;
6067         }
6068
6069         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6070         {
6071                 r_bloomstate.enabled = true;
6072                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6073         }
6074
6075         R_Viewport_InitOrtho(&r_bloomstate.viewport, &identitymatrix, r_refdef.view.x, vid.height - r_bloomstate.bloomheight - r_refdef.view.y, r_bloomstate.bloomwidth, r_bloomstate.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6076
6077         if (r_bloomstate.fbo_framebuffer)
6078                 r_refdef.view.clear = true;
6079 }
6080
6081 void R_Bloom_CopyBloomTexture(float colorscale)
6082 {
6083         r_refdef.stats.bloom++;
6084
6085         // scale down screen texture to the bloom texture size
6086         CHECKGLERROR
6087         R_Mesh_SetMainRenderTargets();
6088         R_SetViewport(&r_bloomstate.viewport);
6089         GL_BlendFunc(GL_ONE, GL_ZERO);
6090         GL_Color(colorscale, colorscale, colorscale, 1);
6091         // D3D has upside down Y coords, the easiest way to flip this is to flip the screen vertices rather than the texcoords, so we just use a different array for that...
6092         switch(vid.renderpath)
6093         {
6094         case RENDERPATH_GL11:
6095         case RENDERPATH_GL13:
6096         case RENDERPATH_GL20:
6097         case RENDERPATH_GLES1:
6098         case RENDERPATH_GLES2:
6099         case RENDERPATH_SOFT:
6100                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6101                 break;
6102         case RENDERPATH_D3D9:
6103         case RENDERPATH_D3D10:
6104         case RENDERPATH_D3D11:
6105                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6106                 break;
6107         }
6108         // TODO: do boxfilter scale-down in shader?
6109         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6110         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6111         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6112
6113         // we now have a bloom image in the framebuffer
6114         // copy it into the bloom image texture for later processing
6115         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6116         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6117 }
6118
6119 void R_Bloom_CopyHDRTexture(void)
6120 {
6121         R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
6122         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6123 }
6124
6125 void R_Bloom_MakeTexture(void)
6126 {
6127         int x, range, dir;
6128         float xoffset, yoffset, r, brighten;
6129
6130         r_refdef.stats.bloom++;
6131
6132         R_ResetViewRendering2D();
6133
6134         // we have a bloom image in the framebuffer
6135         CHECKGLERROR
6136         R_SetViewport(&r_bloomstate.viewport);
6137
6138         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6139         {
6140                 x *= 2;
6141                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6142                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6143                 GL_Color(r,r,r,1);
6144                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6145                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6146                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6147                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6148
6149                 // copy the vertically blurred bloom view to a texture
6150                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6151                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6152         }
6153
6154         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6155         brighten = r_bloom_brighten.value;
6156         if (r_bloomstate.hdr)
6157                 brighten *= r_hdr_range.value;
6158         brighten = sqrt(brighten);
6159         if(range >= 1)
6160                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6161         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6162
6163         for (dir = 0;dir < 2;dir++)
6164         {
6165                 // blend on at multiple vertical offsets to achieve a vertical blur
6166                 // TODO: do offset blends using GLSL
6167                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6168                 GL_BlendFunc(GL_ONE, GL_ZERO);
6169                 for (x = -range;x <= range;x++)
6170                 {
6171                         if (!dir){xoffset = 0;yoffset = x;}
6172                         else {xoffset = x;yoffset = 0;}
6173                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6174                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6175                         // compute a texcoord array with the specified x and y offset
6176                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6177                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6178                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6179                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6180                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6181                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6182                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6183                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6184                         // this r value looks like a 'dot' particle, fading sharply to
6185                         // black at the edges
6186                         // (probably not realistic but looks good enough)
6187                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6188                         //r = brighten/(range*2+1);
6189                         r = brighten / (range * 2 + 1);
6190                         if(range >= 1)
6191                                 r *= (1 - x*x/(float)(range*range));
6192                         GL_Color(r, r, r, 1);
6193                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6194                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6195                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6196                         GL_BlendFunc(GL_ONE, GL_ONE);
6197                 }
6198
6199                 // copy the vertically blurred bloom view to a texture
6200                 R_Mesh_CopyToTexture(r_bloomstate.texture_bloom, 0, 0, r_bloomstate.viewport.x, r_bloomstate.viewport.y, r_bloomstate.viewport.width, r_bloomstate.viewport.height);
6201                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6202         }
6203 }
6204
6205 void R_HDR_RenderBloomTexture(void)
6206 {
6207         int oldwidth, oldheight;
6208         float oldcolorscale;
6209         qboolean oldwaterstate;
6210
6211         oldwaterstate = r_waterstate.enabled;
6212         oldcolorscale = r_refdef.view.colorscale;
6213         oldwidth = r_refdef.view.width;
6214         oldheight = r_refdef.view.height;
6215         r_refdef.view.width = r_bloomstate.bloomwidth;
6216         r_refdef.view.height = r_bloomstate.bloomheight;
6217
6218         if(r_hdr.integer < 2)
6219                 r_waterstate.enabled = false;
6220
6221         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6222         // TODO: add exposure compensation features
6223         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6224
6225         r_refdef.view.showdebug = false;
6226         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6227
6228         R_ResetViewRendering3D();
6229
6230         R_ClearScreen(r_refdef.fogenabled);
6231         if (r_timereport_active)
6232                 R_TimeReport("HDRclear");
6233
6234         R_View_Update();
6235         if (r_timereport_active)
6236                 R_TimeReport("visibility");
6237
6238         // only do secondary renders with HDR if r_hdr is 2 or higher
6239         r_waterstate.numwaterplanes = 0;
6240         if (r_waterstate.enabled)
6241                 R_RenderWaterPlanes();
6242
6243         r_refdef.view.showdebug = true;
6244         R_RenderScene();
6245         r_waterstate.numwaterplanes = 0;
6246
6247         R_ResetViewRendering2D();
6248
6249         R_Bloom_CopyHDRTexture();
6250         R_Bloom_MakeTexture();
6251
6252         // restore the view settings
6253         r_waterstate.enabled = oldwaterstate;
6254         r_refdef.view.width = oldwidth;
6255         r_refdef.view.height = oldheight;
6256         r_refdef.view.colorscale = oldcolorscale;
6257
6258         R_ResetViewRendering3D();
6259
6260         R_ClearScreen(r_refdef.fogenabled);
6261         if (r_timereport_active)
6262                 R_TimeReport("viewclear");
6263 }
6264
6265 static void R_BlendView(void)
6266 {
6267         unsigned int permutation;
6268         float uservecs[4][4];
6269
6270         switch (vid.renderpath)
6271         {
6272         case RENDERPATH_GL20:
6273         case RENDERPATH_D3D9:
6274         case RENDERPATH_D3D10:
6275         case RENDERPATH_D3D11:
6276         case RENDERPATH_SOFT:
6277         case RENDERPATH_GLES2:
6278                 permutation =
6279                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6280                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6281                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6282                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6283                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6284
6285                 if (r_bloomstate.texture_screen)
6286                 {
6287                         // make sure the buffer is available
6288                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6289
6290                         R_ResetViewRendering2D();
6291                         R_Mesh_SetMainRenderTargets();
6292
6293                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6294                         {
6295                                 // declare variables
6296                                 float blur_factor, blur_mouseaccel, blur_velocity;
6297                                 static float blur_average; 
6298                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6299
6300                                 // set a goal for the factoring
6301                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value), 1);
6302                                 blur_mouseaccel = bound(0, (fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) - r_motionblur_vmin.value) / max(1, r_motionblur_vmax.value - r_motionblur_vmin.value), 1);
6303                                 blur_factor = (blur_velocity + blur_mouseaccel) * (1 - r_motionblur_bmin.value) + r_motionblur_bmin.value;
6304
6305                                 // from the goal, pick an averaged value between goal and last value
6306                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_vcoeff.value), 1);
6307                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6308
6309                                 // calculate values into a standard alpha
6310                                 cl.motionbluralpha = 1 - exp(-
6311                                                 (
6312                                                  (r_motionblur.value * blur_average / 80)
6313                                                  +
6314                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6315                                                 )
6316                                                 /
6317                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6318                                           );
6319
6320                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6321                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6322                                 
6323                                 // apply the blur
6324                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6325                                 {
6326                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6327                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6328                                         switch(vid.renderpath)
6329                                         {
6330                                         case RENDERPATH_GL11:
6331                                         case RENDERPATH_GL13:
6332                                         case RENDERPATH_GL20:
6333                                         case RENDERPATH_GLES1:
6334                                         case RENDERPATH_GLES2:
6335                                         case RENDERPATH_SOFT:
6336                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6337                                                 break;
6338                                         case RENDERPATH_D3D9:
6339                                         case RENDERPATH_D3D10:
6340                                         case RENDERPATH_D3D11:
6341                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6342                                                 break;
6343                                         }
6344                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6345                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6346                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6347                                 }
6348                                 
6349                                 // updates old view angles for next pass 
6350                                 VectorCopy(cl.viewangles, blur_oldangles);
6351                         }
6352
6353                         // copy view into the screen texture
6354                         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);
6355                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6356                 }
6357                 else if (!r_bloomstate.texture_bloom)
6358                 {
6359                         // we may still have to do view tint...
6360                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6361                         {
6362                                 // apply a color tint to the whole view
6363                                 R_ResetViewRendering2D();
6364                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6365                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6366                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6367                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6368                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6369                         }
6370                         break; // no screen processing, no bloom, skip it
6371                 }
6372
6373                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6374                 {
6375                         // render simple bloom effect
6376                         // copy the screen and shrink it and darken it for the bloom process
6377                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6378                         // make the bloom texture
6379                         R_Bloom_MakeTexture();
6380                 }
6381
6382 #if _MSC_VER >= 1400
6383 #define sscanf sscanf_s
6384 #endif
6385                 memset(uservecs, 0, sizeof(uservecs));
6386                 if (r_glsl_postprocess_uservec1_enable.integer)
6387                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6388                 if (r_glsl_postprocess_uservec2_enable.integer)
6389                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6390                 if (r_glsl_postprocess_uservec3_enable.integer)
6391                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6392                 if (r_glsl_postprocess_uservec4_enable.integer)
6393                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6394
6395                 R_ResetViewRendering2D();
6396                 GL_Color(1, 1, 1, 1);
6397                 GL_BlendFunc(GL_ONE, GL_ZERO);
6398
6399                 switch(vid.renderpath)
6400                 {
6401                 case RENDERPATH_GL20:
6402                 case RENDERPATH_GLES2:
6403                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6404                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6405                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6406                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6407                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6408                         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]);
6409                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6410                         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]);
6411                         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]);
6412                         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]);
6413                         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]);
6414                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6415                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6416                         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);
6417                         break;
6418                 case RENDERPATH_D3D9:
6419 #ifdef SUPPORTD3D
6420                         // 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...
6421                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6422                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6423                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6424                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6425                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6426                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6427                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6428                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6429                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6430                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6431                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6432                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6433                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6434                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6435 #endif
6436                         break;
6437                 case RENDERPATH_D3D10:
6438                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6439                         break;
6440                 case RENDERPATH_D3D11:
6441                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6442                         break;
6443                 case RENDERPATH_SOFT:
6444                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6445                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6446                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6447                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6448                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6449                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6450                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6451                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6452                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6453                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6454                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6455                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6456                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6457                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6458                         break;
6459                 default:
6460                         break;
6461                 }
6462                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6463                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6464                 break;
6465         case RENDERPATH_GL11:
6466         case RENDERPATH_GL13:
6467         case RENDERPATH_GLES1:
6468                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6469                 {
6470                         // apply a color tint to the whole view
6471                         R_ResetViewRendering2D();
6472                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6473                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6474                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6475                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6476                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6477                 }
6478                 break;
6479         }
6480 }
6481
6482 matrix4x4_t r_waterscrollmatrix;
6483
6484 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6485 {
6486         if (r_refdef.fog_density)
6487         {
6488                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6489                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6490                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6491
6492                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6493                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6494                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6495                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6496
6497                 {
6498                         vec3_t fogvec;
6499                         VectorCopy(r_refdef.fogcolor, fogvec);
6500                         //   color.rgb *= ContrastBoost * SceneBrightness;
6501                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6502                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6503                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6504                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6505                 }
6506         }
6507 }
6508
6509 void R_UpdateVariables(void)
6510 {
6511         R_Textures_Frame();
6512
6513         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6514
6515         r_refdef.farclip = r_farclip_base.value;
6516         if (r_refdef.scene.worldmodel)
6517                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6518         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6519
6520         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6521                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6522         r_refdef.polygonfactor = 0;
6523         r_refdef.polygonoffset = 0;
6524         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6525         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6526
6527         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6528         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6529         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6530         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6531         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6532         if (FAKELIGHT_ENABLED)
6533         {
6534                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6535         }
6536         if (r_showsurfaces.integer)
6537         {
6538                 r_refdef.scene.rtworld = false;
6539                 r_refdef.scene.rtworldshadows = false;
6540                 r_refdef.scene.rtdlight = false;
6541                 r_refdef.scene.rtdlightshadows = false;
6542                 r_refdef.lightmapintensity = 0;
6543         }
6544
6545         if (gamemode == GAME_NEHAHRA)
6546         {
6547                 if (gl_fogenable.integer)
6548                 {
6549                         r_refdef.oldgl_fogenable = true;
6550                         r_refdef.fog_density = gl_fogdensity.value;
6551                         r_refdef.fog_red = gl_fogred.value;
6552                         r_refdef.fog_green = gl_foggreen.value;
6553                         r_refdef.fog_blue = gl_fogblue.value;
6554                         r_refdef.fog_alpha = 1;
6555                         r_refdef.fog_start = 0;
6556                         r_refdef.fog_end = gl_skyclip.value;
6557                         r_refdef.fog_height = 1<<30;
6558                         r_refdef.fog_fadedepth = 128;
6559                 }
6560                 else if (r_refdef.oldgl_fogenable)
6561                 {
6562                         r_refdef.oldgl_fogenable = false;
6563                         r_refdef.fog_density = 0;
6564                         r_refdef.fog_red = 0;
6565                         r_refdef.fog_green = 0;
6566                         r_refdef.fog_blue = 0;
6567                         r_refdef.fog_alpha = 0;
6568                         r_refdef.fog_start = 0;
6569                         r_refdef.fog_end = 0;
6570                         r_refdef.fog_height = 1<<30;
6571                         r_refdef.fog_fadedepth = 128;
6572                 }
6573         }
6574
6575         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6576         r_refdef.fog_start = max(0, r_refdef.fog_start);
6577         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6578
6579         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6580
6581         if (r_refdef.fog_density && r_drawfog.integer)
6582         {
6583                 r_refdef.fogenabled = true;
6584                 // this is the point where the fog reaches 0.9986 alpha, which we
6585                 // consider a good enough cutoff point for the texture
6586                 // (0.9986 * 256 == 255.6)
6587                 if (r_fog_exp2.integer)
6588                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6589                 else
6590                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6591                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6592                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6593                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6594                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6595                         R_BuildFogHeightTexture();
6596                 // fog color was already set
6597                 // update the fog texture
6598                 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)
6599                         R_BuildFogTexture();
6600                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6601                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6602         }
6603         else
6604                 r_refdef.fogenabled = false;
6605
6606         switch(vid.renderpath)
6607         {
6608         case RENDERPATH_GL20:
6609         case RENDERPATH_D3D9:
6610         case RENDERPATH_D3D10:
6611         case RENDERPATH_D3D11:
6612         case RENDERPATH_SOFT:
6613         case RENDERPATH_GLES2:
6614                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6615                 {
6616                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6617                         {
6618                                 // build GLSL gamma texture
6619 #define RAMPWIDTH 256
6620                                 unsigned short ramp[RAMPWIDTH * 3];
6621                                 unsigned char rampbgr[RAMPWIDTH][4];
6622                                 int i;
6623
6624                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6625
6626                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6627                                 for(i = 0; i < RAMPWIDTH; ++i)
6628                                 {
6629                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6630                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6631                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6632                                         rampbgr[i][3] = 0;
6633                                 }
6634                                 if (r_texture_gammaramps)
6635                                 {
6636                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6637                                 }
6638                                 else
6639                                 {
6640                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6641                                 }
6642                         }
6643                 }
6644                 else
6645                 {
6646                         // remove GLSL gamma texture
6647                 }
6648                 break;
6649         case RENDERPATH_GL11:
6650         case RENDERPATH_GL13:
6651         case RENDERPATH_GLES1:
6652                 break;
6653         }
6654 }
6655
6656 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6657 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6658 /*
6659 ================
6660 R_SelectScene
6661 ================
6662 */
6663 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6664         if( scenetype != r_currentscenetype ) {
6665                 // store the old scenetype
6666                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6667                 r_currentscenetype = scenetype;
6668                 // move in the new scene
6669                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6670         }
6671 }
6672
6673 /*
6674 ================
6675 R_GetScenePointer
6676 ================
6677 */
6678 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6679 {
6680         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6681         if( scenetype == r_currentscenetype ) {
6682                 return &r_refdef.scene;
6683         } else {
6684                 return &r_scenes_store[ scenetype ];
6685         }
6686 }
6687
6688 /*
6689 ================
6690 R_RenderView
6691 ================
6692 */
6693 int dpsoftrast_test;
6694 extern void R_Shadow_UpdateBounceGridTexture(void);
6695 extern cvar_t r_shadow_bouncegrid;
6696 void R_RenderView(void)
6697 {
6698         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6699
6700         dpsoftrast_test = r_test.integer;
6701
6702         if (r_timereport_active)
6703                 R_TimeReport("start");
6704         r_textureframe++; // used only by R_GetCurrentTexture
6705         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6706
6707         if(R_CompileShader_CheckStaticParms())
6708                 R_GLSL_Restart_f();
6709
6710         if (!r_drawentities.integer)
6711                 r_refdef.scene.numentities = 0;
6712
6713         R_AnimCache_ClearCache();
6714         R_FrameData_NewFrame();
6715
6716         /* adjust for stereo display */
6717         if(R_Stereo_Active())
6718         {
6719                 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);
6720                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6721         }
6722
6723         if (r_refdef.view.isoverlay)
6724         {
6725                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6726                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6727                 R_TimeReport("depthclear");
6728
6729                 r_refdef.view.showdebug = false;
6730
6731                 r_waterstate.enabled = false;
6732                 r_waterstate.numwaterplanes = 0;
6733
6734                 R_RenderScene();
6735
6736                 r_refdef.view.matrix = originalmatrix;
6737
6738                 CHECKGLERROR
6739                 return;
6740         }
6741
6742         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6743         {
6744                 r_refdef.view.matrix = originalmatrix;
6745                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6746         }
6747
6748         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6749
6750         R_RenderView_UpdateViewVectors();
6751
6752         R_Shadow_UpdateWorldLightSelection();
6753
6754         R_Bloom_StartFrame();
6755         R_Water_StartFrame();
6756
6757         CHECKGLERROR
6758         if (r_timereport_active)
6759                 R_TimeReport("viewsetup");
6760
6761         R_ResetViewRendering3D();
6762
6763         if (r_refdef.view.clear || r_refdef.fogenabled)
6764         {
6765                 R_ClearScreen(r_refdef.fogenabled);
6766                 if (r_timereport_active)
6767                         R_TimeReport("viewclear");
6768         }
6769         r_refdef.view.clear = true;
6770
6771         // this produces a bloom texture to be used in R_BlendView() later
6772         if (r_bloomstate.hdr)
6773         {
6774                 R_HDR_RenderBloomTexture();
6775                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6776                 r_textureframe++; // used only by R_GetCurrentTexture
6777         }
6778
6779         r_refdef.view.showdebug = true;
6780
6781         R_View_Update();
6782         if (r_timereport_active)
6783                 R_TimeReport("visibility");
6784
6785         R_Shadow_UpdateBounceGridTexture();
6786         if (r_timereport_active && r_shadow_bouncegrid.integer)
6787                 R_TimeReport("bouncegrid");
6788
6789         r_waterstate.numwaterplanes = 0;
6790         if (r_waterstate.enabled)
6791                 R_RenderWaterPlanes();
6792
6793         R_RenderScene();
6794         r_waterstate.numwaterplanes = 0;
6795
6796         R_BlendView();
6797         if (r_timereport_active)
6798                 R_TimeReport("blendview");
6799
6800         GL_Scissor(0, 0, vid.width, vid.height);
6801         GL_ScissorTest(false);
6802
6803         r_refdef.view.matrix = originalmatrix;
6804
6805         CHECKGLERROR
6806 }
6807
6808 void R_RenderWaterPlanes(void)
6809 {
6810         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6811         {
6812                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6813                 if (r_timereport_active)
6814                         R_TimeReport("waterworld");
6815         }
6816
6817         // don't let sound skip if going slow
6818         if (r_refdef.scene.extraupdate)
6819                 S_ExtraUpdate ();
6820
6821         R_DrawModelsAddWaterPlanes();
6822         if (r_timereport_active)
6823                 R_TimeReport("watermodels");
6824
6825         if (r_waterstate.numwaterplanes)
6826         {
6827                 R_Water_ProcessPlanes();
6828                 if (r_timereport_active)
6829                         R_TimeReport("waterscenes");
6830         }
6831 }
6832
6833 extern void R_DrawLightningBeams (void);
6834 extern void VM_CL_AddPolygonsToMeshQueue (void);
6835 extern void R_DrawPortals (void);
6836 extern cvar_t cl_locs_show;
6837 static void R_DrawLocs(void);
6838 static void R_DrawEntityBBoxes(void);
6839 static void R_DrawModelDecals(void);
6840 extern void R_DrawModelShadows(void);
6841 extern void R_DrawModelShadowMaps(void);
6842 extern cvar_t cl_decals_newsystem;
6843 extern qboolean r_shadow_usingdeferredprepass;
6844 void R_RenderScene(void)
6845 {
6846         qboolean shadowmapping = false;
6847
6848         if (r_timereport_active)
6849                 R_TimeReport("beginscene");
6850
6851         r_refdef.stats.renders++;
6852
6853         R_UpdateFogColor();
6854
6855         // don't let sound skip if going slow
6856         if (r_refdef.scene.extraupdate)
6857                 S_ExtraUpdate ();
6858
6859         R_MeshQueue_BeginScene();
6860
6861         R_SkyStartFrame();
6862
6863         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);
6864
6865         if (r_timereport_active)
6866                 R_TimeReport("skystartframe");
6867
6868         if (cl.csqc_vidvars.drawworld)
6869         {
6870                 // don't let sound skip if going slow
6871                 if (r_refdef.scene.extraupdate)
6872                         S_ExtraUpdate ();
6873
6874                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6875                 {
6876                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6877                         if (r_timereport_active)
6878                                 R_TimeReport("worldsky");
6879                 }
6880
6881                 if (R_DrawBrushModelsSky() && r_timereport_active)
6882                         R_TimeReport("bmodelsky");
6883
6884                 if (skyrendermasked && skyrenderlater)
6885                 {
6886                         // we have to force off the water clipping plane while rendering sky
6887                         R_SetupView(false);
6888                         R_Sky();
6889                         R_SetupView(true);
6890                         if (r_timereport_active)
6891                                 R_TimeReport("sky");
6892                 }
6893         }
6894
6895         R_AnimCache_CacheVisibleEntities();
6896         if (r_timereport_active)
6897                 R_TimeReport("animation");
6898
6899         R_Shadow_PrepareLights();
6900         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6901                 R_Shadow_PrepareModelShadows();
6902         if (r_timereport_active)
6903                 R_TimeReport("preparelights");
6904
6905         if (R_Shadow_ShadowMappingEnabled())
6906                 shadowmapping = true;
6907
6908         if (r_shadow_usingdeferredprepass)
6909                 R_Shadow_DrawPrepass();
6910
6911         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6912         {
6913                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6914                 if (r_timereport_active)
6915                         R_TimeReport("worlddepth");
6916         }
6917         if (r_depthfirst.integer >= 2)
6918         {
6919                 R_DrawModelsDepth();
6920                 if (r_timereport_active)
6921                         R_TimeReport("modeldepth");
6922         }
6923
6924         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6925         {
6926                 R_DrawModelShadowMaps();
6927                 R_ResetViewRendering3D();
6928                 // don't let sound skip if going slow
6929                 if (r_refdef.scene.extraupdate)
6930                         S_ExtraUpdate ();
6931         }
6932
6933         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6934         {
6935                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6936                 if (r_timereport_active)
6937                         R_TimeReport("world");
6938         }
6939
6940         // don't let sound skip if going slow
6941         if (r_refdef.scene.extraupdate)
6942                 S_ExtraUpdate ();
6943
6944         R_DrawModels();
6945         if (r_timereport_active)
6946                 R_TimeReport("models");
6947
6948         // don't let sound skip if going slow
6949         if (r_refdef.scene.extraupdate)
6950                 S_ExtraUpdate ();
6951
6952         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6953         {
6954                 R_DrawModelShadows();
6955                 R_ResetViewRendering3D();
6956                 // don't let sound skip if going slow
6957                 if (r_refdef.scene.extraupdate)
6958                         S_ExtraUpdate ();
6959         }
6960
6961         if (!r_shadow_usingdeferredprepass)
6962         {
6963                 R_Shadow_DrawLights();
6964                 if (r_timereport_active)
6965                         R_TimeReport("rtlights");
6966         }
6967
6968         // don't let sound skip if going slow
6969         if (r_refdef.scene.extraupdate)
6970                 S_ExtraUpdate ();
6971
6972         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6973         {
6974                 R_DrawModelShadows();
6975                 R_ResetViewRendering3D();
6976                 // don't let sound skip if going slow
6977                 if (r_refdef.scene.extraupdate)
6978                         S_ExtraUpdate ();
6979         }
6980
6981         if (cl.csqc_vidvars.drawworld)
6982         {
6983                 if (cl_decals_newsystem.integer)
6984                 {
6985                         R_DrawModelDecals();
6986                         if (r_timereport_active)
6987                                 R_TimeReport("modeldecals");
6988                 }
6989                 else
6990                 {
6991                         R_DrawDecals();
6992                         if (r_timereport_active)
6993                                 R_TimeReport("decals");
6994                 }
6995
6996                 R_DrawParticles();
6997                 if (r_timereport_active)
6998                         R_TimeReport("particles");
6999
7000                 R_DrawExplosions();
7001                 if (r_timereport_active)
7002                         R_TimeReport("explosions");
7003
7004                 R_DrawLightningBeams();
7005                 if (r_timereport_active)
7006                         R_TimeReport("lightning");
7007         }
7008
7009         VM_CL_AddPolygonsToMeshQueue();
7010
7011         if (r_refdef.view.showdebug)
7012         {
7013                 if (cl_locs_show.integer)
7014                 {
7015                         R_DrawLocs();
7016                         if (r_timereport_active)
7017                                 R_TimeReport("showlocs");
7018                 }
7019
7020                 if (r_drawportals.integer)
7021                 {
7022                         R_DrawPortals();
7023                         if (r_timereport_active)
7024                                 R_TimeReport("portals");
7025                 }
7026
7027                 if (r_showbboxes.value > 0)
7028                 {
7029                         R_DrawEntityBBoxes();
7030                         if (r_timereport_active)
7031                                 R_TimeReport("bboxes");
7032                 }
7033         }
7034
7035         if (r_transparent.integer)
7036         {
7037                 R_MeshQueue_RenderTransparent();
7038                 if (r_timereport_active)
7039                         R_TimeReport("drawtrans");
7040         }
7041
7042         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))
7043         {
7044                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7045                 if (r_timereport_active)
7046                         R_TimeReport("worlddebug");
7047                 R_DrawModelsDebug();
7048                 if (r_timereport_active)
7049                         R_TimeReport("modeldebug");
7050         }
7051
7052         if (cl.csqc_vidvars.drawworld)
7053         {
7054                 R_Shadow_DrawCoronas();
7055                 if (r_timereport_active)
7056                         R_TimeReport("coronas");
7057         }
7058
7059 #if 0
7060         {
7061                 GL_DepthTest(false);
7062                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7063                 GL_Color(1, 1, 1, 1);
7064                 qglBegin(GL_POLYGON);
7065                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7066                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7067                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7068                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7069                 qglEnd();
7070                 qglBegin(GL_POLYGON);
7071                 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]);
7072                 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]);
7073                 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]);
7074                 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]);
7075                 qglEnd();
7076                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7077         }
7078 #endif
7079
7080         // don't let sound skip if going slow
7081         if (r_refdef.scene.extraupdate)
7082                 S_ExtraUpdate ();
7083
7084         R_ResetViewRendering2D();
7085 }
7086
7087 static const unsigned short bboxelements[36] =
7088 {
7089         5, 1, 3, 5, 3, 7,
7090         6, 2, 0, 6, 0, 4,
7091         7, 3, 2, 7, 2, 6,
7092         4, 0, 1, 4, 1, 5,
7093         4, 5, 7, 4, 7, 6,
7094         1, 0, 2, 1, 2, 3,
7095 };
7096
7097 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7098 {
7099         int i;
7100         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7101
7102         RSurf_ActiveWorldEntity();
7103
7104         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7105         GL_DepthMask(false);
7106         GL_DepthRange(0, 1);
7107         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7108 //      R_Mesh_ResetTextureState();
7109
7110         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7111         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7112         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7113         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7114         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7115         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7116         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7117         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7118         R_FillColors(color4f, 8, cr, cg, cb, ca);
7119         if (r_refdef.fogenabled)
7120         {
7121                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7122                 {
7123                         f1 = RSurf_FogVertex(v);
7124                         f2 = 1 - f1;
7125                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7126                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7127                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7128                 }
7129         }
7130         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7131         R_Mesh_ResetTextureState();
7132         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7133         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7134 }
7135
7136 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7137 {
7138         int i;
7139         float color[4];
7140         prvm_edict_t *edict;
7141         prvm_prog_t *prog_save = prog;
7142
7143         // this function draws bounding boxes of server entities
7144         if (!sv.active)
7145                 return;
7146
7147         GL_CullFace(GL_NONE);
7148         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7149
7150         prog = 0;
7151         SV_VM_Begin();
7152         for (i = 0;i < numsurfaces;i++)
7153         {
7154                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7155                 switch ((int)PRVM_serveredictfloat(edict, solid))
7156                 {
7157                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7158                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7159                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7160                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7161                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7162                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7163                 }
7164                 color[3] *= r_showbboxes.value;
7165                 color[3] = bound(0, color[3], 1);
7166                 GL_DepthTest(!r_showdisabledepthtest.integer);
7167                 GL_CullFace(r_refdef.view.cullface_front);
7168                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7169         }
7170         SV_VM_End();
7171         prog = prog_save;
7172 }
7173
7174 static void R_DrawEntityBBoxes(void)
7175 {
7176         int i;
7177         prvm_edict_t *edict;
7178         vec3_t center;
7179         prvm_prog_t *prog_save = prog;
7180
7181         // this function draws bounding boxes of server entities
7182         if (!sv.active)
7183                 return;
7184
7185         prog = 0;
7186         SV_VM_Begin();
7187         for (i = 0;i < prog->num_edicts;i++)
7188         {
7189                 edict = PRVM_EDICT_NUM(i);
7190                 if (edict->priv.server->free)
7191                         continue;
7192                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7193                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7194                         continue;
7195                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7196                         continue;
7197                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7198                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7199         }
7200         SV_VM_End();
7201         prog = prog_save;
7202 }
7203
7204 static const int nomodelelement3i[24] =
7205 {
7206         5, 2, 0,
7207         5, 1, 2,
7208         5, 0, 3,
7209         5, 3, 1,
7210         0, 2, 4,
7211         2, 1, 4,
7212         3, 0, 4,
7213         1, 3, 4
7214 };
7215
7216 static const unsigned short nomodelelement3s[24] =
7217 {
7218         5, 2, 0,
7219         5, 1, 2,
7220         5, 0, 3,
7221         5, 3, 1,
7222         0, 2, 4,
7223         2, 1, 4,
7224         3, 0, 4,
7225         1, 3, 4
7226 };
7227
7228 static const float nomodelvertex3f[6*3] =
7229 {
7230         -16,   0,   0,
7231          16,   0,   0,
7232           0, -16,   0,
7233           0,  16,   0,
7234           0,   0, -16,
7235           0,   0,  16
7236 };
7237
7238 static const float nomodelcolor4f[6*4] =
7239 {
7240         0.0f, 0.0f, 0.5f, 1.0f,
7241         0.0f, 0.0f, 0.5f, 1.0f,
7242         0.0f, 0.5f, 0.0f, 1.0f,
7243         0.0f, 0.5f, 0.0f, 1.0f,
7244         0.5f, 0.0f, 0.0f, 1.0f,
7245         0.5f, 0.0f, 0.0f, 1.0f
7246 };
7247
7248 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7249 {
7250         int i;
7251         float f1, f2, *c;
7252         float color4f[6*4];
7253
7254         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);
7255
7256         // this is only called once per entity so numsurfaces is always 1, and
7257         // surfacelist is always {0}, so this code does not handle batches
7258
7259         if (rsurface.ent_flags & RENDER_ADDITIVE)
7260         {
7261                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7262                 GL_DepthMask(false);
7263         }
7264         else if (rsurface.colormod[3] < 1)
7265         {
7266                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7267                 GL_DepthMask(false);
7268         }
7269         else
7270         {
7271                 GL_BlendFunc(GL_ONE, GL_ZERO);
7272                 GL_DepthMask(true);
7273         }
7274         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7275         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7276         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7277         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7278         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7279         for (i = 0, c = color4f;i < 6;i++, c += 4)
7280         {
7281                 c[0] *= rsurface.colormod[0];
7282                 c[1] *= rsurface.colormod[1];
7283                 c[2] *= rsurface.colormod[2];
7284                 c[3] *= rsurface.colormod[3];
7285         }
7286         if (r_refdef.fogenabled)
7287         {
7288                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7289                 {
7290                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7291                         f2 = 1 - f1;
7292                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7293                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7294                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7295                 }
7296         }
7297 //      R_Mesh_ResetTextureState();
7298         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7299         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7300         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7301 }
7302
7303 void R_DrawNoModel(entity_render_t *ent)
7304 {
7305         vec3_t org;
7306         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7307         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7308                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7309         else
7310                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7311 }
7312
7313 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7314 {
7315         vec3_t right1, right2, diff, normal;
7316
7317         VectorSubtract (org2, org1, normal);
7318
7319         // calculate 'right' vector for start
7320         VectorSubtract (r_refdef.view.origin, org1, diff);
7321         CrossProduct (normal, diff, right1);
7322         VectorNormalize (right1);
7323
7324         // calculate 'right' vector for end
7325         VectorSubtract (r_refdef.view.origin, org2, diff);
7326         CrossProduct (normal, diff, right2);
7327         VectorNormalize (right2);
7328
7329         vert[ 0] = org1[0] + width * right1[0];
7330         vert[ 1] = org1[1] + width * right1[1];
7331         vert[ 2] = org1[2] + width * right1[2];
7332         vert[ 3] = org1[0] - width * right1[0];
7333         vert[ 4] = org1[1] - width * right1[1];
7334         vert[ 5] = org1[2] - width * right1[2];
7335         vert[ 6] = org2[0] - width * right2[0];
7336         vert[ 7] = org2[1] - width * right2[1];
7337         vert[ 8] = org2[2] - width * right2[2];
7338         vert[ 9] = org2[0] + width * right2[0];
7339         vert[10] = org2[1] + width * right2[1];
7340         vert[11] = org2[2] + width * right2[2];
7341 }
7342
7343 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)
7344 {
7345         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7346         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7347         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7348         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7349         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7350         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7351         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7352         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7353         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7354         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7355         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7356         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7357 }
7358
7359 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7360 {
7361         int i;
7362         float *vertex3f;
7363         float v[3];
7364         VectorSet(v, x, y, z);
7365         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7366                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7367                         break;
7368         if (i == mesh->numvertices)
7369         {
7370                 if (mesh->numvertices < mesh->maxvertices)
7371                 {
7372                         VectorCopy(v, vertex3f);
7373                         mesh->numvertices++;
7374                 }
7375                 return mesh->numvertices;
7376         }
7377         else
7378                 return i;
7379 }
7380
7381 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7382 {
7383         int i;
7384         int *e, element[3];
7385         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7386         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7387         e = mesh->element3i + mesh->numtriangles * 3;
7388         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7389         {
7390                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7391                 if (mesh->numtriangles < mesh->maxtriangles)
7392                 {
7393                         *e++ = element[0];
7394                         *e++ = element[1];
7395                         *e++ = element[2];
7396                         mesh->numtriangles++;
7397                 }
7398                 element[1] = element[2];
7399         }
7400 }
7401
7402 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7403 {
7404         int i;
7405         int *e, element[3];
7406         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7407         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7408         e = mesh->element3i + mesh->numtriangles * 3;
7409         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7410         {
7411                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7412                 if (mesh->numtriangles < mesh->maxtriangles)
7413                 {
7414                         *e++ = element[0];
7415                         *e++ = element[1];
7416                         *e++ = element[2];
7417                         mesh->numtriangles++;
7418                 }
7419                 element[1] = element[2];
7420         }
7421 }
7422
7423 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7424 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7425 {
7426         int planenum, planenum2;
7427         int w;
7428         int tempnumpoints;
7429         mplane_t *plane, *plane2;
7430         double maxdist;
7431         double temppoints[2][256*3];
7432         // figure out how large a bounding box we need to properly compute this brush
7433         maxdist = 0;
7434         for (w = 0;w < numplanes;w++)
7435                 maxdist = max(maxdist, fabs(planes[w].dist));
7436         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7437         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7438         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7439         {
7440                 w = 0;
7441                 tempnumpoints = 4;
7442                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7443                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7444                 {
7445                         if (planenum2 == planenum)
7446                                 continue;
7447                         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);
7448                         w = !w;
7449                 }
7450                 if (tempnumpoints < 3)
7451                         continue;
7452                 // generate elements forming a triangle fan for this polygon
7453                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7454         }
7455 }
7456
7457 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)
7458 {
7459         texturelayer_t *layer;
7460         layer = t->currentlayers + t->currentnumlayers++;
7461         layer->type = type;
7462         layer->depthmask = depthmask;
7463         layer->blendfunc1 = blendfunc1;
7464         layer->blendfunc2 = blendfunc2;
7465         layer->texture = texture;
7466         layer->texmatrix = *matrix;
7467         layer->color[0] = r;
7468         layer->color[1] = g;
7469         layer->color[2] = b;
7470         layer->color[3] = a;
7471 }
7472
7473 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7474 {
7475         if(parms[0] == 0 && parms[1] == 0)
7476                 return false;
7477         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7478                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7479                         return false;
7480         return true;
7481 }
7482
7483 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7484 {
7485         double index, f;
7486         index = parms[2] + rsurface.shadertime * parms[3];
7487         index -= floor(index);
7488         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7489         {
7490         default:
7491         case Q3WAVEFUNC_NONE:
7492         case Q3WAVEFUNC_NOISE:
7493         case Q3WAVEFUNC_COUNT:
7494                 f = 0;
7495                 break;
7496         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7497         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7498         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7499         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7500         case Q3WAVEFUNC_TRIANGLE:
7501                 index *= 4;
7502                 f = index - floor(index);
7503                 if (index < 1)
7504                 {
7505                         // f = f;
7506                 }
7507                 else if (index < 2)
7508                         f = 1 - f;
7509                 else if (index < 3)
7510                         f = -f;
7511                 else
7512                         f = -(1 - f);
7513                 break;
7514         }
7515         f = parms[0] + parms[1] * f;
7516         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7517                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7518         return (float) f;
7519 }
7520
7521 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7522 {
7523         int w, h, idx;
7524         double f;
7525         double offsetd[2];
7526         float tcmat[12];
7527         matrix4x4_t matrix, temp;
7528         switch(tcmod->tcmod)
7529         {
7530                 case Q3TCMOD_COUNT:
7531                 case Q3TCMOD_NONE:
7532                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7533                                 matrix = r_waterscrollmatrix;
7534                         else
7535                                 matrix = identitymatrix;
7536                         break;
7537                 case Q3TCMOD_ENTITYTRANSLATE:
7538                         // this is used in Q3 to allow the gamecode to control texcoord
7539                         // scrolling on the entity, which is not supported in darkplaces yet.
7540                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7541                         break;
7542                 case Q3TCMOD_ROTATE:
7543                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7544                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7545                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7546                         break;
7547                 case Q3TCMOD_SCALE:
7548                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7549                         break;
7550                 case Q3TCMOD_SCROLL:
7551                         // extra care is needed because of precision breakdown with large values of time
7552                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7553                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7554                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7555                         break;
7556                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7557                         w = (int) tcmod->parms[0];
7558                         h = (int) tcmod->parms[1];
7559                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7560                         f = f - floor(f);
7561                         idx = (int) floor(f * w * h);
7562                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7563                         break;
7564                 case Q3TCMOD_STRETCH:
7565                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7566                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7567                         break;
7568                 case Q3TCMOD_TRANSFORM:
7569                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7570                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7571                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7572                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7573                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7574                         break;
7575                 case Q3TCMOD_TURBULENT:
7576                         // this is handled in the RSurf_PrepareVertices function
7577                         matrix = identitymatrix;
7578                         break;
7579         }
7580         temp = *texmatrix;
7581         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7582 }
7583
7584 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7585 {
7586         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7587         char name[MAX_QPATH];
7588         skinframe_t *skinframe;
7589         unsigned char pixels[296*194];
7590         strlcpy(cache->name, skinname, sizeof(cache->name));
7591         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7592         if (developer_loading.integer)
7593                 Con_Printf("loading %s\n", name);
7594         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7595         if (!skinframe || !skinframe->base)
7596         {
7597                 unsigned char *f;
7598                 fs_offset_t filesize;
7599                 skinframe = NULL;
7600                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7601                 if (f)
7602                 {
7603                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7604                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7605                         Mem_Free(f);
7606                 }
7607         }
7608         cache->skinframe = skinframe;
7609 }
7610
7611 texture_t *R_GetCurrentTexture(texture_t *t)
7612 {
7613         int i;
7614         const entity_render_t *ent = rsurface.entity;
7615         dp_model_t *model = ent->model;
7616         q3shaderinfo_layer_tcmod_t *tcmod;
7617
7618         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7619                 return t->currentframe;
7620         t->update_lastrenderframe = r_textureframe;
7621         t->update_lastrenderentity = (void *)ent;
7622
7623         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7624                 t->camera_entity = ent->entitynumber;
7625         else
7626                 t->camera_entity = 0;
7627
7628         // switch to an alternate material if this is a q1bsp animated material
7629         {
7630                 texture_t *texture = t;
7631                 int s = rsurface.ent_skinnum;
7632                 if ((unsigned int)s >= (unsigned int)model->numskins)
7633                         s = 0;
7634                 if (model->skinscenes)
7635                 {
7636                         if (model->skinscenes[s].framecount > 1)
7637                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7638                         else
7639                                 s = model->skinscenes[s].firstframe;
7640                 }
7641                 if (s > 0)
7642                         t = t + s * model->num_surfaces;
7643                 if (t->animated)
7644                 {
7645                         // use an alternate animation if the entity's frame is not 0,
7646                         // and only if the texture has an alternate animation
7647                         if (rsurface.ent_alttextures && t->anim_total[1])
7648                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7649                         else
7650                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7651                 }
7652                 texture->currentframe = t;
7653         }
7654
7655         // update currentskinframe to be a qw skin or animation frame
7656         if (rsurface.ent_qwskin >= 0)
7657         {
7658                 i = rsurface.ent_qwskin;
7659                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7660                 {
7661                         r_qwskincache_size = cl.maxclients;
7662                         if (r_qwskincache)
7663                                 Mem_Free(r_qwskincache);
7664                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7665                 }
7666                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7667                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7668                 t->currentskinframe = r_qwskincache[i].skinframe;
7669                 if (t->currentskinframe == NULL)
7670                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7671         }
7672         else if (t->numskinframes >= 2)
7673                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7674         if (t->backgroundnumskinframes >= 2)
7675                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7676
7677         t->currentmaterialflags = t->basematerialflags;
7678         t->currentalpha = rsurface.colormod[3];
7679         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7680                 t->currentalpha *= r_wateralpha.value;
7681         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7682                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7683         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7684                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7685         if (!(rsurface.ent_flags & RENDER_LIGHT))
7686                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7687         else if (FAKELIGHT_ENABLED)
7688         {
7689                 // no modellight if using fakelight for the map
7690         }
7691         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7692         {
7693                 // pick a model lighting mode
7694                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7695                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7696                 else
7697                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7698         }
7699         if (rsurface.ent_flags & RENDER_ADDITIVE)
7700                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7701         else if (t->currentalpha < 1)
7702                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7703         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7704                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7705         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7706                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7707         if (t->backgroundnumskinframes)
7708                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7709         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7710         {
7711                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7712                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7713         }
7714         else
7715                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7716         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7717         {
7718                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7719                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7720         }
7721         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7722                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7723
7724         // there is no tcmod
7725         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7726         {
7727                 t->currenttexmatrix = r_waterscrollmatrix;
7728                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7729         }
7730         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7731         {
7732                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7733                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7734         }
7735
7736         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7737                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7738         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7739                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7740
7741         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7742         if (t->currentskinframe->qpixels)
7743                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7744         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7745         if (!t->basetexture)
7746                 t->basetexture = r_texture_notexture;
7747         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7748         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7749         t->nmaptexture = t->currentskinframe->nmap;
7750         if (!t->nmaptexture)
7751                 t->nmaptexture = r_texture_blanknormalmap;
7752         t->glosstexture = r_texture_black;
7753         t->glowtexture = t->currentskinframe->glow;
7754         t->fogtexture = t->currentskinframe->fog;
7755         t->reflectmasktexture = t->currentskinframe->reflect;
7756         if (t->backgroundnumskinframes)
7757         {
7758                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7759                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7760                 t->backgroundglosstexture = r_texture_black;
7761                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7762                 if (!t->backgroundnmaptexture)
7763                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7764         }
7765         else
7766         {
7767                 t->backgroundbasetexture = r_texture_white;
7768                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7769                 t->backgroundglosstexture = r_texture_black;
7770                 t->backgroundglowtexture = NULL;
7771         }
7772         t->specularpower = r_shadow_glossexponent.value;
7773         // TODO: store reference values for these in the texture?
7774         t->specularscale = 0;
7775         if (r_shadow_gloss.integer > 0)
7776         {
7777                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7778                 {
7779                         if (r_shadow_glossintensity.value > 0)
7780                         {
7781                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7782                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7783                                 t->specularscale = r_shadow_glossintensity.value;
7784                         }
7785                 }
7786                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7787                 {
7788                         t->glosstexture = r_texture_white;
7789                         t->backgroundglosstexture = r_texture_white;
7790                         t->specularscale = r_shadow_gloss2intensity.value;
7791                         t->specularpower = r_shadow_gloss2exponent.value;
7792                 }
7793         }
7794         t->specularscale *= t->specularscalemod;
7795         t->specularpower *= t->specularpowermod;
7796
7797         // lightmaps mode looks bad with dlights using actual texturing, so turn
7798         // off the colormap and glossmap, but leave the normalmap on as it still
7799         // accurately represents the shading involved
7800         if (gl_lightmaps.integer)
7801         {
7802                 t->basetexture = r_texture_grey128;
7803                 t->pantstexture = r_texture_black;
7804                 t->shirttexture = r_texture_black;
7805                 t->nmaptexture = r_texture_blanknormalmap;
7806                 t->glosstexture = r_texture_black;
7807                 t->glowtexture = NULL;
7808                 t->fogtexture = NULL;
7809                 t->reflectmasktexture = NULL;
7810                 t->backgroundbasetexture = NULL;
7811                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7812                 t->backgroundglosstexture = r_texture_black;
7813                 t->backgroundglowtexture = NULL;
7814                 t->specularscale = 0;
7815                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7816         }
7817
7818         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7819         VectorClear(t->dlightcolor);
7820         t->currentnumlayers = 0;
7821         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7822         {
7823                 int blendfunc1, blendfunc2;
7824                 qboolean depthmask;
7825                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7826                 {
7827                         blendfunc1 = GL_SRC_ALPHA;
7828                         blendfunc2 = GL_ONE;
7829                 }
7830                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7831                 {
7832                         blendfunc1 = GL_SRC_ALPHA;
7833                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7834                 }
7835                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7836                 {
7837                         blendfunc1 = t->customblendfunc[0];
7838                         blendfunc2 = t->customblendfunc[1];
7839                 }
7840                 else
7841                 {
7842                         blendfunc1 = GL_ONE;
7843                         blendfunc2 = GL_ZERO;
7844                 }
7845                 // don't colormod evilblend textures
7846                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7847                         VectorSet(t->lightmapcolor, 1, 1, 1);
7848                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7849                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7850                 {
7851                         // fullbright is not affected by r_refdef.lightmapintensity
7852                         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]);
7853                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7854                                 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]);
7855                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7856                                 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]);
7857                 }
7858                 else
7859                 {
7860                         vec3_t ambientcolor;
7861                         float colorscale;
7862                         // set the color tint used for lights affecting this surface
7863                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7864                         colorscale = 2;
7865                         // q3bsp has no lightmap updates, so the lightstylevalue that
7866                         // would normally be baked into the lightmap must be
7867                         // applied to the color
7868                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7869                         if (model->type == mod_brushq3)
7870                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7871                         colorscale *= r_refdef.lightmapintensity;
7872                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7873                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7874                         // basic lit geometry
7875                         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]);
7876                         // add pants/shirt if needed
7877                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7878                                 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]);
7879                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7880                                 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]);
7881                         // now add ambient passes if needed
7882                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7883                         {
7884                                 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]);
7885                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7886                                         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]);
7887                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7888                                         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]);
7889                         }
7890                 }
7891                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7892                         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]);
7893                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7894                 {
7895                         // if this is opaque use alpha blend which will darken the earlier
7896                         // passes cheaply.
7897                         //
7898                         // if this is an alpha blended material, all the earlier passes
7899                         // were darkened by fog already, so we only need to add the fog
7900                         // color ontop through the fog mask texture
7901                         //
7902                         // if this is an additive blended material, all the earlier passes
7903                         // were darkened by fog already, and we should not add fog color
7904                         // (because the background was not darkened, there is no fog color
7905                         // that was lost behind it).
7906                         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]);
7907                 }
7908         }
7909
7910         return t->currentframe;
7911 }
7912
7913 rsurfacestate_t rsurface;
7914
7915 void RSurf_ActiveWorldEntity(void)
7916 {
7917         dp_model_t *model = r_refdef.scene.worldmodel;
7918         //if (rsurface.entity == r_refdef.scene.worldentity)
7919         //      return;
7920         rsurface.entity = r_refdef.scene.worldentity;
7921         rsurface.skeleton = NULL;
7922         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7923         rsurface.ent_skinnum = 0;
7924         rsurface.ent_qwskin = -1;
7925         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7926         rsurface.shadertime = r_refdef.scene.time;
7927         rsurface.matrix = identitymatrix;
7928         rsurface.inversematrix = identitymatrix;
7929         rsurface.matrixscale = 1;
7930         rsurface.inversematrixscale = 1;
7931         R_EntityMatrix(&identitymatrix);
7932         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7933         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7934         rsurface.fograngerecip = r_refdef.fograngerecip;
7935         rsurface.fogheightfade = r_refdef.fogheightfade;
7936         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7937         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7938         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7939         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7940         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7941         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7942         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7943         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7944         rsurface.colormod[3] = 1;
7945         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);
7946         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7947         rsurface.frameblend[0].lerp = 1;
7948         rsurface.ent_alttextures = false;
7949         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7950         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7951         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7952         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7953         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7954         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7955         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7956         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7957         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7958         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7959         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7960         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7961         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7962         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7963         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7964         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7965         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7966         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7967         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7968         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7969         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7970         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7971         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7972         rsurface.modelelement3i = model->surfmesh.data_element3i;
7973         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7974         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7975         rsurface.modelelement3s = model->surfmesh.data_element3s;
7976         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7977         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7978         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7979         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7980         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7981         rsurface.modelsurfaces = model->data_surfaces;
7982         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7983         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7984         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
7985         rsurface.modelgeneratedvertex = false;
7986         rsurface.batchgeneratedvertex = false;
7987         rsurface.batchfirstvertex = 0;
7988         rsurface.batchnumvertices = 0;
7989         rsurface.batchfirsttriangle = 0;
7990         rsurface.batchnumtriangles = 0;
7991         rsurface.batchvertex3f  = NULL;
7992         rsurface.batchvertex3f_vertexbuffer = NULL;
7993         rsurface.batchvertex3f_bufferoffset = 0;
7994         rsurface.batchsvector3f = NULL;
7995         rsurface.batchsvector3f_vertexbuffer = NULL;
7996         rsurface.batchsvector3f_bufferoffset = 0;
7997         rsurface.batchtvector3f = NULL;
7998         rsurface.batchtvector3f_vertexbuffer = NULL;
7999         rsurface.batchtvector3f_bufferoffset = 0;
8000         rsurface.batchnormal3f  = NULL;
8001         rsurface.batchnormal3f_vertexbuffer = NULL;
8002         rsurface.batchnormal3f_bufferoffset = 0;
8003         rsurface.batchlightmapcolor4f = NULL;
8004         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8005         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8006         rsurface.batchtexcoordtexture2f = NULL;
8007         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8008         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8009         rsurface.batchtexcoordlightmap2f = NULL;
8010         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8011         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8012         rsurface.batchvertexmesh = NULL;
8013         rsurface.batchvertexmeshbuffer = NULL;
8014         rsurface.batchvertex3fbuffer = NULL;
8015         rsurface.batchelement3i = NULL;
8016         rsurface.batchelement3i_indexbuffer = NULL;
8017         rsurface.batchelement3i_bufferoffset = 0;
8018         rsurface.batchelement3s = NULL;
8019         rsurface.batchelement3s_indexbuffer = NULL;
8020         rsurface.batchelement3s_bufferoffset = 0;
8021         rsurface.passcolor4f = NULL;
8022         rsurface.passcolor4f_vertexbuffer = NULL;
8023         rsurface.passcolor4f_bufferoffset = 0;
8024 }
8025
8026 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8027 {
8028         dp_model_t *model = ent->model;
8029         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8030         //      return;
8031         rsurface.entity = (entity_render_t *)ent;
8032         rsurface.skeleton = ent->skeleton;
8033         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8034         rsurface.ent_skinnum = ent->skinnum;
8035         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;
8036         rsurface.ent_flags = ent->flags;
8037         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8038         rsurface.matrix = ent->matrix;
8039         rsurface.inversematrix = ent->inversematrix;
8040         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8041         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8042         R_EntityMatrix(&rsurface.matrix);
8043         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8044         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8045         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8046         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8047         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8048         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8049         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8050         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8051         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8052         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8053         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8054         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8055         rsurface.colormod[3] = ent->alpha;
8056         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8057         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8058         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8059         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8060         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8061         if (ent->model->brush.submodel && !prepass)
8062         {
8063                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8064                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8065         }
8066         if (model->surfmesh.isanimated && model->AnimateVertices)
8067         {
8068                 if (ent->animcache_vertex3f)
8069                 {
8070                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8071                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8072                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8073                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8074                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8075                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8076                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8077                 }
8078                 else if (wanttangents)
8079                 {
8080                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8081                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8082                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8083                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8084                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8085                         rsurface.modelvertexmesh = NULL;
8086                         rsurface.modelvertexmeshbuffer = NULL;
8087                         rsurface.modelvertex3fbuffer = NULL;
8088                 }
8089                 else if (wantnormals)
8090                 {
8091                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8092                         rsurface.modelsvector3f = NULL;
8093                         rsurface.modeltvector3f = NULL;
8094                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8095                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8096                         rsurface.modelvertexmesh = NULL;
8097                         rsurface.modelvertexmeshbuffer = NULL;
8098                         rsurface.modelvertex3fbuffer = NULL;
8099                 }
8100                 else
8101                 {
8102                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8103                         rsurface.modelsvector3f = NULL;
8104                         rsurface.modeltvector3f = NULL;
8105                         rsurface.modelnormal3f = NULL;
8106                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8107                         rsurface.modelvertexmesh = NULL;
8108                         rsurface.modelvertexmeshbuffer = NULL;
8109                         rsurface.modelvertex3fbuffer = NULL;
8110                 }
8111                 rsurface.modelvertex3f_vertexbuffer = 0;
8112                 rsurface.modelvertex3f_bufferoffset = 0;
8113                 rsurface.modelsvector3f_vertexbuffer = 0;
8114                 rsurface.modelsvector3f_bufferoffset = 0;
8115                 rsurface.modeltvector3f_vertexbuffer = 0;
8116                 rsurface.modeltvector3f_bufferoffset = 0;
8117                 rsurface.modelnormal3f_vertexbuffer = 0;
8118                 rsurface.modelnormal3f_bufferoffset = 0;
8119                 rsurface.modelgeneratedvertex = true;
8120         }
8121         else
8122         {
8123                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8124                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8125                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8126                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8127                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8128                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8129                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8130                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8131                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8132                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8133                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8134                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8135                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8136                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8137                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8138                 rsurface.modelgeneratedvertex = false;
8139         }
8140         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8141         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8142         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8143         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8144         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8145         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8146         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8147         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8148         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8149         rsurface.modelelement3i = model->surfmesh.data_element3i;
8150         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8151         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8152         rsurface.modelelement3s = model->surfmesh.data_element3s;
8153         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8154         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8155         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8156         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8157         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8158         rsurface.modelsurfaces = model->data_surfaces;
8159         rsurface.batchgeneratedvertex = false;
8160         rsurface.batchfirstvertex = 0;
8161         rsurface.batchnumvertices = 0;
8162         rsurface.batchfirsttriangle = 0;
8163         rsurface.batchnumtriangles = 0;
8164         rsurface.batchvertex3f  = NULL;
8165         rsurface.batchvertex3f_vertexbuffer = NULL;
8166         rsurface.batchvertex3f_bufferoffset = 0;
8167         rsurface.batchsvector3f = NULL;
8168         rsurface.batchsvector3f_vertexbuffer = NULL;
8169         rsurface.batchsvector3f_bufferoffset = 0;
8170         rsurface.batchtvector3f = NULL;
8171         rsurface.batchtvector3f_vertexbuffer = NULL;
8172         rsurface.batchtvector3f_bufferoffset = 0;
8173         rsurface.batchnormal3f  = NULL;
8174         rsurface.batchnormal3f_vertexbuffer = NULL;
8175         rsurface.batchnormal3f_bufferoffset = 0;
8176         rsurface.batchlightmapcolor4f = NULL;
8177         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8178         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8179         rsurface.batchtexcoordtexture2f = NULL;
8180         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8181         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8182         rsurface.batchtexcoordlightmap2f = NULL;
8183         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8184         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8185         rsurface.batchvertexmesh = NULL;
8186         rsurface.batchvertexmeshbuffer = NULL;
8187         rsurface.batchvertex3fbuffer = NULL;
8188         rsurface.batchelement3i = NULL;
8189         rsurface.batchelement3i_indexbuffer = NULL;
8190         rsurface.batchelement3i_bufferoffset = 0;
8191         rsurface.batchelement3s = NULL;
8192         rsurface.batchelement3s_indexbuffer = NULL;
8193         rsurface.batchelement3s_bufferoffset = 0;
8194         rsurface.passcolor4f = NULL;
8195         rsurface.passcolor4f_vertexbuffer = NULL;
8196         rsurface.passcolor4f_bufferoffset = 0;
8197 }
8198
8199 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)
8200 {
8201         rsurface.entity = r_refdef.scene.worldentity;
8202         rsurface.skeleton = NULL;
8203         rsurface.ent_skinnum = 0;
8204         rsurface.ent_qwskin = -1;
8205         rsurface.ent_flags = entflags;
8206         rsurface.shadertime = r_refdef.scene.time - shadertime;
8207         rsurface.modelnumvertices = numvertices;
8208         rsurface.modelnumtriangles = numtriangles;
8209         rsurface.matrix = *matrix;
8210         rsurface.inversematrix = *inversematrix;
8211         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8212         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8213         R_EntityMatrix(&rsurface.matrix);
8214         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8215         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8216         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8217         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8218         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8219         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8220         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8221         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8222         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8223         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8224         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8225         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8226         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);
8227         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8228         rsurface.frameblend[0].lerp = 1;
8229         rsurface.ent_alttextures = false;
8230         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8231         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8232         if (wanttangents)
8233         {
8234                 rsurface.modelvertex3f = (float *)vertex3f;
8235                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8236                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8237                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8238         }
8239         else if (wantnormals)
8240         {
8241                 rsurface.modelvertex3f = (float *)vertex3f;
8242                 rsurface.modelsvector3f = NULL;
8243                 rsurface.modeltvector3f = NULL;
8244                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8245         }
8246         else
8247         {
8248                 rsurface.modelvertex3f = (float *)vertex3f;
8249                 rsurface.modelsvector3f = NULL;
8250                 rsurface.modeltvector3f = NULL;
8251                 rsurface.modelnormal3f = NULL;
8252         }
8253         rsurface.modelvertexmesh = NULL;
8254         rsurface.modelvertexmeshbuffer = NULL;
8255         rsurface.modelvertex3fbuffer = NULL;
8256         rsurface.modelvertex3f_vertexbuffer = 0;
8257         rsurface.modelvertex3f_bufferoffset = 0;
8258         rsurface.modelsvector3f_vertexbuffer = 0;
8259         rsurface.modelsvector3f_bufferoffset = 0;
8260         rsurface.modeltvector3f_vertexbuffer = 0;
8261         rsurface.modeltvector3f_bufferoffset = 0;
8262         rsurface.modelnormal3f_vertexbuffer = 0;
8263         rsurface.modelnormal3f_bufferoffset = 0;
8264         rsurface.modelgeneratedvertex = true;
8265         rsurface.modellightmapcolor4f  = (float *)color4f;
8266         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8267         rsurface.modellightmapcolor4f_bufferoffset = 0;
8268         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8269         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8270         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8271         rsurface.modeltexcoordlightmap2f  = NULL;
8272         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8273         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8274         rsurface.modelelement3i = (int *)element3i;
8275         rsurface.modelelement3i_indexbuffer = NULL;
8276         rsurface.modelelement3i_bufferoffset = 0;
8277         rsurface.modelelement3s = (unsigned short *)element3s;
8278         rsurface.modelelement3s_indexbuffer = NULL;
8279         rsurface.modelelement3s_bufferoffset = 0;
8280         rsurface.modellightmapoffsets = NULL;
8281         rsurface.modelsurfaces = NULL;
8282         rsurface.batchgeneratedvertex = false;
8283         rsurface.batchfirstvertex = 0;
8284         rsurface.batchnumvertices = 0;
8285         rsurface.batchfirsttriangle = 0;
8286         rsurface.batchnumtriangles = 0;
8287         rsurface.batchvertex3f  = NULL;
8288         rsurface.batchvertex3f_vertexbuffer = NULL;
8289         rsurface.batchvertex3f_bufferoffset = 0;
8290         rsurface.batchsvector3f = NULL;
8291         rsurface.batchsvector3f_vertexbuffer = NULL;
8292         rsurface.batchsvector3f_bufferoffset = 0;
8293         rsurface.batchtvector3f = NULL;
8294         rsurface.batchtvector3f_vertexbuffer = NULL;
8295         rsurface.batchtvector3f_bufferoffset = 0;
8296         rsurface.batchnormal3f  = NULL;
8297         rsurface.batchnormal3f_vertexbuffer = NULL;
8298         rsurface.batchnormal3f_bufferoffset = 0;
8299         rsurface.batchlightmapcolor4f = NULL;
8300         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8301         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8302         rsurface.batchtexcoordtexture2f = NULL;
8303         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8304         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8305         rsurface.batchtexcoordlightmap2f = NULL;
8306         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8307         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8308         rsurface.batchvertexmesh = NULL;
8309         rsurface.batchvertexmeshbuffer = NULL;
8310         rsurface.batchvertex3fbuffer = NULL;
8311         rsurface.batchelement3i = NULL;
8312         rsurface.batchelement3i_indexbuffer = NULL;
8313         rsurface.batchelement3i_bufferoffset = 0;
8314         rsurface.batchelement3s = NULL;
8315         rsurface.batchelement3s_indexbuffer = NULL;
8316         rsurface.batchelement3s_bufferoffset = 0;
8317         rsurface.passcolor4f = NULL;
8318         rsurface.passcolor4f_vertexbuffer = NULL;
8319         rsurface.passcolor4f_bufferoffset = 0;
8320
8321         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8322         {
8323                 if ((wantnormals || wanttangents) && !normal3f)
8324                 {
8325                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8326                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8327                 }
8328                 if (wanttangents && !svector3f)
8329                 {
8330                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8331                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8332                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8333                 }
8334         }
8335 }
8336
8337 float RSurf_FogPoint(const float *v)
8338 {
8339         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8340         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8341         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8342         float FogHeightFade = r_refdef.fogheightfade;
8343         float fogfrac;
8344         unsigned int fogmasktableindex;
8345         if (r_refdef.fogplaneviewabove)
8346                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8347         else
8348                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8349         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8350         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8351 }
8352
8353 float RSurf_FogVertex(const float *v)
8354 {
8355         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8356         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8357         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8358         float FogHeightFade = rsurface.fogheightfade;
8359         float fogfrac;
8360         unsigned int fogmasktableindex;
8361         if (r_refdef.fogplaneviewabove)
8362                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8363         else
8364                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8365         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8366         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8367 }
8368
8369 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8370 {
8371         int i;
8372         for (i = 0;i < numelements;i++)
8373                 outelement3i[i] = inelement3i[i] + adjust;
8374 }
8375
8376 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8377 extern cvar_t gl_vbo;
8378 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8379 {
8380         int deformindex;
8381         int firsttriangle;
8382         int numtriangles;
8383         int firstvertex;
8384         int endvertex;
8385         int numvertices;
8386         int surfacefirsttriangle;
8387         int surfacenumtriangles;
8388         int surfacefirstvertex;
8389         int surfaceendvertex;
8390         int surfacenumvertices;
8391         int batchnumvertices;
8392         int batchnumtriangles;
8393         int needsupdate;
8394         int i, j;
8395         qboolean gaps;
8396         qboolean dynamicvertex;
8397         float amplitude;
8398         float animpos;
8399         float scale;
8400         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8401         float waveparms[4];
8402         q3shaderinfo_deform_t *deform;
8403         const msurface_t *surface, *firstsurface;
8404         r_vertexmesh_t *vertexmesh;
8405         if (!texturenumsurfaces)
8406                 return;
8407         // find vertex range of this surface batch
8408         gaps = false;
8409         firstsurface = texturesurfacelist[0];
8410         firsttriangle = firstsurface->num_firsttriangle;
8411         batchnumvertices = 0;
8412         batchnumtriangles = 0;
8413         firstvertex = endvertex = firstsurface->num_firstvertex;
8414         for (i = 0;i < texturenumsurfaces;i++)
8415         {
8416                 surface = texturesurfacelist[i];
8417                 if (surface != firstsurface + i)
8418                         gaps = true;
8419                 surfacefirstvertex = surface->num_firstvertex;
8420                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8421                 surfacenumvertices = surface->num_vertices;
8422                 surfacenumtriangles = surface->num_triangles;
8423                 if (firstvertex > surfacefirstvertex)
8424                         firstvertex = surfacefirstvertex;
8425                 if (endvertex < surfaceendvertex)
8426                         endvertex = surfaceendvertex;
8427                 batchnumvertices += surfacenumvertices;
8428                 batchnumtriangles += surfacenumtriangles;
8429         }
8430
8431         // we now know the vertex range used, and if there are any gaps in it
8432         rsurface.batchfirstvertex = firstvertex;
8433         rsurface.batchnumvertices = endvertex - firstvertex;
8434         rsurface.batchfirsttriangle = firsttriangle;
8435         rsurface.batchnumtriangles = batchnumtriangles;
8436
8437         // this variable holds flags for which properties have been updated that
8438         // may require regenerating vertexmesh array...
8439         needsupdate = 0;
8440
8441         // check if any dynamic vertex processing must occur
8442         dynamicvertex = false;
8443
8444         // if there is a chance of animated vertex colors, it's a dynamic batch
8445         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8446         {
8447                 dynamicvertex = true;
8448                 batchneed |= BATCHNEED_NOGAPS;
8449                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8450         }
8451
8452         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8453         {
8454                 switch (deform->deform)
8455                 {
8456                 default:
8457                 case Q3DEFORM_PROJECTIONSHADOW:
8458                 case Q3DEFORM_TEXT0:
8459                 case Q3DEFORM_TEXT1:
8460                 case Q3DEFORM_TEXT2:
8461                 case Q3DEFORM_TEXT3:
8462                 case Q3DEFORM_TEXT4:
8463                 case Q3DEFORM_TEXT5:
8464                 case Q3DEFORM_TEXT6:
8465                 case Q3DEFORM_TEXT7:
8466                 case Q3DEFORM_NONE:
8467                         break;
8468                 case Q3DEFORM_AUTOSPRITE:
8469                         dynamicvertex = true;
8470                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8471                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8472                         break;
8473                 case Q3DEFORM_AUTOSPRITE2:
8474                         dynamicvertex = true;
8475                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8476                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8477                         break;
8478                 case Q3DEFORM_NORMAL:
8479                         dynamicvertex = true;
8480                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8481                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8482                         break;
8483                 case Q3DEFORM_WAVE:
8484                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8485                                 break; // if wavefunc is a nop, ignore this transform
8486                         dynamicvertex = true;
8487                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8488                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8489                         break;
8490                 case Q3DEFORM_BULGE:
8491                         dynamicvertex = true;
8492                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8493                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8494                         break;
8495                 case Q3DEFORM_MOVE:
8496                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8497                                 break; // if wavefunc is a nop, ignore this transform
8498                         dynamicvertex = true;
8499                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8500                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8501                         break;
8502                 }
8503         }
8504         switch(rsurface.texture->tcgen.tcgen)
8505         {
8506         default:
8507         case Q3TCGEN_TEXTURE:
8508                 break;
8509         case Q3TCGEN_LIGHTMAP:
8510                 dynamicvertex = true;
8511                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8512                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8513                 break;
8514         case Q3TCGEN_VECTOR:
8515                 dynamicvertex = true;
8516                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8517                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8518                 break;
8519         case Q3TCGEN_ENVIRONMENT:
8520                 dynamicvertex = true;
8521                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8522                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8523                 break;
8524         }
8525         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8526         {
8527                 dynamicvertex = true;
8528                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8529                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8530         }
8531
8532         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8533         {
8534                 dynamicvertex = true;
8535                 batchneed |= BATCHNEED_NOGAPS;
8536                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8537         }
8538
8539         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8540         {
8541                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8542                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8543                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8544                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8545                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8546                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8547                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8548         }
8549
8550         // when the model data has no vertex buffer (dynamic mesh), we need to
8551         // eliminate gaps
8552         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8553                 batchneed |= BATCHNEED_NOGAPS;
8554
8555         // if needsupdate, we have to do a dynamic vertex batch for sure
8556         if (needsupdate & batchneed)
8557                 dynamicvertex = true;
8558
8559         // see if we need to build vertexmesh from arrays
8560         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8561                 dynamicvertex = true;
8562
8563         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8564         // also some drivers strongly dislike firstvertex
8565         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8566                 dynamicvertex = true;
8567
8568         rsurface.batchvertex3f = rsurface.modelvertex3f;
8569         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8570         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8571         rsurface.batchsvector3f = rsurface.modelsvector3f;
8572         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8573         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8574         rsurface.batchtvector3f = rsurface.modeltvector3f;
8575         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8576         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8577         rsurface.batchnormal3f = rsurface.modelnormal3f;
8578         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8579         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8580         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8581         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8582         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8583         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8584         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8585         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8586         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8587         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8588         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8589         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8590         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8591         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8592         rsurface.batchelement3i = rsurface.modelelement3i;
8593         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8594         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8595         rsurface.batchelement3s = rsurface.modelelement3s;
8596         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8597         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8598
8599         // if any dynamic vertex processing has to occur in software, we copy the
8600         // entire surface list together before processing to rebase the vertices
8601         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8602         //
8603         // if any gaps exist and we do not have a static vertex buffer, we have to
8604         // copy the surface list together to avoid wasting upload bandwidth on the
8605         // vertices in the gaps.
8606         //
8607         // if gaps exist and we have a static vertex buffer, we still have to
8608         // combine the index buffer ranges into one dynamic index buffer.
8609         //
8610         // in all cases we end up with data that can be drawn in one call.
8611
8612         if (!dynamicvertex)
8613         {
8614                 // static vertex data, just set pointers...
8615                 rsurface.batchgeneratedvertex = false;
8616                 // if there are gaps, we want to build a combined index buffer,
8617                 // otherwise use the original static buffer with an appropriate offset
8618                 if (gaps)
8619                 {
8620                         // build a new triangle elements array for this batch
8621                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8622                         rsurface.batchfirsttriangle = 0;
8623                         numtriangles = 0;
8624                         for (i = 0;i < texturenumsurfaces;i++)
8625                         {
8626                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8627                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8628                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8629                                 numtriangles += surfacenumtriangles;
8630                         }
8631                         rsurface.batchelement3i_indexbuffer = NULL;
8632                         rsurface.batchelement3i_bufferoffset = 0;
8633                         rsurface.batchelement3s = NULL;
8634                         rsurface.batchelement3s_indexbuffer = NULL;
8635                         rsurface.batchelement3s_bufferoffset = 0;
8636                         if (endvertex <= 65536)
8637                         {
8638                                 // make a 16bit (unsigned short) index array if possible
8639                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8640                                 for (i = 0;i < numtriangles*3;i++)
8641                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8642                         }
8643                 }
8644                 return;
8645         }
8646
8647         // something needs software processing, do it for real...
8648         // we only directly handle separate array data in this case and then
8649         // generate interleaved data if needed...
8650         rsurface.batchgeneratedvertex = true;
8651
8652         // now copy the vertex data into a combined array and make an index array
8653         // (this is what Quake3 does all the time)
8654         //if (gaps || rsurface.batchfirstvertex)
8655         {
8656                 rsurface.batchvertex3fbuffer = NULL;
8657                 rsurface.batchvertexmesh = NULL;
8658                 rsurface.batchvertexmeshbuffer = NULL;
8659                 rsurface.batchvertex3f = NULL;
8660                 rsurface.batchvertex3f_vertexbuffer = NULL;
8661                 rsurface.batchvertex3f_bufferoffset = 0;
8662                 rsurface.batchsvector3f = NULL;
8663                 rsurface.batchsvector3f_vertexbuffer = NULL;
8664                 rsurface.batchsvector3f_bufferoffset = 0;
8665                 rsurface.batchtvector3f = NULL;
8666                 rsurface.batchtvector3f_vertexbuffer = NULL;
8667                 rsurface.batchtvector3f_bufferoffset = 0;
8668                 rsurface.batchnormal3f = NULL;
8669                 rsurface.batchnormal3f_vertexbuffer = NULL;
8670                 rsurface.batchnormal3f_bufferoffset = 0;
8671                 rsurface.batchlightmapcolor4f = NULL;
8672                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8673                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8674                 rsurface.batchtexcoordtexture2f = NULL;
8675                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8676                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8677                 rsurface.batchtexcoordlightmap2f = NULL;
8678                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8679                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8680                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8681                 rsurface.batchelement3i_indexbuffer = NULL;
8682                 rsurface.batchelement3i_bufferoffset = 0;
8683                 rsurface.batchelement3s = NULL;
8684                 rsurface.batchelement3s_indexbuffer = NULL;
8685                 rsurface.batchelement3s_bufferoffset = 0;
8686                 // we'll only be setting up certain arrays as needed
8687                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8688                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8689                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8690                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8691                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8692                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8693                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8694                 {
8695                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8696                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8697                 }
8698                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8699                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8700                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8701                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8702                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8703                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8704                 numvertices = 0;
8705                 numtriangles = 0;
8706                 for (i = 0;i < texturenumsurfaces;i++)
8707                 {
8708                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8709                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8710                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8711                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8712                         // copy only the data requested
8713                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8714                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8715                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8716                         {
8717                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8718                                 {
8719                                         if (rsurface.batchvertex3f)
8720                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8721                                         else
8722                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8723                                 }
8724                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8725                                 {
8726                                         if (rsurface.modelnormal3f)
8727                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8728                                         else
8729                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8730                                 }
8731                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8732                                 {
8733                                         if (rsurface.modelsvector3f)
8734                                         {
8735                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8736                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8737                                         }
8738                                         else
8739                                         {
8740                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8741                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8742                                         }
8743                                 }
8744                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8745                                 {
8746                                         if (rsurface.modellightmapcolor4f)
8747                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8748                                         else
8749                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8750                                 }
8751                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8752                                 {
8753                                         if (rsurface.modeltexcoordtexture2f)
8754                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8755                                         else
8756                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8757                                 }
8758                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8759                                 {
8760                                         if (rsurface.modeltexcoordlightmap2f)
8761                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8762                                         else
8763                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8764                                 }
8765                         }
8766                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8767                         numvertices += surfacenumvertices;
8768                         numtriangles += surfacenumtriangles;
8769                 }
8770
8771                 // generate a 16bit index array as well if possible
8772                 // (in general, dynamic batches fit)
8773                 if (numvertices <= 65536)
8774                 {
8775                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8776                         for (i = 0;i < numtriangles*3;i++)
8777                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8778                 }
8779
8780                 // since we've copied everything, the batch now starts at 0
8781                 rsurface.batchfirstvertex = 0;
8782                 rsurface.batchnumvertices = batchnumvertices;
8783                 rsurface.batchfirsttriangle = 0;
8784                 rsurface.batchnumtriangles = batchnumtriangles;
8785         }
8786
8787         // q1bsp surfaces rendered in vertex color mode have to have colors
8788         // calculated based on lightstyles
8789         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8790         {
8791                 // generate color arrays for the surfaces in this list
8792                 int c[4];
8793                 int scale;
8794                 int size3;
8795                 const int *offsets;
8796                 const unsigned char *lm;
8797                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8798                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8799                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8800                 numvertices = 0;
8801                 for (i = 0;i < texturenumsurfaces;i++)
8802                 {
8803                         surface = texturesurfacelist[i];
8804                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8805                         surfacenumvertices = surface->num_vertices;
8806                         if (surface->lightmapinfo->samples)
8807                         {
8808                                 for (j = 0;j < surfacenumvertices;j++)
8809                                 {
8810                                         lm = surface->lightmapinfo->samples + offsets[j];
8811                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8812                                         VectorScale(lm, scale, c);
8813                                         if (surface->lightmapinfo->styles[1] != 255)
8814                                         {
8815                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8816                                                 lm += size3;
8817                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8818                                                 VectorMA(c, scale, lm, c);
8819                                                 if (surface->lightmapinfo->styles[2] != 255)
8820                                                 {
8821                                                         lm += size3;
8822                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8823                                                         VectorMA(c, scale, lm, c);
8824                                                         if (surface->lightmapinfo->styles[3] != 255)
8825                                                         {
8826                                                                 lm += size3;
8827                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8828                                                                 VectorMA(c, scale, lm, c);
8829                                                         }
8830                                                 }
8831                                         }
8832                                         c[0] >>= 7;
8833                                         c[1] >>= 7;
8834                                         c[2] >>= 7;
8835                                         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);
8836                                         numvertices++;
8837                                 }
8838                         }
8839                         else
8840                         {
8841                                 for (j = 0;j < surfacenumvertices;j++)
8842                                 {
8843                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8844                                         numvertices++;
8845                                 }
8846                         }
8847                 }
8848         }
8849
8850         // if vertices are deformed (sprite flares and things in maps, possibly
8851         // water waves, bulges and other deformations), modify the copied vertices
8852         // in place
8853         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8854         {
8855                 switch (deform->deform)
8856                 {
8857                 default:
8858                 case Q3DEFORM_PROJECTIONSHADOW:
8859                 case Q3DEFORM_TEXT0:
8860                 case Q3DEFORM_TEXT1:
8861                 case Q3DEFORM_TEXT2:
8862                 case Q3DEFORM_TEXT3:
8863                 case Q3DEFORM_TEXT4:
8864                 case Q3DEFORM_TEXT5:
8865                 case Q3DEFORM_TEXT6:
8866                 case Q3DEFORM_TEXT7:
8867                 case Q3DEFORM_NONE:
8868                         break;
8869                 case Q3DEFORM_AUTOSPRITE:
8870                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8871                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8872                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8873                         VectorNormalize(newforward);
8874                         VectorNormalize(newright);
8875                         VectorNormalize(newup);
8876 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8877 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8878 //                      rsurface.batchvertex3f_bufferoffset = 0;
8879 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8880 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8881 //                      rsurface.batchsvector3f_bufferoffset = 0;
8882 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8883 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8884 //                      rsurface.batchtvector3f_bufferoffset = 0;
8885 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8886 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8887 //                      rsurface.batchnormal3f_bufferoffset = 0;
8888                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8889                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8890                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8891                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8892                                 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);
8893                         // a single autosprite surface can contain multiple sprites...
8894                         for (j = 0;j < batchnumvertices - 3;j += 4)
8895                         {
8896                                 VectorClear(center);
8897                                 for (i = 0;i < 4;i++)
8898                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8899                                 VectorScale(center, 0.25f, center);
8900                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8901                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8902                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8903                                 for (i = 0;i < 4;i++)
8904                                 {
8905                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8906                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8907                                 }
8908                         }
8909                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8910                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8911                         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);
8912                         break;
8913                 case Q3DEFORM_AUTOSPRITE2:
8914                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8915                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8916                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8917                         VectorNormalize(newforward);
8918                         VectorNormalize(newright);
8919                         VectorNormalize(newup);
8920 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8921 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8922 //                      rsurface.batchvertex3f_bufferoffset = 0;
8923                         {
8924                                 const float *v1, *v2;
8925                                 vec3_t start, end;
8926                                 float f, l;
8927                                 struct
8928                                 {
8929                                         float length2;
8930                                         const float *v1;
8931                                         const float *v2;
8932                                 }
8933                                 shortest[2];
8934                                 memset(shortest, 0, sizeof(shortest));
8935                                 // a single autosprite surface can contain multiple sprites...
8936                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8937                                 {
8938                                         VectorClear(center);
8939                                         for (i = 0;i < 4;i++)
8940                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8941                                         VectorScale(center, 0.25f, center);
8942                                         // find the two shortest edges, then use them to define the
8943                                         // axis vectors for rotating around the central axis
8944                                         for (i = 0;i < 6;i++)
8945                                         {
8946                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8947                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8948                                                 l = VectorDistance2(v1, v2);
8949                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8950                                                 if (v1[2] != v2[2])
8951                                                         l += (1.0f / 1024.0f);
8952                                                 if (shortest[0].length2 > l || i == 0)
8953                                                 {
8954                                                         shortest[1] = shortest[0];
8955                                                         shortest[0].length2 = l;
8956                                                         shortest[0].v1 = v1;
8957                                                         shortest[0].v2 = v2;
8958                                                 }
8959                                                 else if (shortest[1].length2 > l || i == 1)
8960                                                 {
8961                                                         shortest[1].length2 = l;
8962                                                         shortest[1].v1 = v1;
8963                                                         shortest[1].v2 = v2;
8964                                                 }
8965                                         }
8966                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8967                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8968                                         // this calculates the right vector from the shortest edge
8969                                         // and the up vector from the edge midpoints
8970                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8971                                         VectorNormalize(right);
8972                                         VectorSubtract(end, start, up);
8973                                         VectorNormalize(up);
8974                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8975                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8976                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8977                                         VectorNegate(forward, forward);
8978                                         VectorReflect(forward, 0, up, forward);
8979                                         VectorNormalize(forward);
8980                                         CrossProduct(up, forward, newright);
8981                                         VectorNormalize(newright);
8982                                         // rotate the quad around the up axis vector, this is made
8983                                         // especially easy by the fact we know the quad is flat,
8984                                         // so we only have to subtract the center position and
8985                                         // measure distance along the right vector, and then
8986                                         // multiply that by the newright vector and add back the
8987                                         // center position
8988                                         // we also need to subtract the old position to undo the
8989                                         // displacement from the center, which we do with a
8990                                         // DotProduct, the subtraction/addition of center is also
8991                                         // optimized into DotProducts here
8992                                         l = DotProduct(right, center);
8993                                         for (i = 0;i < 4;i++)
8994                                         {
8995                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
8996                                                 f = DotProduct(right, v1) - l;
8997                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
8998                                         }
8999                                 }
9000                         }
9001                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9002                         {
9003 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9004 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9005 //                              rsurface.batchnormal3f_bufferoffset = 0;
9006                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9007                         }
9008                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9009                         {
9010 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9011 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9012 //                              rsurface.batchsvector3f_bufferoffset = 0;
9013 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9014 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9015 //                              rsurface.batchtvector3f_bufferoffset = 0;
9016                                 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);
9017                         }
9018                         break;
9019                 case Q3DEFORM_NORMAL:
9020                         // deform the normals to make reflections wavey
9021                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9022                         rsurface.batchnormal3f_vertexbuffer = NULL;
9023                         rsurface.batchnormal3f_bufferoffset = 0;
9024                         for (j = 0;j < batchnumvertices;j++)
9025                         {
9026                                 float vertex[3];
9027                                 float *normal = rsurface.batchnormal3f + 3*j;
9028                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9029                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9030                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9031                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9032                                 VectorNormalize(normal);
9033                         }
9034                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9035                         {
9036 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9037 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9038 //                              rsurface.batchsvector3f_bufferoffset = 0;
9039 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9040 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9041 //                              rsurface.batchtvector3f_bufferoffset = 0;
9042                                 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);
9043                         }
9044                         break;
9045                 case Q3DEFORM_WAVE:
9046                         // deform vertex array to make wavey water and flags and such
9047                         waveparms[0] = deform->waveparms[0];
9048                         waveparms[1] = deform->waveparms[1];
9049                         waveparms[2] = deform->waveparms[2];
9050                         waveparms[3] = deform->waveparms[3];
9051                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9052                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9053                         // this is how a divisor of vertex influence on deformation
9054                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9055                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9056 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9057 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9058 //                      rsurface.batchvertex3f_bufferoffset = 0;
9059 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9060 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9061 //                      rsurface.batchnormal3f_bufferoffset = 0;
9062                         for (j = 0;j < batchnumvertices;j++)
9063                         {
9064                                 // if the wavefunc depends on time, evaluate it per-vertex
9065                                 if (waveparms[3])
9066                                 {
9067                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9068                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9069                                 }
9070                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9071                         }
9072                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9073                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9074                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9075                         {
9076 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9077 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9078 //                              rsurface.batchsvector3f_bufferoffset = 0;
9079 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9080 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9081 //                              rsurface.batchtvector3f_bufferoffset = 0;
9082                                 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);
9083                         }
9084                         break;
9085                 case Q3DEFORM_BULGE:
9086                         // deform vertex array to make the surface have moving bulges
9087 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9088 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9089 //                      rsurface.batchvertex3f_bufferoffset = 0;
9090 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9091 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9092 //                      rsurface.batchnormal3f_bufferoffset = 0;
9093                         for (j = 0;j < batchnumvertices;j++)
9094                         {
9095                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9096                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9097                         }
9098                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9099                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9100                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9101                         {
9102 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9103 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9104 //                              rsurface.batchsvector3f_bufferoffset = 0;
9105 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9106 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9107 //                              rsurface.batchtvector3f_bufferoffset = 0;
9108                                 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);
9109                         }
9110                         break;
9111                 case Q3DEFORM_MOVE:
9112                         // deform vertex array
9113                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9114                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9115                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9116                         VectorScale(deform->parms, scale, waveparms);
9117 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9118 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9119 //                      rsurface.batchvertex3f_bufferoffset = 0;
9120                         for (j = 0;j < batchnumvertices;j++)
9121                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9122                         break;
9123                 }
9124         }
9125
9126         // generate texcoords based on the chosen texcoord source
9127         switch(rsurface.texture->tcgen.tcgen)
9128         {
9129         default:
9130         case Q3TCGEN_TEXTURE:
9131                 break;
9132         case Q3TCGEN_LIGHTMAP:
9133 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9134 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9135 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9136                 if (rsurface.batchtexcoordlightmap2f)
9137                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9138                 break;
9139         case Q3TCGEN_VECTOR:
9140 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9141 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9142 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9143                 for (j = 0;j < batchnumvertices;j++)
9144                 {
9145                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9146                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9147                 }
9148                 break;
9149         case Q3TCGEN_ENVIRONMENT:
9150                 // make environment reflections using a spheremap
9151                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9152                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9153                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9154                 for (j = 0;j < batchnumvertices;j++)
9155                 {
9156                         // identical to Q3A's method, but executed in worldspace so
9157                         // carried models can be shiny too
9158
9159                         float viewer[3], d, reflected[3], worldreflected[3];
9160
9161                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9162                         // VectorNormalize(viewer);
9163
9164                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9165
9166                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9167                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9168                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9169                         // note: this is proportinal to viewer, so we can normalize later
9170
9171                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9172                         VectorNormalize(worldreflected);
9173
9174                         // note: this sphere map only uses world x and z!
9175                         // so positive and negative y will LOOK THE SAME.
9176                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9177                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9178                 }
9179                 break;
9180         }
9181         // the only tcmod that needs software vertex processing is turbulent, so
9182         // check for it here and apply the changes if needed
9183         // and we only support that as the first one
9184         // (handling a mixture of turbulent and other tcmods would be problematic
9185         //  without punting it entirely to a software path)
9186         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9187         {
9188                 amplitude = rsurface.texture->tcmods[0].parms[1];
9189                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9190 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9191 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9192 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9193                 for (j = 0;j < batchnumvertices;j++)
9194                 {
9195                         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);
9196                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9197                 }
9198         }
9199
9200         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9201         {
9202                 // convert the modified arrays to vertex structs
9203 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9204 //              rsurface.batchvertexmeshbuffer = NULL;
9205                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9206                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9207                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9208                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9209                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9210                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9211                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9212                 {
9213                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9214                         {
9215                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9216                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9217                         }
9218                 }
9219                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9220                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9221                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9222                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9223                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9224                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9225                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9226                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9227                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9228         }
9229 }
9230
9231 void RSurf_DrawBatch(void)
9232 {
9233         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9234         // through the pipeline, killing it earlier in the pipeline would have
9235         // per-surface overhead rather than per-batch overhead, so it's best to
9236         // reject it here, before it hits glDraw.
9237         if (rsurface.batchnumtriangles == 0)
9238                 return;
9239 #if 0
9240         // batch debugging code
9241         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9242         {
9243                 int i;
9244                 int j;
9245                 int c;
9246                 const int *e;
9247                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9248                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9249                 {
9250                         c = e[i];
9251                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9252                         {
9253                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9254                                 {
9255                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9256                                                 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);
9257                                         break;
9258                                 }
9259                         }
9260                 }
9261         }
9262 #endif
9263         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);
9264 }
9265
9266 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9267 {
9268         // pick the closest matching water plane
9269         int planeindex, vertexindex, bestplaneindex = -1;
9270         float d, bestd;
9271         vec3_t vert;
9272         const float *v;
9273         r_waterstate_waterplane_t *p;
9274         qboolean prepared = false;
9275         bestd = 0;
9276         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9277         {
9278                 if(p->camera_entity != rsurface.texture->camera_entity)
9279                         continue;
9280                 d = 0;
9281                 if(!prepared)
9282                 {
9283                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9284                         prepared = true;
9285                         if(rsurface.batchnumvertices == 0)
9286                                 break;
9287                 }
9288                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9289                 {
9290                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9291                         d += fabs(PlaneDiff(vert, &p->plane));
9292                 }
9293                 if (bestd > d || bestplaneindex < 0)
9294                 {
9295                         bestd = d;
9296                         bestplaneindex = planeindex;
9297                 }
9298         }
9299         return bestplaneindex;
9300         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9301         // this situation though, as it might be better to render single larger
9302         // batches with useless stuff (backface culled for example) than to
9303         // render multiple smaller batches
9304 }
9305
9306 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9307 {
9308         int i;
9309         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9310         rsurface.passcolor4f_vertexbuffer = 0;
9311         rsurface.passcolor4f_bufferoffset = 0;
9312         for (i = 0;i < rsurface.batchnumvertices;i++)
9313                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9314 }
9315
9316 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9317 {
9318         int i;
9319         float f;
9320         const float *v;
9321         const float *c;
9322         float *c2;
9323         if (rsurface.passcolor4f)
9324         {
9325                 // generate color arrays
9326                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9327                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9328                 rsurface.passcolor4f_vertexbuffer = 0;
9329                 rsurface.passcolor4f_bufferoffset = 0;
9330                 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)
9331                 {
9332                         f = RSurf_FogVertex(v);
9333                         c2[0] = c[0] * f;
9334                         c2[1] = c[1] * f;
9335                         c2[2] = c[2] * f;
9336                         c2[3] = c[3];
9337                 }
9338         }
9339         else
9340         {
9341                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9342                 rsurface.passcolor4f_vertexbuffer = 0;
9343                 rsurface.passcolor4f_bufferoffset = 0;
9344                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9345                 {
9346                         f = RSurf_FogVertex(v);
9347                         c2[0] = f;
9348                         c2[1] = f;
9349                         c2[2] = f;
9350                         c2[3] = 1;
9351                 }
9352         }
9353 }
9354
9355 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9356 {
9357         int i;
9358         float f;
9359         const float *v;
9360         const float *c;
9361         float *c2;
9362         if (!rsurface.passcolor4f)
9363                 return;
9364         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9365         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9366         rsurface.passcolor4f_vertexbuffer = 0;
9367         rsurface.passcolor4f_bufferoffset = 0;
9368         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)
9369         {
9370                 f = RSurf_FogVertex(v);
9371                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9372                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9373                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9374                 c2[3] = c[3];
9375         }
9376 }
9377
9378 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9379 {
9380         int i;
9381         const float *c;
9382         float *c2;
9383         if (!rsurface.passcolor4f)
9384                 return;
9385         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9386         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9387         rsurface.passcolor4f_vertexbuffer = 0;
9388         rsurface.passcolor4f_bufferoffset = 0;
9389         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9390         {
9391                 c2[0] = c[0] * r;
9392                 c2[1] = c[1] * g;
9393                 c2[2] = c[2] * b;
9394                 c2[3] = c[3] * a;
9395         }
9396 }
9397
9398 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9399 {
9400         int i;
9401         const float *c;
9402         float *c2;
9403         if (!rsurface.passcolor4f)
9404                 return;
9405         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9406         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9407         rsurface.passcolor4f_vertexbuffer = 0;
9408         rsurface.passcolor4f_bufferoffset = 0;
9409         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9410         {
9411                 c2[0] = c[0] + r_refdef.scene.ambient;
9412                 c2[1] = c[1] + r_refdef.scene.ambient;
9413                 c2[2] = c[2] + r_refdef.scene.ambient;
9414                 c2[3] = c[3];
9415         }
9416 }
9417
9418 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9419 {
9420         // TODO: optimize
9421         rsurface.passcolor4f = NULL;
9422         rsurface.passcolor4f_vertexbuffer = 0;
9423         rsurface.passcolor4f_bufferoffset = 0;
9424         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9425         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9426         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9427         GL_Color(r, g, b, a);
9428         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9429         RSurf_DrawBatch();
9430 }
9431
9432 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9433 {
9434         // TODO: optimize applyfog && applycolor case
9435         // just apply fog if necessary, and tint the fog color array if necessary
9436         rsurface.passcolor4f = NULL;
9437         rsurface.passcolor4f_vertexbuffer = 0;
9438         rsurface.passcolor4f_bufferoffset = 0;
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_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9447 {
9448         // TODO: optimize
9449         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9450         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9451         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9452         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9453         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9454         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9455         GL_Color(r, g, b, a);
9456         RSurf_DrawBatch();
9457 }
9458
9459 static void RSurf_DrawBatch_GL11_ClampColor(void)
9460 {
9461         int i;
9462         const float *c1;
9463         float *c2;
9464         if (!rsurface.passcolor4f)
9465                 return;
9466         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9467         {
9468                 c2[0] = bound(0.0f, c1[0], 1.0f);
9469                 c2[1] = bound(0.0f, c1[1], 1.0f);
9470                 c2[2] = bound(0.0f, c1[2], 1.0f);
9471                 c2[3] = bound(0.0f, c1[3], 1.0f);
9472         }
9473 }
9474
9475 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9476 {
9477         int i;
9478         float f;
9479         const float *v;
9480         const float *n;
9481         float *c;
9482         //vec3_t eyedir;
9483
9484         // fake shading
9485         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9486         rsurface.passcolor4f_vertexbuffer = 0;
9487         rsurface.passcolor4f_bufferoffset = 0;
9488         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)
9489         {
9490                 f = -DotProduct(r_refdef.view.forward, n);
9491                 f = max(0, f);
9492                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9493                 f *= r_refdef.lightmapintensity;
9494                 Vector4Set(c, f, f, f, 1);
9495         }
9496 }
9497
9498 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9499 {
9500         RSurf_DrawBatch_GL11_ApplyFakeLight();
9501         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9502         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9503         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9504         GL_Color(r, g, b, a);
9505         RSurf_DrawBatch();
9506 }
9507
9508 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9509 {
9510         int i;
9511         float f;
9512         float alpha;
9513         const float *v;
9514         const float *n;
9515         float *c;
9516         vec3_t ambientcolor;
9517         vec3_t diffusecolor;
9518         vec3_t lightdir;
9519         // TODO: optimize
9520         // model lighting
9521         VectorCopy(rsurface.modellight_lightdir, lightdir);
9522         f = 0.5f * r_refdef.lightmapintensity;
9523         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9524         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9525         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9526         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9527         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9528         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9529         alpha = *a;
9530         if (VectorLength2(diffusecolor) > 0)
9531         {
9532                 // q3-style directional shading
9533                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9534                 rsurface.passcolor4f_vertexbuffer = 0;
9535                 rsurface.passcolor4f_bufferoffset = 0;
9536                 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)
9537                 {
9538                         if ((f = DotProduct(n, lightdir)) > 0)
9539                                 VectorMA(ambientcolor, f, diffusecolor, c);
9540                         else
9541                                 VectorCopy(ambientcolor, c);
9542                         c[3] = alpha;
9543                 }
9544                 *r = 1;
9545                 *g = 1;
9546                 *b = 1;
9547                 *a = 1;
9548                 *applycolor = false;
9549         }
9550         else
9551         {
9552                 *r = ambientcolor[0];
9553                 *g = ambientcolor[1];
9554                 *b = ambientcolor[2];
9555                 rsurface.passcolor4f = NULL;
9556                 rsurface.passcolor4f_vertexbuffer = 0;
9557                 rsurface.passcolor4f_bufferoffset = 0;
9558         }
9559 }
9560
9561 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9562 {
9563         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9564         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9565         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9566         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9567         GL_Color(r, g, b, a);
9568         RSurf_DrawBatch();
9569 }
9570
9571 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9572 {
9573         int i;
9574         float f;
9575         const float *v;
9576         float *c;
9577
9578         // fake shading
9579         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9580         rsurface.passcolor4f_vertexbuffer = 0;
9581         rsurface.passcolor4f_bufferoffset = 0;
9582
9583         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9584         {
9585                 f = 1 - RSurf_FogVertex(v);
9586                 c[0] = r;
9587                 c[1] = g;
9588                 c[2] = b;
9589                 c[3] = f * a;
9590         }
9591 }
9592
9593 void RSurf_SetupDepthAndCulling(void)
9594 {
9595         // submodels are biased to avoid z-fighting with world surfaces that they
9596         // may be exactly overlapping (avoids z-fighting artifacts on certain
9597         // doors and things in Quake maps)
9598         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9599         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9600         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9601         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9602 }
9603
9604 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9605 {
9606         // transparent sky would be ridiculous
9607         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9608                 return;
9609         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9610         skyrenderlater = true;
9611         RSurf_SetupDepthAndCulling();
9612         GL_DepthMask(true);
9613         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9614         // skymasking on them, and Quake3 never did sky masking (unlike
9615         // software Quake and software Quake2), so disable the sky masking
9616         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9617         // and skymasking also looks very bad when noclipping outside the
9618         // level, so don't use it then either.
9619         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9620         {
9621                 R_Mesh_ResetTextureState();
9622                 if (skyrendermasked)
9623                 {
9624                         R_SetupShader_DepthOrShadow(false);
9625                         // depth-only (masking)
9626                         GL_ColorMask(0,0,0,0);
9627                         // just to make sure that braindead drivers don't draw
9628                         // anything despite that colormask...
9629                         GL_BlendFunc(GL_ZERO, GL_ONE);
9630                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9631                         if (rsurface.batchvertex3fbuffer)
9632                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9633                         else
9634                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9635                 }
9636                 else
9637                 {
9638                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9639                         // fog sky
9640                         GL_BlendFunc(GL_ONE, GL_ZERO);
9641                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9642                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9643                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9644                 }
9645                 RSurf_DrawBatch();
9646                 if (skyrendermasked)
9647                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9648         }
9649         R_Mesh_ResetTextureState();
9650         GL_Color(1, 1, 1, 1);
9651 }
9652
9653 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9654 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9655 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9656 {
9657         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9658                 return;
9659         if (prepass)
9660         {
9661                 // render screenspace normalmap to texture
9662                 GL_DepthMask(true);
9663                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9664                 RSurf_DrawBatch();
9665         }
9666
9667         // bind lightmap texture
9668
9669         // water/refraction/reflection/camera surfaces have to be handled specially
9670         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9671         {
9672                 int start, end, startplaneindex;
9673                 for (start = 0;start < texturenumsurfaces;start = end)
9674                 {
9675                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9676                         if(startplaneindex < 0)
9677                         {
9678                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9679                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9680                                 end = start + 1;
9681                                 continue;
9682                         }
9683                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9684                                 ;
9685                         // now that we have a batch using the same planeindex, render it
9686                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9687                         {
9688                                 // render water or distortion background
9689                                 GL_DepthMask(true);
9690                                 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);
9691                                 RSurf_DrawBatch();
9692                                 // blend surface on top
9693                                 GL_DepthMask(false);
9694                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9695                                 RSurf_DrawBatch();
9696                         }
9697                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9698                         {
9699                                 // render surface with reflection texture as input
9700                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9701                                 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);
9702                                 RSurf_DrawBatch();
9703                         }
9704                 }
9705                 return;
9706         }
9707
9708         // render surface batch normally
9709         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9710         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);
9711         RSurf_DrawBatch();
9712 }
9713
9714 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9715 {
9716         // OpenGL 1.3 path - anything not completely ancient
9717         qboolean applycolor;
9718         qboolean applyfog;
9719         int layerindex;
9720         const texturelayer_t *layer;
9721         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);
9722         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9723
9724         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9725         {
9726                 vec4_t layercolor;
9727                 int layertexrgbscale;
9728                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9729                 {
9730                         if (layerindex == 0)
9731                                 GL_AlphaTest(true);
9732                         else
9733                         {
9734                                 GL_AlphaTest(false);
9735                                 GL_DepthFunc(GL_EQUAL);
9736                         }
9737                 }
9738                 GL_DepthMask(layer->depthmask && writedepth);
9739                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9740                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9741                 {
9742                         layertexrgbscale = 4;
9743                         VectorScale(layer->color, 0.25f, layercolor);
9744                 }
9745                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9746                 {
9747                         layertexrgbscale = 2;
9748                         VectorScale(layer->color, 0.5f, layercolor);
9749                 }
9750                 else
9751                 {
9752                         layertexrgbscale = 1;
9753                         VectorScale(layer->color, 1.0f, layercolor);
9754                 }
9755                 layercolor[3] = layer->color[3];
9756                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9757                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9758                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9759                 switch (layer->type)
9760                 {
9761                 case TEXTURELAYERTYPE_LITTEXTURE:
9762                         // single-pass lightmapped texture with 2x rgbscale
9763                         R_Mesh_TexBind(0, r_texture_white);
9764                         R_Mesh_TexMatrix(0, NULL);
9765                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9766                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9767                         R_Mesh_TexBind(1, layer->texture);
9768                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9769                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9770                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9771                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9772                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9773                         else if (FAKELIGHT_ENABLED)
9774                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9775                         else if (rsurface.uselightmaptexture)
9776                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9777                         else
9778                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9779                         break;
9780                 case TEXTURELAYERTYPE_TEXTURE:
9781                         // singletexture unlit texture with transparency support
9782                         R_Mesh_TexBind(0, layer->texture);
9783                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9784                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9785                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9786                         R_Mesh_TexBind(1, 0);
9787                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9788                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9789                         break;
9790                 case TEXTURELAYERTYPE_FOG:
9791                         // singletexture fogging
9792                         if (layer->texture)
9793                         {
9794                                 R_Mesh_TexBind(0, layer->texture);
9795                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9796                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9797                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9798                         }
9799                         else
9800                         {
9801                                 R_Mesh_TexBind(0, 0);
9802                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9803                         }
9804                         R_Mesh_TexBind(1, 0);
9805                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9806                         // generate a color array for the fog pass
9807                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9808                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9809                         RSurf_DrawBatch();
9810                         break;
9811                 default:
9812                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9813                 }
9814         }
9815         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9816         {
9817                 GL_DepthFunc(GL_LEQUAL);
9818                 GL_AlphaTest(false);
9819         }
9820 }
9821
9822 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9823 {
9824         // OpenGL 1.1 - crusty old voodoo path
9825         qboolean applyfog;
9826         int layerindex;
9827         const texturelayer_t *layer;
9828         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);
9829         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9830
9831         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9832         {
9833                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9834                 {
9835                         if (layerindex == 0)
9836                                 GL_AlphaTest(true);
9837                         else
9838                         {
9839                                 GL_AlphaTest(false);
9840                                 GL_DepthFunc(GL_EQUAL);
9841                         }
9842                 }
9843                 GL_DepthMask(layer->depthmask && writedepth);
9844                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9845                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9846                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9847                 switch (layer->type)
9848                 {
9849                 case TEXTURELAYERTYPE_LITTEXTURE:
9850                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9851                         {
9852                                 // two-pass lit texture with 2x rgbscale
9853                                 // first the lightmap pass
9854                                 R_Mesh_TexBind(0, r_texture_white);
9855                                 R_Mesh_TexMatrix(0, NULL);
9856                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9857                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9858                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9859                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9860                                 else if (FAKELIGHT_ENABLED)
9861                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9862                                 else if (rsurface.uselightmaptexture)
9863                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9864                                 else
9865                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9866                                 // then apply the texture to it
9867                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9868                                 R_Mesh_TexBind(0, layer->texture);
9869                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9870                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9871                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9872                                 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);
9873                         }
9874                         else
9875                         {
9876                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9877                                 R_Mesh_TexBind(0, layer->texture);
9878                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9879                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9880                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9881                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9882                                         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);
9883                                 else
9884                                         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);
9885                         }
9886                         break;
9887                 case TEXTURELAYERTYPE_TEXTURE:
9888                         // singletexture unlit texture with transparency support
9889                         R_Mesh_TexBind(0, layer->texture);
9890                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9891                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9892                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9893                         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);
9894                         break;
9895                 case TEXTURELAYERTYPE_FOG:
9896                         // singletexture fogging
9897                         if (layer->texture)
9898                         {
9899                                 R_Mesh_TexBind(0, layer->texture);
9900                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9901                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9902                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9903                         }
9904                         else
9905                         {
9906                                 R_Mesh_TexBind(0, 0);
9907                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9908                         }
9909                         // generate a color array for the fog pass
9910                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9911                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9912                         RSurf_DrawBatch();
9913                         break;
9914                 default:
9915                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9916                 }
9917         }
9918         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9919         {
9920                 GL_DepthFunc(GL_LEQUAL);
9921                 GL_AlphaTest(false);
9922         }
9923 }
9924
9925 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9926 {
9927         int vi;
9928         int j;
9929         r_vertexgeneric_t *batchvertex;
9930         float c[4];
9931
9932 //      R_Mesh_ResetTextureState();
9933         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9934
9935         if(rsurface.texture && rsurface.texture->currentskinframe)
9936         {
9937                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9938                 c[3] *= rsurface.texture->currentalpha;
9939         }
9940         else
9941         {
9942                 c[0] = 1;
9943                 c[1] = 0;
9944                 c[2] = 1;
9945                 c[3] = 1;
9946         }
9947
9948         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9949         {
9950                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9951                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9952                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9953         }
9954
9955         // brighten it up (as texture value 127 means "unlit")
9956         c[0] *= 2 * r_refdef.view.colorscale;
9957         c[1] *= 2 * r_refdef.view.colorscale;
9958         c[2] *= 2 * r_refdef.view.colorscale;
9959
9960         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9961                 c[3] *= r_wateralpha.value;
9962
9963         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9964         {
9965                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9966                 GL_DepthMask(false);
9967         }
9968         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9969         {
9970                 GL_BlendFunc(GL_ONE, GL_ONE);
9971                 GL_DepthMask(false);
9972         }
9973         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9974         {
9975                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9976                 GL_DepthMask(false);
9977         }
9978         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9979         {
9980                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9981                 GL_DepthMask(false);
9982         }
9983         else
9984         {
9985                 GL_BlendFunc(GL_ONE, GL_ZERO);
9986                 GL_DepthMask(writedepth);
9987         }
9988
9989         if (r_showsurfaces.integer == 3)
9990         {
9991                 rsurface.passcolor4f = NULL;
9992
9993                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
9994                 {
9995                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9996
9997                         rsurface.passcolor4f = NULL;
9998                         rsurface.passcolor4f_vertexbuffer = 0;
9999                         rsurface.passcolor4f_bufferoffset = 0;
10000                 }
10001                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10002                 {
10003                         qboolean applycolor = true;
10004                         float one = 1.0;
10005
10006                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10007
10008                         r_refdef.lightmapintensity = 1;
10009                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10010                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10011                 }
10012                 else if (FAKELIGHT_ENABLED)
10013                 {
10014                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10015
10016                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10017                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10018                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10019                 }
10020                 else
10021                 {
10022                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10023
10024                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10025                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10026                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10027                 }
10028
10029                 if(!rsurface.passcolor4f)
10030                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10031
10032                 RSurf_DrawBatch_GL11_ApplyAmbient();
10033                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10034                 if(r_refdef.fogenabled)
10035                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10036                 RSurf_DrawBatch_GL11_ClampColor();
10037
10038                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10039                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10040                 RSurf_DrawBatch();
10041         }
10042         else if (!r_refdef.view.showdebug)
10043         {
10044                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10045                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10046                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10047                 {
10048                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10049                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10050                 }
10051                 R_Mesh_PrepareVertices_Generic_Unlock();
10052                 RSurf_DrawBatch();
10053         }
10054         else if (r_showsurfaces.integer == 4)
10055         {
10056                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10057                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10058                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10059                 {
10060                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10061                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10062                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10063                 }
10064                 R_Mesh_PrepareVertices_Generic_Unlock();
10065                 RSurf_DrawBatch();
10066         }
10067         else if (r_showsurfaces.integer == 2)
10068         {
10069                 const int *e;
10070                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10071                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10072                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10073                 {
10074                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10075                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10076                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10077                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10078                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10079                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10080                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10081                 }
10082                 R_Mesh_PrepareVertices_Generic_Unlock();
10083                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10084         }
10085         else
10086         {
10087                 int texturesurfaceindex;
10088                 int k;
10089                 const msurface_t *surface;
10090                 float surfacecolor4f[4];
10091                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10092                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10093                 vi = 0;
10094                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10095                 {
10096                         surface = texturesurfacelist[texturesurfaceindex];
10097                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10098                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10099                         for (j = 0;j < surface->num_vertices;j++)
10100                         {
10101                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10102                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10103                                 vi++;
10104                         }
10105                 }
10106                 R_Mesh_PrepareVertices_Generic_Unlock();
10107                 RSurf_DrawBatch();
10108         }
10109 }
10110
10111 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10112 {
10113         CHECKGLERROR
10114         RSurf_SetupDepthAndCulling();
10115         if (r_showsurfaces.integer)
10116         {
10117                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10118                 return;
10119         }
10120         switch (vid.renderpath)
10121         {
10122         case RENDERPATH_GL20:
10123         case RENDERPATH_D3D9:
10124         case RENDERPATH_D3D10:
10125         case RENDERPATH_D3D11:
10126         case RENDERPATH_SOFT:
10127         case RENDERPATH_GLES2:
10128                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10129                 break;
10130         case RENDERPATH_GL13:
10131         case RENDERPATH_GLES1:
10132                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10133                 break;
10134         case RENDERPATH_GL11:
10135                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10136                 break;
10137         }
10138         CHECKGLERROR
10139 }
10140
10141 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10142 {
10143         CHECKGLERROR
10144         RSurf_SetupDepthAndCulling();
10145         if (r_showsurfaces.integer)
10146         {
10147                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10148                 return;
10149         }
10150         switch (vid.renderpath)
10151         {
10152         case RENDERPATH_GL20:
10153         case RENDERPATH_D3D9:
10154         case RENDERPATH_D3D10:
10155         case RENDERPATH_D3D11:
10156         case RENDERPATH_SOFT:
10157         case RENDERPATH_GLES2:
10158                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10159                 break;
10160         case RENDERPATH_GL13:
10161         case RENDERPATH_GLES1:
10162                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10163                 break;
10164         case RENDERPATH_GL11:
10165                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10166                 break;
10167         }
10168         CHECKGLERROR
10169 }
10170
10171 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10172 {
10173         int i, j;
10174         int texturenumsurfaces, endsurface;
10175         texture_t *texture;
10176         const msurface_t *surface;
10177         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10178
10179         // if the model is static it doesn't matter what value we give for
10180         // wantnormals and wanttangents, so this logic uses only rules applicable
10181         // to a model, knowing that they are meaningless otherwise
10182         if (ent == r_refdef.scene.worldentity)
10183                 RSurf_ActiveWorldEntity();
10184         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10185                 RSurf_ActiveModelEntity(ent, false, false, false);
10186         else
10187         {
10188                 switch (vid.renderpath)
10189                 {
10190                 case RENDERPATH_GL20:
10191                 case RENDERPATH_D3D9:
10192                 case RENDERPATH_D3D10:
10193                 case RENDERPATH_D3D11:
10194                 case RENDERPATH_SOFT:
10195                 case RENDERPATH_GLES2:
10196                         RSurf_ActiveModelEntity(ent, true, true, false);
10197                         break;
10198                 case RENDERPATH_GL11:
10199                 case RENDERPATH_GL13:
10200                 case RENDERPATH_GLES1:
10201                         RSurf_ActiveModelEntity(ent, true, false, false);
10202                         break;
10203                 }
10204         }
10205
10206         if (r_transparentdepthmasking.integer)
10207         {
10208                 qboolean setup = false;
10209                 for (i = 0;i < numsurfaces;i = j)
10210                 {
10211                         j = i + 1;
10212                         surface = rsurface.modelsurfaces + surfacelist[i];
10213                         texture = surface->texture;
10214                         rsurface.texture = R_GetCurrentTexture(texture);
10215                         rsurface.lightmaptexture = NULL;
10216                         rsurface.deluxemaptexture = NULL;
10217                         rsurface.uselightmaptexture = false;
10218                         // scan ahead until we find a different texture
10219                         endsurface = min(i + 1024, numsurfaces);
10220                         texturenumsurfaces = 0;
10221                         texturesurfacelist[texturenumsurfaces++] = surface;
10222                         for (;j < endsurface;j++)
10223                         {
10224                                 surface = rsurface.modelsurfaces + surfacelist[j];
10225                                 if (texture != surface->texture)
10226                                         break;
10227                                 texturesurfacelist[texturenumsurfaces++] = surface;
10228                         }
10229                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10230                                 continue;
10231                         // render the range of surfaces as depth
10232                         if (!setup)
10233                         {
10234                                 setup = true;
10235                                 GL_ColorMask(0,0,0,0);
10236                                 GL_Color(1,1,1,1);
10237                                 GL_DepthTest(true);
10238                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10239                                 GL_DepthMask(true);
10240 //                              R_Mesh_ResetTextureState();
10241                                 R_SetupShader_DepthOrShadow(false);
10242                         }
10243                         RSurf_SetupDepthAndCulling();
10244                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10245                         if (rsurface.batchvertex3fbuffer)
10246                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10247                         else
10248                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10249                         RSurf_DrawBatch();
10250                 }
10251                 if (setup)
10252                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10253         }
10254
10255         for (i = 0;i < numsurfaces;i = j)
10256         {
10257                 j = i + 1;
10258                 surface = rsurface.modelsurfaces + surfacelist[i];
10259                 texture = surface->texture;
10260                 rsurface.texture = R_GetCurrentTexture(texture);
10261                 // scan ahead until we find a different texture
10262                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10263                 texturenumsurfaces = 0;
10264                 texturesurfacelist[texturenumsurfaces++] = surface;
10265                 if(FAKELIGHT_ENABLED)
10266                 {
10267                         rsurface.lightmaptexture = NULL;
10268                         rsurface.deluxemaptexture = NULL;
10269                         rsurface.uselightmaptexture = false;
10270                         for (;j < endsurface;j++)
10271                         {
10272                                 surface = rsurface.modelsurfaces + surfacelist[j];
10273                                 if (texture != surface->texture)
10274                                         break;
10275                                 texturesurfacelist[texturenumsurfaces++] = surface;
10276                         }
10277                 }
10278                 else
10279                 {
10280                         rsurface.lightmaptexture = surface->lightmaptexture;
10281                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10282                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10283                         for (;j < endsurface;j++)
10284                         {
10285                                 surface = rsurface.modelsurfaces + surfacelist[j];
10286                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10287                                         break;
10288                                 texturesurfacelist[texturenumsurfaces++] = surface;
10289                         }
10290                 }
10291                 // render the range of surfaces
10292                 if (ent == r_refdef.scene.worldentity)
10293                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10294                 else
10295                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10296         }
10297         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10298 }
10299
10300 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10301 {
10302         // transparent surfaces get pushed off into the transparent queue
10303         int surfacelistindex;
10304         const msurface_t *surface;
10305         vec3_t tempcenter, center;
10306         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10307         {
10308                 surface = texturesurfacelist[surfacelistindex];
10309                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10310                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10311                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10312                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10313                 if (queueentity->transparent_offset) // transparent offset
10314                 {
10315                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10316                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10317                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10318                 }
10319                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10320         }
10321 }
10322
10323 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10324 {
10325         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10326                 return;
10327         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10328                 return;
10329         RSurf_SetupDepthAndCulling();
10330         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10331         if (rsurface.batchvertex3fbuffer)
10332                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10333         else
10334                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10335         RSurf_DrawBatch();
10336 }
10337
10338 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10339 {
10340         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10341         CHECKGLERROR
10342         if (depthonly)
10343                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10344         else if (prepass)
10345         {
10346                 if (!rsurface.texture->currentnumlayers)
10347                         return;
10348                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10349                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10350                 else
10351                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10352         }
10353         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10354                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10355         else if (!rsurface.texture->currentnumlayers)
10356                 return;
10357         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10358         {
10359                 // in the deferred case, transparent surfaces were queued during prepass
10360                 if (!r_shadow_usingdeferredprepass)
10361                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10362         }
10363         else
10364         {
10365                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10366                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10367         }
10368         CHECKGLERROR
10369 }
10370
10371 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10372 {
10373         int i, j;
10374         texture_t *texture;
10375         R_FrameData_SetMark();
10376         // break the surface list down into batches by texture and use of lightmapping
10377         for (i = 0;i < numsurfaces;i = j)
10378         {
10379                 j = i + 1;
10380                 // texture is the base texture pointer, rsurface.texture is the
10381                 // current frame/skin the texture is directing us to use (for example
10382                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10383                 // use skin 1 instead)
10384                 texture = surfacelist[i]->texture;
10385                 rsurface.texture = R_GetCurrentTexture(texture);
10386                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10387                 {
10388                         // if this texture is not the kind we want, skip ahead to the next one
10389                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10390                                 ;
10391                         continue;
10392                 }
10393                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10394                 {
10395                         rsurface.lightmaptexture = NULL;
10396                         rsurface.deluxemaptexture = NULL;
10397                         rsurface.uselightmaptexture = false;
10398                         // simply scan ahead until we find a different texture or lightmap state
10399                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10400                                 ;
10401                 }
10402                 else
10403                 {
10404                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10405                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10406                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10407                         // simply scan ahead until we find a different texture or lightmap state
10408                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10409                                 ;
10410                 }
10411                 // render the range of surfaces
10412                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10413         }
10414         R_FrameData_ReturnToMark();
10415 }
10416
10417 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10418 {
10419         CHECKGLERROR
10420         if (depthonly)
10421                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10422         else if (prepass)
10423         {
10424                 if (!rsurface.texture->currentnumlayers)
10425                         return;
10426                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10427                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10428                 else
10429                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10430         }
10431         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10432                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10433         else if (!rsurface.texture->currentnumlayers)
10434                 return;
10435         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10436         {
10437                 // in the deferred case, transparent surfaces were queued during prepass
10438                 if (!r_shadow_usingdeferredprepass)
10439                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10440         }
10441         else
10442         {
10443                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10444                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10445         }
10446         CHECKGLERROR
10447 }
10448
10449 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10450 {
10451         int i, j;
10452         texture_t *texture;
10453         R_FrameData_SetMark();
10454         // break the surface list down into batches by texture and use of lightmapping
10455         for (i = 0;i < numsurfaces;i = j)
10456         {
10457                 j = i + 1;
10458                 // texture is the base texture pointer, rsurface.texture is the
10459                 // current frame/skin the texture is directing us to use (for example
10460                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10461                 // use skin 1 instead)
10462                 texture = surfacelist[i]->texture;
10463                 rsurface.texture = R_GetCurrentTexture(texture);
10464                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10465                 {
10466                         // if this texture is not the kind we want, skip ahead to the next one
10467                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10468                                 ;
10469                         continue;
10470                 }
10471                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10472                 {
10473                         rsurface.lightmaptexture = NULL;
10474                         rsurface.deluxemaptexture = NULL;
10475                         rsurface.uselightmaptexture = false;
10476                         // simply scan ahead until we find a different texture or lightmap state
10477                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10478                                 ;
10479                 }
10480                 else
10481                 {
10482                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10483                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10484                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10485                         // simply scan ahead until we find a different texture or lightmap state
10486                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10487                                 ;
10488                 }
10489                 // render the range of surfaces
10490                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10491         }
10492         R_FrameData_ReturnToMark();
10493 }
10494
10495 float locboxvertex3f[6*4*3] =
10496 {
10497         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10498         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10499         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10500         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10501         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10502         1,0,0, 0,0,0, 0,1,0, 1,1,0
10503 };
10504
10505 unsigned short locboxelements[6*2*3] =
10506 {
10507          0, 1, 2, 0, 2, 3,
10508          4, 5, 6, 4, 6, 7,
10509          8, 9,10, 8,10,11,
10510         12,13,14, 12,14,15,
10511         16,17,18, 16,18,19,
10512         20,21,22, 20,22,23
10513 };
10514
10515 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10516 {
10517         int i, j;
10518         cl_locnode_t *loc = (cl_locnode_t *)ent;
10519         vec3_t mins, size;
10520         float vertex3f[6*4*3];
10521         CHECKGLERROR
10522         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10523         GL_DepthMask(false);
10524         GL_DepthRange(0, 1);
10525         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10526         GL_DepthTest(true);
10527         GL_CullFace(GL_NONE);
10528         R_EntityMatrix(&identitymatrix);
10529
10530 //      R_Mesh_ResetTextureState();
10531
10532         i = surfacelist[0];
10533         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10534                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10535                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10536                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10537
10538         if (VectorCompare(loc->mins, loc->maxs))
10539         {
10540                 VectorSet(size, 2, 2, 2);
10541                 VectorMA(loc->mins, -0.5f, size, mins);
10542         }
10543         else
10544         {
10545                 VectorCopy(loc->mins, mins);
10546                 VectorSubtract(loc->maxs, loc->mins, size);
10547         }
10548
10549         for (i = 0;i < 6*4*3;)
10550                 for (j = 0;j < 3;j++, i++)
10551                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10552
10553         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10554         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10555         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10556 }
10557
10558 void R_DrawLocs(void)
10559 {
10560         int index;
10561         cl_locnode_t *loc, *nearestloc;
10562         vec3_t center;
10563         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10564         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10565         {
10566                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10567                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10568         }
10569 }
10570
10571 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10572 {
10573         if (decalsystem->decals)
10574                 Mem_Free(decalsystem->decals);
10575         memset(decalsystem, 0, sizeof(*decalsystem));
10576 }
10577
10578 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)
10579 {
10580         tridecal_t *decal;
10581         tridecal_t *decals;
10582         int i;
10583
10584         // expand or initialize the system
10585         if (decalsystem->maxdecals <= decalsystem->numdecals)
10586         {
10587                 decalsystem_t old = *decalsystem;
10588                 qboolean useshortelements;
10589                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10590                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10591                 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)));
10592                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10593                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10594                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10595                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10596                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10597                 if (decalsystem->numdecals)
10598                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10599                 if (old.decals)
10600                         Mem_Free(old.decals);
10601                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10602                         decalsystem->element3i[i] = i;
10603                 if (useshortelements)
10604                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10605                                 decalsystem->element3s[i] = i;
10606         }
10607
10608         // grab a decal and search for another free slot for the next one
10609         decals = decalsystem->decals;
10610         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10611         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10612                 ;
10613         decalsystem->freedecal = i;
10614         if (decalsystem->numdecals <= i)
10615                 decalsystem->numdecals = i + 1;
10616
10617         // initialize the decal
10618         decal->lived = 0;
10619         decal->triangleindex = triangleindex;
10620         decal->surfaceindex = surfaceindex;
10621         decal->decalsequence = decalsequence;
10622         decal->color4f[0][0] = c0[0];
10623         decal->color4f[0][1] = c0[1];
10624         decal->color4f[0][2] = c0[2];
10625         decal->color4f[0][3] = 1;
10626         decal->color4f[1][0] = c1[0];
10627         decal->color4f[1][1] = c1[1];
10628         decal->color4f[1][2] = c1[2];
10629         decal->color4f[1][3] = 1;
10630         decal->color4f[2][0] = c2[0];
10631         decal->color4f[2][1] = c2[1];
10632         decal->color4f[2][2] = c2[2];
10633         decal->color4f[2][3] = 1;
10634         decal->vertex3f[0][0] = v0[0];
10635         decal->vertex3f[0][1] = v0[1];
10636         decal->vertex3f[0][2] = v0[2];
10637         decal->vertex3f[1][0] = v1[0];
10638         decal->vertex3f[1][1] = v1[1];
10639         decal->vertex3f[1][2] = v1[2];
10640         decal->vertex3f[2][0] = v2[0];
10641         decal->vertex3f[2][1] = v2[1];
10642         decal->vertex3f[2][2] = v2[2];
10643         decal->texcoord2f[0][0] = t0[0];
10644         decal->texcoord2f[0][1] = t0[1];
10645         decal->texcoord2f[1][0] = t1[0];
10646         decal->texcoord2f[1][1] = t1[1];
10647         decal->texcoord2f[2][0] = t2[0];
10648         decal->texcoord2f[2][1] = t2[1];
10649         TriangleNormal(v0, v1, v2, decal->plane);
10650         VectorNormalize(decal->plane);
10651         decal->plane[3] = DotProduct(v0, decal->plane);
10652 }
10653
10654 extern cvar_t cl_decals_bias;
10655 extern cvar_t cl_decals_models;
10656 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10657 // baseparms, parms, temps
10658 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)
10659 {
10660         int cornerindex;
10661         int index;
10662         float v[9][3];
10663         const float *vertex3f;
10664         const float *normal3f;
10665         int numpoints;
10666         float points[2][9][3];
10667         float temp[3];
10668         float tc[9][2];
10669         float f;
10670         float c[9][4];
10671         const int *e;
10672
10673         e = rsurface.modelelement3i + 3*triangleindex;
10674
10675         vertex3f = rsurface.modelvertex3f;
10676         normal3f = rsurface.modelnormal3f;
10677
10678         if (normal3f)
10679         {
10680                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10681                 {
10682                         index = 3*e[cornerindex];
10683                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10684                 }
10685         }
10686         else
10687         {
10688                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10689                 {
10690                         index = 3*e[cornerindex];
10691                         VectorCopy(vertex3f + index, v[cornerindex]);
10692                 }
10693         }
10694
10695         // cull backfaces
10696         //TriangleNormal(v[0], v[1], v[2], normal);
10697         //if (DotProduct(normal, localnormal) < 0.0f)
10698         //      continue;
10699         // clip by each of the box planes formed from the projection matrix
10700         // if anything survives, we emit the decal
10701         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]);
10702         if (numpoints < 3)
10703                 return;
10704         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]);
10705         if (numpoints < 3)
10706                 return;
10707         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]);
10708         if (numpoints < 3)
10709                 return;
10710         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]);
10711         if (numpoints < 3)
10712                 return;
10713         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]);
10714         if (numpoints < 3)
10715                 return;
10716         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]);
10717         if (numpoints < 3)
10718                 return;
10719         // some part of the triangle survived, so we have to accept it...
10720         if (dynamic)
10721         {
10722                 // dynamic always uses the original triangle
10723                 numpoints = 3;
10724                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10725                 {
10726                         index = 3*e[cornerindex];
10727                         VectorCopy(vertex3f + index, v[cornerindex]);
10728                 }
10729         }
10730         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10731         {
10732                 // convert vertex positions to texcoords
10733                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10734                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10735                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10736                 // calculate distance fade from the projection origin
10737                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10738                 f = bound(0.0f, f, 1.0f);
10739                 c[cornerindex][0] = r * f;
10740                 c[cornerindex][1] = g * f;
10741                 c[cornerindex][2] = b * f;
10742                 c[cornerindex][3] = 1.0f;
10743                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10744         }
10745         if (dynamic)
10746                 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);
10747         else
10748                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10749                         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);
10750 }
10751 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)
10752 {
10753         matrix4x4_t projection;
10754         decalsystem_t *decalsystem;
10755         qboolean dynamic;
10756         dp_model_t *model;
10757         const msurface_t *surface;
10758         const msurface_t *surfaces;
10759         const int *surfacelist;
10760         const texture_t *texture;
10761         int numtriangles;
10762         int numsurfacelist;
10763         int surfacelistindex;
10764         int surfaceindex;
10765         int triangleindex;
10766         float localorigin[3];
10767         float localnormal[3];
10768         float localmins[3];
10769         float localmaxs[3];
10770         float localsize;
10771         //float normal[3];
10772         float planes[6][4];
10773         float angles[3];
10774         bih_t *bih;
10775         int bih_triangles_count;
10776         int bih_triangles[256];
10777         int bih_surfaces[256];
10778
10779         decalsystem = &ent->decalsystem;
10780         model = ent->model;
10781         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10782         {
10783                 R_DecalSystem_Reset(&ent->decalsystem);
10784                 return;
10785         }
10786
10787         if (!model->brush.data_leafs && !cl_decals_models.integer)
10788         {
10789                 if (decalsystem->model)
10790                         R_DecalSystem_Reset(decalsystem);
10791                 return;
10792         }
10793
10794         if (decalsystem->model != model)
10795                 R_DecalSystem_Reset(decalsystem);
10796         decalsystem->model = model;
10797
10798         RSurf_ActiveModelEntity(ent, true, false, false);
10799
10800         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10801         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10802         VectorNormalize(localnormal);
10803         localsize = worldsize*rsurface.inversematrixscale;
10804         localmins[0] = localorigin[0] - localsize;
10805         localmins[1] = localorigin[1] - localsize;
10806         localmins[2] = localorigin[2] - localsize;
10807         localmaxs[0] = localorigin[0] + localsize;
10808         localmaxs[1] = localorigin[1] + localsize;
10809         localmaxs[2] = localorigin[2] + localsize;
10810
10811         //VectorCopy(localnormal, planes[4]);
10812         //VectorVectors(planes[4], planes[2], planes[0]);
10813         AnglesFromVectors(angles, localnormal, NULL, false);
10814         AngleVectors(angles, planes[0], planes[2], planes[4]);
10815         VectorNegate(planes[0], planes[1]);
10816         VectorNegate(planes[2], planes[3]);
10817         VectorNegate(planes[4], planes[5]);
10818         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10819         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10820         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10821         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10822         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10823         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10824
10825 #if 1
10826 // works
10827 {
10828         matrix4x4_t forwardprojection;
10829         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10830         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10831 }
10832 #else
10833 // broken
10834 {
10835         float projectionvector[4][3];
10836         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10837         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10838         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10839         projectionvector[0][0] = planes[0][0] * ilocalsize;
10840         projectionvector[0][1] = planes[1][0] * ilocalsize;
10841         projectionvector[0][2] = planes[2][0] * ilocalsize;
10842         projectionvector[1][0] = planes[0][1] * ilocalsize;
10843         projectionvector[1][1] = planes[1][1] * ilocalsize;
10844         projectionvector[1][2] = planes[2][1] * ilocalsize;
10845         projectionvector[2][0] = planes[0][2] * ilocalsize;
10846         projectionvector[2][1] = planes[1][2] * ilocalsize;
10847         projectionvector[2][2] = planes[2][2] * ilocalsize;
10848         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10849         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10850         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10851         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10852 }
10853 #endif
10854
10855         dynamic = model->surfmesh.isanimated;
10856         numsurfacelist = model->nummodelsurfaces;
10857         surfacelist = model->sortedmodelsurfaces;
10858         surfaces = model->data_surfaces;
10859
10860         bih = NULL;
10861         bih_triangles_count = -1;
10862         if(!dynamic)
10863         {
10864                 if(model->render_bih.numleafs)
10865                         bih = &model->render_bih;
10866                 else if(model->collision_bih.numleafs)
10867                         bih = &model->collision_bih;
10868         }
10869         if(bih)
10870                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10871         if(bih_triangles_count == 0)
10872                 return;
10873         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10874                 return;
10875         if(bih_triangles_count > 0)
10876         {
10877                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10878                 {
10879                         surfaceindex = bih_surfaces[triangleindex];
10880                         surface = surfaces + surfaceindex;
10881                         texture = surface->texture;
10882                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10883                                 continue;
10884                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10885                                 continue;
10886                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10887                 }
10888         }
10889         else
10890         {
10891                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10892                 {
10893                         surfaceindex = surfacelist[surfacelistindex];
10894                         surface = surfaces + surfaceindex;
10895                         // check cull box first because it rejects more than any other check
10896                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10897                                 continue;
10898                         // skip transparent surfaces
10899                         texture = surface->texture;
10900                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10901                                 continue;
10902                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10903                                 continue;
10904                         numtriangles = surface->num_triangles;
10905                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10906                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10907                 }
10908         }
10909 }
10910
10911 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10912 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)
10913 {
10914         int renderentityindex;
10915         float worldmins[3];
10916         float worldmaxs[3];
10917         entity_render_t *ent;
10918
10919         if (!cl_decals_newsystem.integer)
10920                 return;
10921
10922         worldmins[0] = worldorigin[0] - worldsize;
10923         worldmins[1] = worldorigin[1] - worldsize;
10924         worldmins[2] = worldorigin[2] - worldsize;
10925         worldmaxs[0] = worldorigin[0] + worldsize;
10926         worldmaxs[1] = worldorigin[1] + worldsize;
10927         worldmaxs[2] = worldorigin[2] + worldsize;
10928
10929         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10930
10931         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10932         {
10933                 ent = r_refdef.scene.entities[renderentityindex];
10934                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10935                         continue;
10936
10937                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10938         }
10939 }
10940
10941 typedef struct r_decalsystem_splatqueue_s
10942 {
10943         vec3_t worldorigin;
10944         vec3_t worldnormal;
10945         float color[4];
10946         float tcrange[4];
10947         float worldsize;
10948         int decalsequence;
10949 }
10950 r_decalsystem_splatqueue_t;
10951
10952 int r_decalsystem_numqueued = 0;
10953 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10954
10955 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)
10956 {
10957         r_decalsystem_splatqueue_t *queue;
10958
10959         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10960                 return;
10961
10962         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10963         VectorCopy(worldorigin, queue->worldorigin);
10964         VectorCopy(worldnormal, queue->worldnormal);
10965         Vector4Set(queue->color, r, g, b, a);
10966         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10967         queue->worldsize = worldsize;
10968         queue->decalsequence = cl.decalsequence++;
10969 }
10970
10971 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10972 {
10973         int i;
10974         r_decalsystem_splatqueue_t *queue;
10975
10976         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10977                 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);
10978         r_decalsystem_numqueued = 0;
10979 }
10980
10981 extern cvar_t cl_decals_max;
10982 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10983 {
10984         int i;
10985         decalsystem_t *decalsystem = &ent->decalsystem;
10986         int numdecals;
10987         int killsequence;
10988         tridecal_t *decal;
10989         float frametime;
10990         float lifetime;
10991
10992         if (!decalsystem->numdecals)
10993                 return;
10994
10995         if (r_showsurfaces.integer)
10996                 return;
10997
10998         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
10999         {
11000                 R_DecalSystem_Reset(decalsystem);
11001                 return;
11002         }
11003
11004         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11005         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11006
11007         if (decalsystem->lastupdatetime)
11008                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11009         else
11010                 frametime = 0;
11011         decalsystem->lastupdatetime = r_refdef.scene.time;
11012         decal = decalsystem->decals;
11013         numdecals = decalsystem->numdecals;
11014
11015         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11016         {
11017                 if (decal->color4f[0][3])
11018                 {
11019                         decal->lived += frametime;
11020                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11021                         {
11022                                 memset(decal, 0, sizeof(*decal));
11023                                 if (decalsystem->freedecal > i)
11024                                         decalsystem->freedecal = i;
11025                         }
11026                 }
11027         }
11028         decal = decalsystem->decals;
11029         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11030                 numdecals--;
11031
11032         // collapse the array by shuffling the tail decals into the gaps
11033         for (;;)
11034         {
11035                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11036                         decalsystem->freedecal++;
11037                 if (decalsystem->freedecal == numdecals)
11038                         break;
11039                 decal[decalsystem->freedecal] = decal[--numdecals];
11040         }
11041
11042         decalsystem->numdecals = numdecals;
11043
11044         if (numdecals <= 0)
11045         {
11046                 // if there are no decals left, reset decalsystem
11047                 R_DecalSystem_Reset(decalsystem);
11048         }
11049 }
11050
11051 extern skinframe_t *decalskinframe;
11052 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11053 {
11054         int i;
11055         decalsystem_t *decalsystem = &ent->decalsystem;
11056         int numdecals;
11057         tridecal_t *decal;
11058         float faderate;
11059         float alpha;
11060         float *v3f;
11061         float *c4f;
11062         float *t2f;
11063         const int *e;
11064         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11065         int numtris = 0;
11066
11067         numdecals = decalsystem->numdecals;
11068         if (!numdecals)
11069                 return;
11070
11071         if (r_showsurfaces.integer)
11072                 return;
11073
11074         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11075         {
11076                 R_DecalSystem_Reset(decalsystem);
11077                 return;
11078         }
11079
11080         // if the model is static it doesn't matter what value we give for
11081         // wantnormals and wanttangents, so this logic uses only rules applicable
11082         // to a model, knowing that they are meaningless otherwise
11083         if (ent == r_refdef.scene.worldentity)
11084                 RSurf_ActiveWorldEntity();
11085         else
11086                 RSurf_ActiveModelEntity(ent, false, false, false);
11087
11088         decalsystem->lastupdatetime = r_refdef.scene.time;
11089         decal = decalsystem->decals;
11090
11091         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11092
11093         // update vertex positions for animated models
11094         v3f = decalsystem->vertex3f;
11095         c4f = decalsystem->color4f;
11096         t2f = decalsystem->texcoord2f;
11097         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11098         {
11099                 if (!decal->color4f[0][3])
11100                         continue;
11101
11102                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11103                         continue;
11104
11105                 // skip backfaces
11106                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11107                         continue;
11108
11109                 // update color values for fading decals
11110                 if (decal->lived >= cl_decals_time.value)
11111                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11112                 else
11113                         alpha = 1.0f;
11114
11115                 c4f[ 0] = decal->color4f[0][0] * alpha;
11116                 c4f[ 1] = decal->color4f[0][1] * alpha;
11117                 c4f[ 2] = decal->color4f[0][2] * alpha;
11118                 c4f[ 3] = 1;
11119                 c4f[ 4] = decal->color4f[1][0] * alpha;
11120                 c4f[ 5] = decal->color4f[1][1] * alpha;
11121                 c4f[ 6] = decal->color4f[1][2] * alpha;
11122                 c4f[ 7] = 1;
11123                 c4f[ 8] = decal->color4f[2][0] * alpha;
11124                 c4f[ 9] = decal->color4f[2][1] * alpha;
11125                 c4f[10] = decal->color4f[2][2] * alpha;
11126                 c4f[11] = 1;
11127
11128                 t2f[0] = decal->texcoord2f[0][0];
11129                 t2f[1] = decal->texcoord2f[0][1];
11130                 t2f[2] = decal->texcoord2f[1][0];
11131                 t2f[3] = decal->texcoord2f[1][1];
11132                 t2f[4] = decal->texcoord2f[2][0];
11133                 t2f[5] = decal->texcoord2f[2][1];
11134
11135                 // update vertex positions for animated models
11136                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11137                 {
11138                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11139                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11140                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11141                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11142                 }
11143                 else
11144                 {
11145                         VectorCopy(decal->vertex3f[0], v3f);
11146                         VectorCopy(decal->vertex3f[1], v3f + 3);
11147                         VectorCopy(decal->vertex3f[2], v3f + 6);
11148                 }
11149
11150                 if (r_refdef.fogenabled)
11151                 {
11152                         alpha = RSurf_FogVertex(v3f);
11153                         VectorScale(c4f, alpha, c4f);
11154                         alpha = RSurf_FogVertex(v3f + 3);
11155                         VectorScale(c4f + 4, alpha, c4f + 4);
11156                         alpha = RSurf_FogVertex(v3f + 6);
11157                         VectorScale(c4f + 8, alpha, c4f + 8);
11158                 }
11159
11160                 v3f += 9;
11161                 c4f += 12;
11162                 t2f += 6;
11163                 numtris++;
11164         }
11165
11166         if (numtris > 0)
11167         {
11168                 r_refdef.stats.drawndecals += numtris;
11169
11170                 // now render the decals all at once
11171                 // (this assumes they all use one particle font texture!)
11172                 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);
11173 //              R_Mesh_ResetTextureState();
11174                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11175                 GL_DepthMask(false);
11176                 GL_DepthRange(0, 1);
11177                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11178                 GL_DepthTest(true);
11179                 GL_CullFace(GL_NONE);
11180                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11181                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11182                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11183         }
11184 }
11185
11186 static void R_DrawModelDecals(void)
11187 {
11188         int i, numdecals;
11189
11190         // fade faster when there are too many decals
11191         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11192         for (i = 0;i < r_refdef.scene.numentities;i++)
11193                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11194
11195         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11196         for (i = 0;i < r_refdef.scene.numentities;i++)
11197                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11198                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11199
11200         R_DecalSystem_ApplySplatEntitiesQueue();
11201
11202         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11203         for (i = 0;i < r_refdef.scene.numentities;i++)
11204                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11205
11206         r_refdef.stats.totaldecals += numdecals;
11207
11208         if (r_showsurfaces.integer)
11209                 return;
11210
11211         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11212
11213         for (i = 0;i < r_refdef.scene.numentities;i++)
11214         {
11215                 if (!r_refdef.viewcache.entityvisible[i])
11216                         continue;
11217                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11218                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11219         }
11220 }
11221
11222 extern cvar_t mod_collision_bih;
11223 void R_DrawDebugModel(void)
11224 {
11225         entity_render_t *ent = rsurface.entity;
11226         int i, j, k, l, flagsmask;
11227         const msurface_t *surface;
11228         dp_model_t *model = ent->model;
11229         vec3_t v;
11230
11231         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11232                 return;
11233
11234         if (r_showoverdraw.value > 0)
11235         {
11236                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11237                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11238                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11239                 GL_DepthTest(false);
11240                 GL_DepthMask(false);
11241                 GL_DepthRange(0, 1);
11242                 GL_BlendFunc(GL_ONE, GL_ONE);
11243                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11244                 {
11245                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11246                                 continue;
11247                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11248                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11249                         {
11250                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11251                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11252                                 if (!rsurface.texture->currentlayers->depthmask)
11253                                         GL_Color(c, 0, 0, 1.0f);
11254                                 else if (ent == r_refdef.scene.worldentity)
11255                                         GL_Color(c, c, c, 1.0f);
11256                                 else
11257                                         GL_Color(0, c, 0, 1.0f);
11258                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11259                                 RSurf_DrawBatch();
11260                         }
11261                 }
11262                 rsurface.texture = NULL;
11263         }
11264
11265         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11266
11267 //      R_Mesh_ResetTextureState();
11268         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11269         GL_DepthRange(0, 1);
11270         GL_DepthTest(!r_showdisabledepthtest.integer);
11271         GL_DepthMask(false);
11272         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11273
11274         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11275         {
11276                 int triangleindex;
11277                 int bihleafindex;
11278                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11279                 const q3mbrush_t *brush;
11280                 const bih_t *bih = &model->collision_bih;
11281                 const bih_leaf_t *bihleaf;
11282                 float vertex3f[3][3];
11283                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11284                 cullbox = false;
11285                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11286                 {
11287                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11288                                 continue;
11289                         switch (bihleaf->type)
11290                         {
11291                         case BIH_BRUSH:
11292                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11293                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11294                                 {
11295                                         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);
11296                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11297                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11298                                 }
11299                                 break;
11300                         case BIH_COLLISIONTRIANGLE:
11301                                 triangleindex = bihleaf->itemindex;
11302                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11303                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11304                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11305                                 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);
11306                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11307                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11308                                 break;
11309                         case BIH_RENDERTRIANGLE:
11310                                 triangleindex = bihleaf->itemindex;
11311                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11312                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11313                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11314                                 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);
11315                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11316                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11317                                 break;
11318                         }
11319                 }
11320         }
11321
11322         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11323
11324         if (r_showtris.integer && qglPolygonMode)
11325         {
11326                 if (r_showdisabledepthtest.integer)
11327                 {
11328                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11329                         GL_DepthMask(false);
11330                 }
11331                 else
11332                 {
11333                         GL_BlendFunc(GL_ONE, GL_ZERO);
11334                         GL_DepthMask(true);
11335                 }
11336                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11337                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11338                 {
11339                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11340                                 continue;
11341                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11342                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11343                         {
11344                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11345                                 if (!rsurface.texture->currentlayers->depthmask)
11346                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11347                                 else if (ent == r_refdef.scene.worldentity)
11348                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11349                                 else
11350                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11351                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11352                                 RSurf_DrawBatch();
11353                         }
11354                 }
11355                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11356                 rsurface.texture = NULL;
11357         }
11358
11359         if (r_shownormals.value != 0 && qglBegin)
11360         {
11361                 if (r_showdisabledepthtest.integer)
11362                 {
11363                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11364                         GL_DepthMask(false);
11365                 }
11366                 else
11367                 {
11368                         GL_BlendFunc(GL_ONE, GL_ZERO);
11369                         GL_DepthMask(true);
11370                 }
11371                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11372                 {
11373                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11374                                 continue;
11375                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11376                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11377                         {
11378                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11379                                 qglBegin(GL_LINES);
11380                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11381                                 {
11382                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11383                                         {
11384                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11385                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11386                                                 qglVertex3f(v[0], v[1], v[2]);
11387                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11388                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11389                                                 qglVertex3f(v[0], v[1], v[2]);
11390                                         }
11391                                 }
11392                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11393                                 {
11394                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11395                                         {
11396                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11397                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11398                                                 qglVertex3f(v[0], v[1], v[2]);
11399                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11400                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11401                                                 qglVertex3f(v[0], v[1], v[2]);
11402                                         }
11403                                 }
11404                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11405                                 {
11406                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11407                                         {
11408                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11409                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11410                                                 qglVertex3f(v[0], v[1], v[2]);
11411                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11412                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11413                                                 qglVertex3f(v[0], v[1], v[2]);
11414                                         }
11415                                 }
11416                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11417                                 {
11418                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11419                                         {
11420                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11421                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11422                                                 qglVertex3f(v[0], v[1], v[2]);
11423                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11424                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11425                                                 qglVertex3f(v[0], v[1], v[2]);
11426                                         }
11427                                 }
11428                                 qglEnd();
11429                                 CHECKGLERROR
11430                         }
11431                 }
11432                 rsurface.texture = NULL;
11433         }
11434 }
11435
11436 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11437 int r_maxsurfacelist = 0;
11438 const msurface_t **r_surfacelist = NULL;
11439 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11440 {
11441         int i, j, endj, flagsmask;
11442         dp_model_t *model = r_refdef.scene.worldmodel;
11443         msurface_t *surfaces;
11444         unsigned char *update;
11445         int numsurfacelist = 0;
11446         if (model == NULL)
11447                 return;
11448
11449         if (r_maxsurfacelist < model->num_surfaces)
11450         {
11451                 r_maxsurfacelist = model->num_surfaces;
11452                 if (r_surfacelist)
11453                         Mem_Free((msurface_t**)r_surfacelist);
11454                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11455         }
11456
11457         RSurf_ActiveWorldEntity();
11458
11459         surfaces = model->data_surfaces;
11460         update = model->brushq1.lightmapupdateflags;
11461
11462         // update light styles on this submodel
11463         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11464         {
11465                 model_brush_lightstyleinfo_t *style;
11466                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11467                 {
11468                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11469                         {
11470                                 int *list = style->surfacelist;
11471                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11472                                 for (j = 0;j < style->numsurfaces;j++)
11473                                         update[list[j]] = true;
11474                         }
11475                 }
11476         }
11477
11478         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11479
11480         if (debug)
11481         {
11482                 R_DrawDebugModel();
11483                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11484                 return;
11485         }
11486
11487         rsurface.lightmaptexture = NULL;
11488         rsurface.deluxemaptexture = NULL;
11489         rsurface.uselightmaptexture = false;
11490         rsurface.texture = NULL;
11491         rsurface.rtlight = NULL;
11492         numsurfacelist = 0;
11493         // add visible surfaces to draw list
11494         for (i = 0;i < model->nummodelsurfaces;i++)
11495         {
11496                 j = model->sortedmodelsurfaces[i];
11497                 if (r_refdef.viewcache.world_surfacevisible[j])
11498                         r_surfacelist[numsurfacelist++] = surfaces + j;
11499         }
11500         // update lightmaps if needed
11501         if (model->brushq1.firstrender)
11502         {
11503                 model->brushq1.firstrender = false;
11504                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11505                         if (update[j])
11506                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11507         }
11508         else if (update)
11509         {
11510                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11511                         if (r_refdef.viewcache.world_surfacevisible[j])
11512                                 if (update[j])
11513                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11514         }
11515         // don't do anything if there were no surfaces
11516         if (!numsurfacelist)
11517         {
11518                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11519                 return;
11520         }
11521         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11522
11523         // add to stats if desired
11524         if (r_speeds.integer && !skysurfaces && !depthonly)
11525         {
11526                 r_refdef.stats.world_surfaces += numsurfacelist;
11527                 for (j = 0;j < numsurfacelist;j++)
11528                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11529         }
11530
11531         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11532 }
11533
11534 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11535 {
11536         int i, j, endj, flagsmask;
11537         dp_model_t *model = ent->model;
11538         msurface_t *surfaces;
11539         unsigned char *update;
11540         int numsurfacelist = 0;
11541         if (model == NULL)
11542                 return;
11543
11544         if (r_maxsurfacelist < model->num_surfaces)
11545         {
11546                 r_maxsurfacelist = model->num_surfaces;
11547                 if (r_surfacelist)
11548                         Mem_Free((msurface_t **)r_surfacelist);
11549                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11550         }
11551
11552         // if the model is static it doesn't matter what value we give for
11553         // wantnormals and wanttangents, so this logic uses only rules applicable
11554         // to a model, knowing that they are meaningless otherwise
11555         if (ent == r_refdef.scene.worldentity)
11556                 RSurf_ActiveWorldEntity();
11557         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11558                 RSurf_ActiveModelEntity(ent, false, false, false);
11559         else if (prepass)
11560                 RSurf_ActiveModelEntity(ent, true, true, true);
11561         else if (depthonly)
11562         {
11563                 switch (vid.renderpath)
11564                 {
11565                 case RENDERPATH_GL20:
11566                 case RENDERPATH_D3D9:
11567                 case RENDERPATH_D3D10:
11568                 case RENDERPATH_D3D11:
11569                 case RENDERPATH_SOFT:
11570                 case RENDERPATH_GLES2:
11571                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11572                         break;
11573                 case RENDERPATH_GL11:
11574                 case RENDERPATH_GL13:
11575                 case RENDERPATH_GLES1:
11576                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11577                         break;
11578                 }
11579         }
11580         else
11581         {
11582                 switch (vid.renderpath)
11583                 {
11584                 case RENDERPATH_GL20:
11585                 case RENDERPATH_D3D9:
11586                 case RENDERPATH_D3D10:
11587                 case RENDERPATH_D3D11:
11588                 case RENDERPATH_SOFT:
11589                 case RENDERPATH_GLES2:
11590                         RSurf_ActiveModelEntity(ent, true, true, false);
11591                         break;
11592                 case RENDERPATH_GL11:
11593                 case RENDERPATH_GL13:
11594                 case RENDERPATH_GLES1:
11595                         RSurf_ActiveModelEntity(ent, true, false, false);
11596                         break;
11597                 }
11598         }
11599
11600         surfaces = model->data_surfaces;
11601         update = model->brushq1.lightmapupdateflags;
11602
11603         // update light styles
11604         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11605         {
11606                 model_brush_lightstyleinfo_t *style;
11607                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11608                 {
11609                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11610                         {
11611                                 int *list = style->surfacelist;
11612                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11613                                 for (j = 0;j < style->numsurfaces;j++)
11614                                         update[list[j]] = true;
11615                         }
11616                 }
11617         }
11618
11619         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11620
11621         if (debug)
11622         {
11623                 R_DrawDebugModel();
11624                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11625                 return;
11626         }
11627
11628         rsurface.lightmaptexture = NULL;
11629         rsurface.deluxemaptexture = NULL;
11630         rsurface.uselightmaptexture = false;
11631         rsurface.texture = NULL;
11632         rsurface.rtlight = NULL;
11633         numsurfacelist = 0;
11634         // add visible surfaces to draw list
11635         for (i = 0;i < model->nummodelsurfaces;i++)
11636                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11637         // don't do anything if there were no surfaces
11638         if (!numsurfacelist)
11639         {
11640                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11641                 return;
11642         }
11643         // update lightmaps if needed
11644         if (update)
11645         {
11646                 int updated = 0;
11647                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11648                 {
11649                         if (update[j])
11650                         {
11651                                 updated++;
11652                                 R_BuildLightMap(ent, surfaces + j);
11653                         }
11654                 }
11655         }
11656         if (update)
11657                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11658                         if (update[j])
11659                                 R_BuildLightMap(ent, surfaces + j);
11660         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11661
11662         // add to stats if desired
11663         if (r_speeds.integer && !skysurfaces && !depthonly)
11664         {
11665                 r_refdef.stats.entities_surfaces += numsurfacelist;
11666                 for (j = 0;j < numsurfacelist;j++)
11667                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11668         }
11669
11670         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11671 }
11672
11673 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11674 {
11675         static texture_t texture;
11676         static msurface_t surface;
11677         const msurface_t *surfacelist = &surface;
11678
11679         // fake enough texture and surface state to render this geometry
11680
11681         texture.update_lastrenderframe = -1; // regenerate this texture
11682         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11683         texture.currentskinframe = skinframe;
11684         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11685         texture.offsetmapping = OFFSETMAPPING_OFF;
11686         texture.offsetscale = 1;
11687         texture.specularscalemod = 1;
11688         texture.specularpowermod = 1;
11689
11690         surface.texture = &texture;
11691         surface.num_triangles = numtriangles;
11692         surface.num_firsttriangle = firsttriangle;
11693         surface.num_vertices = numvertices;
11694         surface.num_firstvertex = firstvertex;
11695
11696         // now render it
11697         rsurface.texture = R_GetCurrentTexture(surface.texture);
11698         rsurface.lightmaptexture = NULL;
11699         rsurface.deluxemaptexture = NULL;
11700         rsurface.uselightmaptexture = false;
11701         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11702 }
11703
11704 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)
11705 {
11706         static msurface_t surface;
11707         const msurface_t *surfacelist = &surface;
11708
11709         // fake enough texture and surface state to render this geometry
11710         surface.texture = texture;
11711         surface.num_triangles = numtriangles;
11712         surface.num_firsttriangle = firsttriangle;
11713         surface.num_vertices = numvertices;
11714         surface.num_firstvertex = firstvertex;
11715
11716         // now render it
11717         rsurface.texture = R_GetCurrentTexture(surface.texture);
11718         rsurface.lightmaptexture = NULL;
11719         rsurface.deluxemaptexture = NULL;
11720         rsurface.uselightmaptexture = false;
11721         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11722 }