]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
7656e011c6d79cbf208fb4b0d4e5c72c6476d190
[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", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 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"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 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)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 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"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 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"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 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)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 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"};
86 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"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 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"};
89 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"};
90 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"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 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)"};
99 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)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
103 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
104
105 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
106 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
107 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
108
109 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
110 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
111 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
112 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."};
113 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
114 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
115 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
116 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."};
117 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
118 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
119 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
120 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
121 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"};
122 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"};
123 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
124 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
126 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
127 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
128 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"};
129 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
130 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
131
132 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
133 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
134 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
135 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
136 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
137 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
138 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
139 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
140
141 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)"};
142 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"};
143
144 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
145 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
146 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
147
148 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"};
149 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"};
150 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
151 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
152 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"};
153 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)"};
154 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)"};
155 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
156
157 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)"};
158 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
159 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)"};
160 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
161 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)"};
162 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)"};
163 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
164 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
165 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)"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173
174 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)"};
175 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
176 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"};
177 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
178 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
179 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
180 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"};
181
182 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
183 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
184 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
185 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
186
187 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
188 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
189 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
190 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
191 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
192 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
193 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
194
195 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
196 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
197 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
198 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)"};
199 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
200 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
201 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
202 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
203 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
204 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
205 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
206
207 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"};
208
209 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"};
210
211 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
212
213 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
214
215 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
216 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"};
217
218 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."};
219
220 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)"};
221
222 extern cvar_t v_glslgamma;
223
224 extern qboolean v_flipped_state;
225
226 static struct r_bloomstate_s
227 {
228         qboolean enabled;
229         qboolean hdr;
230
231         int bloomwidth, bloomheight;
232
233         textype_t texturetype;
234         int viewfbo; // used to check if r_viewfbo cvar has changed
235
236         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
237         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
238         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
239
240         int screentexturewidth, screentextureheight;
241         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
242
243         int bloomtexturewidth, bloomtextureheight;
244         rtexture_t *texture_bloom;
245
246         // arrays for rendering the screen passes
247         float screentexcoord2f[8];
248         float bloomtexcoord2f[8];
249         float offsettexcoord2f[8];
250
251         r_viewport_t viewport;
252 }
253 r_bloomstate;
254
255 r_waterstate_t r_waterstate;
256
257 /// shadow volume bsp struct with automatically growing nodes buffer
258 svbsp_t r_svbsp;
259
260 rtexture_t *r_texture_blanknormalmap;
261 rtexture_t *r_texture_white;
262 rtexture_t *r_texture_grey128;
263 rtexture_t *r_texture_black;
264 rtexture_t *r_texture_notexture;
265 rtexture_t *r_texture_whitecube;
266 rtexture_t *r_texture_normalizationcube;
267 rtexture_t *r_texture_fogattenuation;
268 rtexture_t *r_texture_fogheighttexture;
269 rtexture_t *r_texture_gammaramps;
270 unsigned int r_texture_gammaramps_serial;
271 //rtexture_t *r_texture_fogintensity;
272 rtexture_t *r_texture_reflectcube;
273
274 // TODO: hash lookups?
275 typedef struct cubemapinfo_s
276 {
277         char basename[64];
278         rtexture_t *texture;
279 }
280 cubemapinfo_t;
281
282 int r_texture_numcubemaps;
283 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
284
285 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
286 unsigned int r_numqueries;
287 unsigned int r_maxqueries;
288
289 typedef struct r_qwskincache_s
290 {
291         char name[MAX_QPATH];
292         skinframe_t *skinframe;
293 }
294 r_qwskincache_t;
295
296 static r_qwskincache_t *r_qwskincache;
297 static int r_qwskincache_size;
298
299 /// vertex coordinates for a quad that covers the screen exactly
300 extern const float r_screenvertex3f[12];
301 extern const float r_d3dscreenvertex3f[12];
302 const float r_screenvertex3f[12] =
303 {
304         0, 0, 0,
305         1, 0, 0,
306         1, 1, 0,
307         0, 1, 0
308 };
309 const float r_d3dscreenvertex3f[12] =
310 {
311         0, 1, 0,
312         1, 1, 0,
313         1, 0, 0,
314         0, 0, 0
315 };
316
317 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
318 {
319         int i;
320         for (i = 0;i < verts;i++)
321         {
322                 out[0] = in[0] * r;
323                 out[1] = in[1] * g;
324                 out[2] = in[2] * b;
325                 out[3] = in[3];
326                 in += 4;
327                 out += 4;
328         }
329 }
330
331 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
332 {
333         int i;
334         for (i = 0;i < verts;i++)
335         {
336                 out[0] = r;
337                 out[1] = g;
338                 out[2] = b;
339                 out[3] = a;
340                 out += 4;
341         }
342 }
343
344 // FIXME: move this to client?
345 void FOG_clear(void)
346 {
347         if (gamemode == GAME_NEHAHRA)
348         {
349                 Cvar_Set("gl_fogenable", "0");
350                 Cvar_Set("gl_fogdensity", "0.2");
351                 Cvar_Set("gl_fogred", "0.3");
352                 Cvar_Set("gl_foggreen", "0.3");
353                 Cvar_Set("gl_fogblue", "0.3");
354         }
355         r_refdef.fog_density = 0;
356         r_refdef.fog_red = 0;
357         r_refdef.fog_green = 0;
358         r_refdef.fog_blue = 0;
359         r_refdef.fog_alpha = 1;
360         r_refdef.fog_start = 0;
361         r_refdef.fog_end = 16384;
362         r_refdef.fog_height = 1<<30;
363         r_refdef.fog_fadedepth = 128;
364         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
365 }
366
367 static void R_BuildBlankTextures(void)
368 {
369         unsigned char data[4];
370         data[2] = 128; // normal X
371         data[1] = 128; // normal Y
372         data[0] = 255; // normal Z
373         data[3] = 128; // height
374         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 255;
376         data[1] = 255;
377         data[2] = 255;
378         data[3] = 255;
379         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 128;
381         data[1] = 128;
382         data[2] = 128;
383         data[3] = 255;
384         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385         data[0] = 0;
386         data[1] = 0;
387         data[2] = 0;
388         data[3] = 255;
389         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 }
391
392 static void R_BuildNoTexture(void)
393 {
394         int x, y;
395         unsigned char pix[16][16][4];
396         // this makes a light grey/dark grey checkerboard texture
397         for (y = 0;y < 16;y++)
398         {
399                 for (x = 0;x < 16;x++)
400                 {
401                         if ((y < 8) ^ (x < 8))
402                         {
403                                 pix[y][x][0] = 128;
404                                 pix[y][x][1] = 128;
405                                 pix[y][x][2] = 128;
406                                 pix[y][x][3] = 255;
407                         }
408                         else
409                         {
410                                 pix[y][x][0] = 64;
411                                 pix[y][x][1] = 64;
412                                 pix[y][x][2] = 64;
413                                 pix[y][x][3] = 255;
414                         }
415                 }
416         }
417         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
418 }
419
420 static void R_BuildWhiteCube(void)
421 {
422         unsigned char data[6*1*1*4];
423         memset(data, 255, sizeof(data));
424         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
425 }
426
427 static void R_BuildNormalizationCube(void)
428 {
429         int x, y, side;
430         vec3_t v;
431         vec_t s, t, intensity;
432 #define NORMSIZE 64
433         unsigned char *data;
434         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
435         for (side = 0;side < 6;side++)
436         {
437                 for (y = 0;y < NORMSIZE;y++)
438                 {
439                         for (x = 0;x < NORMSIZE;x++)
440                         {
441                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
442                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 switch(side)
444                                 {
445                                 default:
446                                 case 0:
447                                         v[0] = 1;
448                                         v[1] = -t;
449                                         v[2] = -s;
450                                         break;
451                                 case 1:
452                                         v[0] = -1;
453                                         v[1] = -t;
454                                         v[2] = s;
455                                         break;
456                                 case 2:
457                                         v[0] = s;
458                                         v[1] = 1;
459                                         v[2] = t;
460                                         break;
461                                 case 3:
462                                         v[0] = s;
463                                         v[1] = -1;
464                                         v[2] = -t;
465                                         break;
466                                 case 4:
467                                         v[0] = s;
468                                         v[1] = -t;
469                                         v[2] = 1;
470                                         break;
471                                 case 5:
472                                         v[0] = -s;
473                                         v[1] = -t;
474                                         v[2] = -1;
475                                         break;
476                                 }
477                                 intensity = 127.0f / sqrt(DotProduct(v, v));
478                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
479                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
480                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
481                                 data[((side*64+y)*64+x)*4+3] = 255;
482                         }
483                 }
484         }
485         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
486         Mem_Free(data);
487 }
488
489 static void R_BuildFogTexture(void)
490 {
491         int x, b;
492 #define FOGWIDTH 256
493         unsigned char data1[FOGWIDTH][4];
494         //unsigned char data2[FOGWIDTH][4];
495         double d, r, alpha;
496
497         r_refdef.fogmasktable_start = r_refdef.fog_start;
498         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
499         r_refdef.fogmasktable_range = r_refdef.fogrange;
500         r_refdef.fogmasktable_density = r_refdef.fog_density;
501
502         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
503         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
504         {
505                 d = (x * r - r_refdef.fogmasktable_start);
506                 if(developer_extra.integer)
507                         Con_DPrintf("%f ", d);
508                 d = max(0, d);
509                 if (r_fog_exp2.integer)
510                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
511                 else
512                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
513                 if(developer_extra.integer)
514                         Con_DPrintf(" : %f ", alpha);
515                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
516                 if(developer_extra.integer)
517                         Con_DPrintf(" = %f\n", alpha);
518                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
519         }
520
521         for (x = 0;x < FOGWIDTH;x++)
522         {
523                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
524                 data1[x][0] = b;
525                 data1[x][1] = b;
526                 data1[x][2] = b;
527                 data1[x][3] = 255;
528                 //data2[x][0] = 255 - b;
529                 //data2[x][1] = 255 - b;
530                 //data2[x][2] = 255 - b;
531                 //data2[x][3] = 255;
532         }
533         if (r_texture_fogattenuation)
534         {
535                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
536                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537         }
538         else
539         {
540                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
541                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
542         }
543 }
544
545 static void R_BuildFogHeightTexture(void)
546 {
547         unsigned char *inpixels;
548         int size;
549         int x;
550         int y;
551         int j;
552         float c[4];
553         float f;
554         inpixels = NULL;
555         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
556         if (r_refdef.fogheighttexturename[0])
557                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
558         if (!inpixels)
559         {
560                 r_refdef.fog_height_tablesize = 0;
561                 if (r_texture_fogheighttexture)
562                         R_FreeTexture(r_texture_fogheighttexture);
563                 r_texture_fogheighttexture = NULL;
564                 if (r_refdef.fog_height_table2d)
565                         Mem_Free(r_refdef.fog_height_table2d);
566                 r_refdef.fog_height_table2d = NULL;
567                 if (r_refdef.fog_height_table1d)
568                         Mem_Free(r_refdef.fog_height_table1d);
569                 r_refdef.fog_height_table1d = NULL;
570                 return;
571         }
572         size = image_width;
573         r_refdef.fog_height_tablesize = size;
574         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
575         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
576         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
577         Mem_Free(inpixels);
578         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
579         // average fog color table accounting for every fog layer between a point
580         // and the camera.  (Note: attenuation is handled separately!)
581         for (y = 0;y < size;y++)
582         {
583                 for (x = 0;x < size;x++)
584                 {
585                         Vector4Clear(c);
586                         f = 0;
587                         if (x < y)
588                         {
589                                 for (j = x;j <= y;j++)
590                                 {
591                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
592                                         f++;
593                                 }
594                         }
595                         else
596                         {
597                                 for (j = x;j >= y;j--)
598                                 {
599                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
600                                         f++;
601                                 }
602                         }
603                         f = 1.0f / f;
604                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
605                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
608                 }
609         }
610         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
611 }
612
613 //=======================================================================================================================================================
614
615 static const char *builtinshaderstring =
616 #include "shader_glsl.h"
617 ;
618
619 const char *builtinhlslshaderstring =
620 #include "shader_hlsl.h"
621 ;
622
623 char *glslshaderstring = NULL;
624 char *hlslshaderstring = NULL;
625
626 //=======================================================================================================================================================
627
628 typedef struct shaderpermutationinfo_s
629 {
630         const char *pretext;
631         const char *name;
632 }
633 shaderpermutationinfo_t;
634
635 typedef struct shadermodeinfo_s
636 {
637         const char *vertexfilename;
638         const char *geometryfilename;
639         const char *fragmentfilename;
640         const char *pretext;
641         const char *name;
642 }
643 shadermodeinfo_t;
644
645 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
646 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
647 {
648         {"#define USEDIFFUSE\n", " diffuse"},
649         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
650         {"#define USEVIEWTINT\n", " viewtint"},
651         {"#define USECOLORMAPPING\n", " colormapping"},
652         {"#define USESATURATION\n", " saturation"},
653         {"#define USEFOGINSIDE\n", " foginside"},
654         {"#define USEFOGOUTSIDE\n", " fogoutside"},
655         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
656         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
657         {"#define USEGAMMARAMPS\n", " gammaramps"},
658         {"#define USECUBEFILTER\n", " cubefilter"},
659         {"#define USEGLOW\n", " glow"},
660         {"#define USEBLOOM\n", " bloom"},
661         {"#define USESPECULAR\n", " specular"},
662         {"#define USEPOSTPROCESSING\n", " postprocessing"},
663         {"#define USEREFLECTION\n", " reflection"},
664         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
665         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
666         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
667         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
668         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
669         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
670         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
671         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673         {"#define USEALPHAKILL\n", " alphakill"},
674         {"#define USEREFLECTCUBE\n", " reflectcube"},
675         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676         {"#define USEBOUNCEGRID\n", " bouncegrid"},
677         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
678         {"#define USETRIPPY\n", " trippy"},
679 };
680
681 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
682 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
700 };
701
702 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
703 {
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
720 };
721
722 struct r_glsl_permutation_s;
723 typedef struct r_glsl_permutation_s
724 {
725         /// hash lookup data
726         struct r_glsl_permutation_s *hashnext;
727         unsigned int mode;
728         unsigned int permutation;
729
730         /// indicates if we have tried compiling this permutation already
731         qboolean compiled;
732         /// 0 if compilation failed
733         int program;
734         // texture units assigned to each detected uniform
735         int tex_Texture_First;
736         int tex_Texture_Second;
737         int tex_Texture_GammaRamps;
738         int tex_Texture_Normal;
739         int tex_Texture_Color;
740         int tex_Texture_Gloss;
741         int tex_Texture_Glow;
742         int tex_Texture_SecondaryNormal;
743         int tex_Texture_SecondaryColor;
744         int tex_Texture_SecondaryGloss;
745         int tex_Texture_SecondaryGlow;
746         int tex_Texture_Pants;
747         int tex_Texture_Shirt;
748         int tex_Texture_FogHeightTexture;
749         int tex_Texture_FogMask;
750         int tex_Texture_Lightmap;
751         int tex_Texture_Deluxemap;
752         int tex_Texture_Attenuation;
753         int tex_Texture_Cube;
754         int tex_Texture_Refraction;
755         int tex_Texture_Reflection;
756         int tex_Texture_ShadowMap2D;
757         int tex_Texture_CubeProjection;
758         int tex_Texture_ScreenDepth;
759         int tex_Texture_ScreenNormalMap;
760         int tex_Texture_ScreenDiffuse;
761         int tex_Texture_ScreenSpecular;
762         int tex_Texture_ReflectMask;
763         int tex_Texture_ReflectCube;
764         int tex_Texture_BounceGrid;
765         /// locations of detected uniforms in program object, or -1 if not found
766         int loc_Texture_First;
767         int loc_Texture_Second;
768         int loc_Texture_GammaRamps;
769         int loc_Texture_Normal;
770         int loc_Texture_Color;
771         int loc_Texture_Gloss;
772         int loc_Texture_Glow;
773         int loc_Texture_SecondaryNormal;
774         int loc_Texture_SecondaryColor;
775         int loc_Texture_SecondaryGloss;
776         int loc_Texture_SecondaryGlow;
777         int loc_Texture_Pants;
778         int loc_Texture_Shirt;
779         int loc_Texture_FogHeightTexture;
780         int loc_Texture_FogMask;
781         int loc_Texture_Lightmap;
782         int loc_Texture_Deluxemap;
783         int loc_Texture_Attenuation;
784         int loc_Texture_Cube;
785         int loc_Texture_Refraction;
786         int loc_Texture_Reflection;
787         int loc_Texture_ShadowMap2D;
788         int loc_Texture_CubeProjection;
789         int loc_Texture_ScreenDepth;
790         int loc_Texture_ScreenNormalMap;
791         int loc_Texture_ScreenDiffuse;
792         int loc_Texture_ScreenSpecular;
793         int loc_Texture_ReflectMask;
794         int loc_Texture_ReflectCube;
795         int loc_Texture_BounceGrid;
796         int loc_Alpha;
797         int loc_BloomBlur_Parameters;
798         int loc_ClientTime;
799         int loc_Color_Ambient;
800         int loc_Color_Diffuse;
801         int loc_Color_Specular;
802         int loc_Color_Glow;
803         int loc_Color_Pants;
804         int loc_Color_Shirt;
805         int loc_DeferredColor_Ambient;
806         int loc_DeferredColor_Diffuse;
807         int loc_DeferredColor_Specular;
808         int loc_DeferredMod_Diffuse;
809         int loc_DeferredMod_Specular;
810         int loc_DistortScaleRefractReflect;
811         int loc_EyePosition;
812         int loc_FogColor;
813         int loc_FogHeightFade;
814         int loc_FogPlane;
815         int loc_FogPlaneViewDist;
816         int loc_FogRangeRecip;
817         int loc_LightColor;
818         int loc_LightDir;
819         int loc_LightPosition;
820         int loc_OffsetMapping_ScaleSteps;
821         int loc_PixelSize;
822         int loc_ReflectColor;
823         int loc_ReflectFactor;
824         int loc_ReflectOffset;
825         int loc_RefractColor;
826         int loc_Saturation;
827         int loc_ScreenCenterRefractReflect;
828         int loc_ScreenScaleRefractReflect;
829         int loc_ScreenToDepth;
830         int loc_ShadowMap_Parameters;
831         int loc_ShadowMap_TextureScale;
832         int loc_SpecularPower;
833         int loc_UserVec1;
834         int loc_UserVec2;
835         int loc_UserVec3;
836         int loc_UserVec4;
837         int loc_ViewTintColor;
838         int loc_ViewToLight;
839         int loc_ModelToLight;
840         int loc_TexMatrix;
841         int loc_BackgroundTexMatrix;
842         int loc_ModelViewProjectionMatrix;
843         int loc_ModelViewMatrix;
844         int loc_PixelToScreenTexCoord;
845         int loc_ModelToReflectCube;
846         int loc_ShadowMapMatrix;
847         int loc_BloomColorSubtract;
848         int loc_NormalmapScrollBlend;
849         int loc_BounceGridMatrix;
850         int loc_BounceGridIntensity;
851 }
852 r_glsl_permutation_t;
853
854 #define SHADERPERMUTATION_HASHSIZE 256
855
856
857 // non-degradable "lightweight" shader parameters to keep the permutations simpler
858 // these can NOT degrade! only use for simple stuff
859 enum
860 {
861         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
862         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
863         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
864         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
865         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
866         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
867         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
868 };
869 #define SHADERSTATICPARMS_COUNT 7
870
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
873
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876 qboolean R_CompileShader_CheckStaticParms(void)
877 {
878         static int r_compileshader_staticparms_save[1];
879         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
881
882         // detect all
883         if (r_glsl_saturation_redcompensate.integer)
884                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885         if (r_glsl_vertextextureblend_usebothalphas.integer)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887         if (r_shadow_glossexact.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889         if (r_glsl_postprocess.integer)
890         {
891                 if (r_glsl_postprocess_uservec1_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893                 if (r_glsl_postprocess_uservec2_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895                 if (r_glsl_postprocess_uservec3_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897                 if (r_glsl_postprocess_uservec4_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
899         }
900         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
901 }
902
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
906         else \
907                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
909 {
910         shaderstaticparms_count = 0;
911
912         // emit all
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
920 }
921
922 /// information about each possible shader permutation
923 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
924 /// currently selected permutation
925 r_glsl_permutation_t *r_glsl_permutation;
926 /// storage for permutations linked in the hash table
927 memexpandablearray_t r_glsl_permutationarray;
928
929 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
930 {
931         //unsigned int hashdepth = 0;
932         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
933         r_glsl_permutation_t *p;
934         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
935         {
936                 if (p->mode == mode && p->permutation == permutation)
937                 {
938                         //if (hashdepth > 10)
939                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
940                         return p;
941                 }
942                 //hashdepth++;
943         }
944         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
945         p->mode = mode;
946         p->permutation = permutation;
947         p->hashnext = r_glsl_permutationhash[mode][hashindex];
948         r_glsl_permutationhash[mode][hashindex] = p;
949         //if (hashdepth > 10)
950         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
951         return p;
952 }
953
954 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
955 {
956         char *shaderstring;
957         if (!filename || !filename[0])
958                 return NULL;
959         if (!strcmp(filename, "glsl/default.glsl"))
960         {
961                 if (!glslshaderstring)
962                 {
963                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964                         if (glslshaderstring)
965                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
966                         else
967                                 glslshaderstring = (char *)builtinshaderstring;
968                 }
969                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
970                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
971                 return shaderstring;
972         }
973         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
974         if (shaderstring)
975         {
976                 if (printfromdisknotice)
977                         Con_DPrintf("from disk %s... ", filename);
978                 return shaderstring;
979         }
980         return shaderstring;
981 }
982
983 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
984 {
985         int i;
986         int sampler;
987         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
988         char *vertexstring, *geometrystring, *fragmentstring;
989         char permutationname[256];
990         int vertstrings_count = 0;
991         int geomstrings_count = 0;
992         int fragstrings_count = 0;
993         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
994         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996
997         if (p->compiled)
998                 return;
999         p->compiled = true;
1000         p->program = 0;
1001
1002         permutationname[0] = 0;
1003         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1004         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1005         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1006
1007         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1008
1009         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1010         if(vid.support.gl20shaders130)
1011         {
1012                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1013                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1014                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1015                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1016                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1017                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1018         }
1019
1020         // the first pretext is which type of shader to compile as
1021         // (later these will all be bound together as a program object)
1022         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1023         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1024         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1025
1026         // the second pretext is the mode (for example a light source)
1027         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1028         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1029         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1030         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1031
1032         // now add all the permutation pretexts
1033         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1034         {
1035                 if (permutation & (1<<i))
1036                 {
1037                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1038                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1039                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1040                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1041                 }
1042                 else
1043                 {
1044                         // keep line numbers correct
1045                         vertstrings_list[vertstrings_count++] = "\n";
1046                         geomstrings_list[geomstrings_count++] = "\n";
1047                         fragstrings_list[fragstrings_count++] = "\n";
1048                 }
1049         }
1050
1051         // add static parms
1052         R_CompileShader_AddStaticParms(mode, permutation);
1053         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054         vertstrings_count += shaderstaticparms_count;
1055         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056         geomstrings_count += shaderstaticparms_count;
1057         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058         fragstrings_count += shaderstaticparms_count;
1059
1060         // now append the shader text itself
1061         vertstrings_list[vertstrings_count++] = vertexstring;
1062         geomstrings_list[geomstrings_count++] = geometrystring;
1063         fragstrings_list[fragstrings_count++] = fragmentstring;
1064
1065         // if any sources were NULL, clear the respective list
1066         if (!vertexstring)
1067                 vertstrings_count = 0;
1068         if (!geometrystring)
1069                 geomstrings_count = 0;
1070         if (!fragmentstring)
1071                 fragstrings_count = 0;
1072
1073         // compile the shader program
1074         if (vertstrings_count + geomstrings_count + fragstrings_count)
1075                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1076         if (p->program)
1077         {
1078                 CHECKGLERROR
1079                 qglUseProgram(p->program);CHECKGLERROR
1080                 // look up all the uniform variable names we care about, so we don't
1081                 // have to look them up every time we set them
1082
1083                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1084                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1085                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1086                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1087                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1088                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1089                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1090                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1091                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1092                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1093                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1094                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1095                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1096                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1097                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1098                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1099                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1100                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1101                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1102                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1103                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1104                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1105                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1106                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1107                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1108                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1109                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1110                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1111                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1112                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1113                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1114                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1115                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1116                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1117                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1118                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1119                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1120                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1121                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1122                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1123                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1124                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1125                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1126                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1127                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1128                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1129                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1130                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1131                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1132                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1133                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1134                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1135                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1136                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1137                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1138                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1139                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1140                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1141                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1142                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1143                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1144                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1145                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1146                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1147                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1148                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1149                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1150                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1151                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1152                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1153                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1154                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1155                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1156                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1157                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1158                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1159                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1160                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1161                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1162                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1163                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1164                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1165                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1166                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1167                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1168                 // initialize the samplers to refer to the texture units we use
1169                 p->tex_Texture_First = -1;
1170                 p->tex_Texture_Second = -1;
1171                 p->tex_Texture_GammaRamps = -1;
1172                 p->tex_Texture_Normal = -1;
1173                 p->tex_Texture_Color = -1;
1174                 p->tex_Texture_Gloss = -1;
1175                 p->tex_Texture_Glow = -1;
1176                 p->tex_Texture_SecondaryNormal = -1;
1177                 p->tex_Texture_SecondaryColor = -1;
1178                 p->tex_Texture_SecondaryGloss = -1;
1179                 p->tex_Texture_SecondaryGlow = -1;
1180                 p->tex_Texture_Pants = -1;
1181                 p->tex_Texture_Shirt = -1;
1182                 p->tex_Texture_FogHeightTexture = -1;
1183                 p->tex_Texture_FogMask = -1;
1184                 p->tex_Texture_Lightmap = -1;
1185                 p->tex_Texture_Deluxemap = -1;
1186                 p->tex_Texture_Attenuation = -1;
1187                 p->tex_Texture_Cube = -1;
1188                 p->tex_Texture_Refraction = -1;
1189                 p->tex_Texture_Reflection = -1;
1190                 p->tex_Texture_ShadowMap2D = -1;
1191                 p->tex_Texture_CubeProjection = -1;
1192                 p->tex_Texture_ScreenDepth = -1;
1193                 p->tex_Texture_ScreenNormalMap = -1;
1194                 p->tex_Texture_ScreenDiffuse = -1;
1195                 p->tex_Texture_ScreenSpecular = -1;
1196                 p->tex_Texture_ReflectMask = -1;
1197                 p->tex_Texture_ReflectCube = -1;
1198                 p->tex_Texture_BounceGrid = -1;
1199                 sampler = 0;
1200                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1201                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1202                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1203                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1204                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1205                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1206                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1207                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1208                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1209                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1210                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1211                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1212                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1213                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1214                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1215                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1216                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1217                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1218                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1219                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1220                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1221                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1222                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1223                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1224                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1225                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1226                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1227                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1228                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1229                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1230                 CHECKGLERROR
1231                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1232         }
1233         else
1234                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1235
1236         // free the strings
1237         if (vertexstring)
1238                 Mem_Free(vertexstring);
1239         if (geometrystring)
1240                 Mem_Free(geometrystring);
1241         if (fragmentstring)
1242                 Mem_Free(fragmentstring);
1243 }
1244
1245 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1246 {
1247         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1248         if (r_glsl_permutation != perm)
1249         {
1250                 r_glsl_permutation = perm;
1251                 if (!r_glsl_permutation->program)
1252                 {
1253                         if (!r_glsl_permutation->compiled)
1254                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1255                         if (!r_glsl_permutation->program)
1256                         {
1257                                 // remove features until we find a valid permutation
1258                                 int i;
1259                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1260                                 {
1261                                         // reduce i more quickly whenever it would not remove any bits
1262                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1263                                         if (!(permutation & j))
1264                                                 continue;
1265                                         permutation -= j;
1266                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1267                                         if (!r_glsl_permutation->compiled)
1268                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1269                                         if (r_glsl_permutation->program)
1270                                                 break;
1271                                 }
1272                                 if (i >= SHADERPERMUTATION_COUNT)
1273                                 {
1274                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1275                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1276                                         qglUseProgram(0);CHECKGLERROR
1277                                         return; // no bit left to clear, entire mode is broken
1278                                 }
1279                         }
1280                 }
1281                 CHECKGLERROR
1282                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1283         }
1284         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1285         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1286         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1287 }
1288
1289 #ifdef SUPPORTD3D
1290
1291 #ifdef SUPPORTD3D
1292 #include <d3d9.h>
1293 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1294 extern D3DCAPS9 vid_d3d9caps;
1295 #endif
1296
1297 struct r_hlsl_permutation_s;
1298 typedef struct r_hlsl_permutation_s
1299 {
1300         /// hash lookup data
1301         struct r_hlsl_permutation_s *hashnext;
1302         unsigned int mode;
1303         unsigned int permutation;
1304
1305         /// indicates if we have tried compiling this permutation already
1306         qboolean compiled;
1307         /// NULL if compilation failed
1308         IDirect3DVertexShader9 *vertexshader;
1309         IDirect3DPixelShader9 *pixelshader;
1310 }
1311 r_hlsl_permutation_t;
1312
1313 typedef enum D3DVSREGISTER_e
1314 {
1315         D3DVSREGISTER_TexMatrix = 0, // float4x4
1316         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1317         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1318         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1319         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1320         D3DVSREGISTER_ModelToLight = 20, // float4x4
1321         D3DVSREGISTER_EyePosition = 24,
1322         D3DVSREGISTER_FogPlane = 25,
1323         D3DVSREGISTER_LightDir = 26,
1324         D3DVSREGISTER_LightPosition = 27,
1325 }
1326 D3DVSREGISTER_t;
1327
1328 typedef enum D3DPSREGISTER_e
1329 {
1330         D3DPSREGISTER_Alpha = 0,
1331         D3DPSREGISTER_BloomBlur_Parameters = 1,
1332         D3DPSREGISTER_ClientTime = 2,
1333         D3DPSREGISTER_Color_Ambient = 3,
1334         D3DPSREGISTER_Color_Diffuse = 4,
1335         D3DPSREGISTER_Color_Specular = 5,
1336         D3DPSREGISTER_Color_Glow = 6,
1337         D3DPSREGISTER_Color_Pants = 7,
1338         D3DPSREGISTER_Color_Shirt = 8,
1339         D3DPSREGISTER_DeferredColor_Ambient = 9,
1340         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1341         D3DPSREGISTER_DeferredColor_Specular = 11,
1342         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1343         D3DPSREGISTER_DeferredMod_Specular = 13,
1344         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1345         D3DPSREGISTER_EyePosition = 15, // unused
1346         D3DPSREGISTER_FogColor = 16,
1347         D3DPSREGISTER_FogHeightFade = 17,
1348         D3DPSREGISTER_FogPlane = 18,
1349         D3DPSREGISTER_FogPlaneViewDist = 19,
1350         D3DPSREGISTER_FogRangeRecip = 20,
1351         D3DPSREGISTER_LightColor = 21,
1352         D3DPSREGISTER_LightDir = 22, // unused
1353         D3DPSREGISTER_LightPosition = 23,
1354         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1355         D3DPSREGISTER_PixelSize = 25,
1356         D3DPSREGISTER_ReflectColor = 26,
1357         D3DPSREGISTER_ReflectFactor = 27,
1358         D3DPSREGISTER_ReflectOffset = 28,
1359         D3DPSREGISTER_RefractColor = 29,
1360         D3DPSREGISTER_Saturation = 30,
1361         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1362         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1363         D3DPSREGISTER_ScreenToDepth = 33,
1364         D3DPSREGISTER_ShadowMap_Parameters = 34,
1365         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1366         D3DPSREGISTER_SpecularPower = 36,
1367         D3DPSREGISTER_UserVec1 = 37,
1368         D3DPSREGISTER_UserVec2 = 38,
1369         D3DPSREGISTER_UserVec3 = 39,
1370         D3DPSREGISTER_UserVec4 = 40,
1371         D3DPSREGISTER_ViewTintColor = 41,
1372         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1373         D3DPSREGISTER_BloomColorSubtract = 43,
1374         D3DPSREGISTER_ViewToLight = 44, // float4x4
1375         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1376         D3DPSREGISTER_NormalmapScrollBlend = 52,
1377         // next at 53
1378 }
1379 D3DPSREGISTER_t;
1380
1381 /// information about each possible shader permutation
1382 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1383 /// currently selected permutation
1384 r_hlsl_permutation_t *r_hlsl_permutation;
1385 /// storage for permutations linked in the hash table
1386 memexpandablearray_t r_hlsl_permutationarray;
1387
1388 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1389 {
1390         //unsigned int hashdepth = 0;
1391         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1392         r_hlsl_permutation_t *p;
1393         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1394         {
1395                 if (p->mode == mode && p->permutation == permutation)
1396                 {
1397                         //if (hashdepth > 10)
1398                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1399                         return p;
1400                 }
1401                 //hashdepth++;
1402         }
1403         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1404         p->mode = mode;
1405         p->permutation = permutation;
1406         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1407         r_hlsl_permutationhash[mode][hashindex] = p;
1408         //if (hashdepth > 10)
1409         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1410         return p;
1411 }
1412
1413 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1414 {
1415         char *shaderstring;
1416         if (!filename || !filename[0])
1417                 return NULL;
1418         if (!strcmp(filename, "hlsl/default.hlsl"))
1419         {
1420                 if (!hlslshaderstring)
1421                 {
1422                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423                         if (hlslshaderstring)
1424                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1425                         else
1426                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1427                 }
1428                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1429                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1430                 return shaderstring;
1431         }
1432         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1433         if (shaderstring)
1434         {
1435                 if (printfromdisknotice)
1436                         Con_DPrintf("from disk %s... ", filename);
1437                 return shaderstring;
1438         }
1439         return shaderstring;
1440 }
1441
1442 #include <d3dx9.h>
1443 //#include <d3dx9shader.h>
1444 //#include <d3dx9mesh.h>
1445
1446 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1447 {
1448         DWORD *vsbin = NULL;
1449         DWORD *psbin = NULL;
1450         fs_offset_t vsbinsize;
1451         fs_offset_t psbinsize;
1452 //      IDirect3DVertexShader9 *vs = NULL;
1453 //      IDirect3DPixelShader9 *ps = NULL;
1454         ID3DXBuffer *vslog = NULL;
1455         ID3DXBuffer *vsbuffer = NULL;
1456         ID3DXConstantTable *vsconstanttable = NULL;
1457         ID3DXBuffer *pslog = NULL;
1458         ID3DXBuffer *psbuffer = NULL;
1459         ID3DXConstantTable *psconstanttable = NULL;
1460         int vsresult = 0;
1461         int psresult = 0;
1462         char temp[MAX_INPUTLINE];
1463         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1464         qboolean debugshader = gl_paranoid.integer != 0;
1465         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1466         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1467         if (!debugshader)
1468         {
1469                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1470                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1471         }
1472         if ((!vsbin && vertstring) || (!psbin && fragstring))
1473         {
1474                 const char* dllnames_d3dx9 [] =
1475                 {
1476                         "d3dx9_43.dll",
1477                         "d3dx9_42.dll",
1478                         "d3dx9_41.dll",
1479                         "d3dx9_40.dll",
1480                         "d3dx9_39.dll",
1481                         "d3dx9_38.dll",
1482                         "d3dx9_37.dll",
1483                         "d3dx9_36.dll",
1484                         "d3dx9_35.dll",
1485                         "d3dx9_34.dll",
1486                         "d3dx9_33.dll",
1487                         "d3dx9_32.dll",
1488                         "d3dx9_31.dll",
1489                         "d3dx9_30.dll",
1490                         "d3dx9_29.dll",
1491                         "d3dx9_28.dll",
1492                         "d3dx9_27.dll",
1493                         "d3dx9_26.dll",
1494                         "d3dx9_25.dll",
1495                         "d3dx9_24.dll",
1496                         NULL
1497                 };
1498                 dllhandle_t d3dx9_dll = NULL;
1499                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1500                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1501                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502                 dllfunction_t d3dx9_dllfuncs[] =
1503                 {
1504                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1505                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1506                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1507                         {NULL, NULL}
1508                 };
1509                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1510                 {
1511                         DWORD shaderflags = 0;
1512                         if (debugshader)
1513                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1514                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1515                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1516                         if (vertstring && vertstring[0])
1517                         {
1518                                 if (debugshader)
1519                                 {
1520 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1521 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1522                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1523                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1524                                 }
1525                                 else
1526                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1527                                 if (vsbuffer)
1528                                 {
1529                                         vsbinsize = vsbuffer->GetBufferSize();
1530                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1531                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1532                                         vsbuffer->Release();
1533                                 }
1534                                 if (vslog)
1535                                 {
1536                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1537                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1538                                         vslog->Release();
1539                                 }
1540                         }
1541                         if (fragstring && fragstring[0])
1542                         {
1543                                 if (debugshader)
1544                                 {
1545 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1546 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1547                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1548                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1549                                 }
1550                                 else
1551                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1552                                 if (psbuffer)
1553                                 {
1554                                         psbinsize = psbuffer->GetBufferSize();
1555                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1556                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1557                                         psbuffer->Release();
1558                                 }
1559                                 if (pslog)
1560                                 {
1561                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1562                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1563                                         pslog->Release();
1564                                 }
1565                         }
1566                         Sys_UnloadLibrary(&d3dx9_dll);
1567                 }
1568                 else
1569                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1570         }
1571         if (vsbin && psbin)
1572         {
1573                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1574                 if (FAILED(vsresult))
1575                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1576                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1577                 if (FAILED(psresult))
1578                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1579         }
1580         // free the shader data
1581         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1582         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1583 }
1584
1585 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1586 {
1587         int i;
1588         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1589         int vertstring_length = 0;
1590         int geomstring_length = 0;
1591         int fragstring_length = 0;
1592         char *t;
1593         char *vertexstring, *geometrystring, *fragmentstring;
1594         char *vertstring, *geomstring, *fragstring;
1595         char permutationname[256];
1596         char cachename[256];
1597         int vertstrings_count = 0;
1598         int geomstrings_count = 0;
1599         int fragstrings_count = 0;
1600         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603
1604         if (p->compiled)
1605                 return;
1606         p->compiled = true;
1607         p->vertexshader = NULL;
1608         p->pixelshader = NULL;
1609
1610         permutationname[0] = 0;
1611         cachename[0] = 0;
1612         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1613         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1614         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1615
1616         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1617         strlcat(cachename, "hlsl/", sizeof(cachename));
1618
1619         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1620         vertstrings_count = 0;
1621         geomstrings_count = 0;
1622         fragstrings_count = 0;
1623         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1624         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1625         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1626
1627         // the first pretext is which type of shader to compile as
1628         // (later these will all be bound together as a program object)
1629         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1630         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1631         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1632
1633         // the second pretext is the mode (for example a light source)
1634         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1635         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1636         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1637         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1638         strlcat(cachename, modeinfo->name, sizeof(cachename));
1639
1640         // now add all the permutation pretexts
1641         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1642         {
1643                 if (permutation & (1<<i))
1644                 {
1645                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1646                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1647                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1648                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1649                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1650                 }
1651                 else
1652                 {
1653                         // keep line numbers correct
1654                         vertstrings_list[vertstrings_count++] = "\n";
1655                         geomstrings_list[geomstrings_count++] = "\n";
1656                         fragstrings_list[fragstrings_count++] = "\n";
1657                 }
1658         }
1659
1660         // add static parms
1661         R_CompileShader_AddStaticParms(mode, permutation);
1662         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663         vertstrings_count += shaderstaticparms_count;
1664         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665         geomstrings_count += shaderstaticparms_count;
1666         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667         fragstrings_count += shaderstaticparms_count;
1668
1669         // replace spaces in the cachename with _ characters
1670         for (i = 0;cachename[i];i++)
1671                 if (cachename[i] == ' ')
1672                         cachename[i] = '_';
1673
1674         // now append the shader text itself
1675         vertstrings_list[vertstrings_count++] = vertexstring;
1676         geomstrings_list[geomstrings_count++] = geometrystring;
1677         fragstrings_list[fragstrings_count++] = fragmentstring;
1678
1679         // if any sources were NULL, clear the respective list
1680         if (!vertexstring)
1681                 vertstrings_count = 0;
1682         if (!geometrystring)
1683                 geomstrings_count = 0;
1684         if (!fragmentstring)
1685                 fragstrings_count = 0;
1686
1687         vertstring_length = 0;
1688         for (i = 0;i < vertstrings_count;i++)
1689                 vertstring_length += strlen(vertstrings_list[i]);
1690         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1691         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1692                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1693
1694         geomstring_length = 0;
1695         for (i = 0;i < geomstrings_count;i++)
1696                 geomstring_length += strlen(geomstrings_list[i]);
1697         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1698         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1699                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1700
1701         fragstring_length = 0;
1702         for (i = 0;i < fragstrings_count;i++)
1703                 fragstring_length += strlen(fragstrings_list[i]);
1704         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1705         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1706                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1707
1708         // try to load the cached shader, or generate one
1709         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1710
1711         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1712                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1713         else
1714                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1715
1716         // free the strings
1717         if (vertstring)
1718                 Mem_Free(vertstring);
1719         if (geomstring)
1720                 Mem_Free(geomstring);
1721         if (fragstring)
1722                 Mem_Free(fragstring);
1723         if (vertexstring)
1724                 Mem_Free(vertexstring);
1725         if (geometrystring)
1726                 Mem_Free(geometrystring);
1727         if (fragmentstring)
1728                 Mem_Free(fragmentstring);
1729 }
1730
1731 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 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);}
1734 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);}
1735 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);}
1736 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);}
1737
1738 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 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);}
1741 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);}
1742 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);}
1743 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);}
1744
1745 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1746 {
1747         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1748         if (r_hlsl_permutation != perm)
1749         {
1750                 r_hlsl_permutation = perm;
1751                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1752                 {
1753                         if (!r_hlsl_permutation->compiled)
1754                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1755                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1756                         {
1757                                 // remove features until we find a valid permutation
1758                                 int i;
1759                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1760                                 {
1761                                         // reduce i more quickly whenever it would not remove any bits
1762                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1763                                         if (!(permutation & j))
1764                                                 continue;
1765                                         permutation -= j;
1766                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767                                         if (!r_hlsl_permutation->compiled)
1768                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1769                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1770                                                 break;
1771                                 }
1772                                 if (i >= SHADERPERMUTATION_COUNT)
1773                                 {
1774                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1775                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776                                         return; // no bit left to clear, entire mode is broken
1777                                 }
1778                         }
1779                 }
1780                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1781                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1782         }
1783         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1784         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1785         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1786 }
1787 #endif
1788
1789 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1790 {
1791         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1792         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1793         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1794         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1795 }
1796
1797 void R_GLSL_Restart_f(void)
1798 {
1799         unsigned int i, limit;
1800         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1801                 Mem_Free(glslshaderstring);
1802         glslshaderstring = NULL;
1803         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1804                 Mem_Free(hlslshaderstring);
1805         hlslshaderstring = NULL;
1806         switch(vid.renderpath)
1807         {
1808         case RENDERPATH_D3D9:
1809 #ifdef SUPPORTD3D
1810                 {
1811                         r_hlsl_permutation_t *p;
1812                         r_hlsl_permutation = NULL;
1813                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1814                         for (i = 0;i < limit;i++)
1815                         {
1816                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1817                                 {
1818                                         if (p->vertexshader)
1819                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1820                                         if (p->pixelshader)
1821                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1822                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1823                                 }
1824                         }
1825                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1826                 }
1827 #endif
1828                 break;
1829         case RENDERPATH_D3D10:
1830                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1831                 break;
1832         case RENDERPATH_D3D11:
1833                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1834                 break;
1835         case RENDERPATH_GL20:
1836         case RENDERPATH_GLES2:
1837                 {
1838                         r_glsl_permutation_t *p;
1839                         r_glsl_permutation = NULL;
1840                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1841                         for (i = 0;i < limit;i++)
1842                         {
1843                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1844                                 {
1845                                         GL_Backend_FreeProgram(p->program);
1846                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1847                                 }
1848                         }
1849                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1850                 }
1851                 break;
1852         case RENDERPATH_GL11:
1853         case RENDERPATH_GL13:
1854         case RENDERPATH_GLES1:
1855                 break;
1856         case RENDERPATH_SOFT:
1857                 break;
1858         }
1859 }
1860
1861 void R_GLSL_DumpShader_f(void)
1862 {
1863         int i;
1864         qfile_t *file;
1865
1866         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1867         if (file)
1868         {
1869                 FS_Print(file, "/* The engine may define the following macros:\n");
1870                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1871                 for (i = 0;i < SHADERMODE_COUNT;i++)
1872                         FS_Print(file, glslshadermodeinfo[i].pretext);
1873                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1874                         FS_Print(file, shaderpermutationinfo[i].pretext);
1875                 FS_Print(file, "*/\n");
1876                 FS_Print(file, builtinshaderstring);
1877                 FS_Close(file);
1878                 Con_Printf("glsl/default.glsl written\n");
1879         }
1880         else
1881                 Con_Printf("failed to write to glsl/default.glsl\n");
1882
1883         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1884         if (file)
1885         {
1886                 FS_Print(file, "/* The engine may define the following macros:\n");
1887                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1888                 for (i = 0;i < SHADERMODE_COUNT;i++)
1889                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1890                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1891                         FS_Print(file, shaderpermutationinfo[i].pretext);
1892                 FS_Print(file, "*/\n");
1893                 FS_Print(file, builtinhlslshaderstring);
1894                 FS_Close(file);
1895                 Con_Printf("hlsl/default.hlsl written\n");
1896         }
1897         else
1898                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1899 }
1900
1901 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1902 {
1903         unsigned int permutation = 0;
1904         if (r_trippy.integer && !notrippy)
1905                 permutation |= SHADERPERMUTATION_TRIPPY;
1906         permutation |= SHADERPERMUTATION_VIEWTINT;
1907         if (first)
1908                 permutation |= SHADERPERMUTATION_DIFFUSE;
1909         if (second)
1910                 permutation |= SHADERPERMUTATION_SPECULAR;
1911         if (texturemode == GL_MODULATE)
1912                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1913         if (usegamma && r_texture_gammaramps && v_glslgamma.integer && !vid_gammatables_trivial)
1914                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1915         else if (texturemode == GL_ADD)
1916                 permutation |= SHADERPERMUTATION_GLOW;
1917         else if (texturemode == GL_DECAL)
1918                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1919         if (!second)
1920                 texturemode = GL_MODULATE;
1921         if (vid.allowalphatocoverage)
1922                 GL_AlphaToCoverage(false);
1923         switch (vid.renderpath)
1924         {
1925         case RENDERPATH_D3D9:
1926 #ifdef SUPPORTD3D
1927                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1928                 R_Mesh_TexBind(GL20TU_FIRST , first );
1929                 R_Mesh_TexBind(GL20TU_SECOND, second);
1930                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1931                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1932 #endif
1933                 break;
1934         case RENDERPATH_D3D10:
1935                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1936                 break;
1937         case RENDERPATH_D3D11:
1938                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1939                 break;
1940         case RENDERPATH_GL20:
1941         case RENDERPATH_GLES2:
1942                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1943                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1944                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1945                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1946                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1947                 break;
1948         case RENDERPATH_GL13:
1949         case RENDERPATH_GLES1:
1950                 R_Mesh_TexBind(0, first );
1951                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1952                 R_Mesh_TexBind(1, second);
1953                 if (second)
1954                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1955                 break;
1956         case RENDERPATH_GL11:
1957                 R_Mesh_TexBind(0, first );
1958                 break;
1959         case RENDERPATH_SOFT:
1960                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1961                 R_Mesh_TexBind(GL20TU_FIRST , first );
1962                 R_Mesh_TexBind(GL20TU_SECOND, second);
1963                 break;
1964         }
1965 }
1966
1967 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1968 {
1969         unsigned int permutation = 0;
1970         if (r_trippy.integer && !notrippy)
1971                 permutation |= SHADERPERMUTATION_TRIPPY;
1972         if (vid.allowalphatocoverage)
1973                 GL_AlphaToCoverage(false);
1974         switch (vid.renderpath)
1975         {
1976         case RENDERPATH_D3D9:
1977 #ifdef SUPPORTD3D
1978                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1979 #endif
1980                 break;
1981         case RENDERPATH_D3D10:
1982                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1983                 break;
1984         case RENDERPATH_D3D11:
1985                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1986                 break;
1987         case RENDERPATH_GL20:
1988         case RENDERPATH_GLES2:
1989                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1990                 break;
1991         case RENDERPATH_GL13:
1992         case RENDERPATH_GLES1:
1993                 R_Mesh_TexBind(0, 0);
1994                 R_Mesh_TexBind(1, 0);
1995                 break;
1996         case RENDERPATH_GL11:
1997                 R_Mesh_TexBind(0, 0);
1998                 break;
1999         case RENDERPATH_SOFT:
2000                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2001                 break;
2002         }
2003 }
2004
2005 void R_SetupShader_ShowDepth(qboolean notrippy)
2006 {
2007         int permutation = 0;
2008         if (r_trippy.integer && !notrippy)
2009                 permutation |= SHADERPERMUTATION_TRIPPY;
2010         if (vid.allowalphatocoverage)
2011                 GL_AlphaToCoverage(false);
2012         switch (vid.renderpath)
2013         {
2014         case RENDERPATH_D3D9:
2015 #ifdef SUPPORTHLSL
2016                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2017 #endif
2018                 break;
2019         case RENDERPATH_D3D10:
2020                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2021                 break;
2022         case RENDERPATH_D3D11:
2023                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2024                 break;
2025         case RENDERPATH_GL20:
2026         case RENDERPATH_GLES2:
2027                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2028                 break;
2029         case RENDERPATH_GL13:
2030         case RENDERPATH_GLES1:
2031                 break;
2032         case RENDERPATH_GL11:
2033                 break;
2034         case RENDERPATH_SOFT:
2035                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2036                 break;
2037         }
2038 }
2039
2040 extern qboolean r_shadow_usingdeferredprepass;
2041 extern cvar_t r_shadow_deferred_8bitrange;
2042 extern rtexture_t *r_shadow_attenuationgradienttexture;
2043 extern rtexture_t *r_shadow_attenuation2dtexture;
2044 extern rtexture_t *r_shadow_attenuation3dtexture;
2045 extern qboolean r_shadow_usingshadowmap2d;
2046 extern qboolean r_shadow_usingshadowmaportho;
2047 extern float r_shadow_shadowmap_texturescale[2];
2048 extern float r_shadow_shadowmap_parameters[4];
2049 extern qboolean r_shadow_shadowmapvsdct;
2050 extern qboolean r_shadow_shadowmapsampler;
2051 extern int r_shadow_shadowmappcf;
2052 extern rtexture_t *r_shadow_shadowmap2dtexture;
2053 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2054 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2055 extern matrix4x4_t r_shadow_shadowmapmatrix;
2056 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2057 extern int r_shadow_prepass_width;
2058 extern int r_shadow_prepass_height;
2059 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2060 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2061 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2062 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2063 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2064
2065 #define BLENDFUNC_ALLOWS_COLORMOD      1
2066 #define BLENDFUNC_ALLOWS_FOG           2
2067 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2068 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2069 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2070 static int R_BlendFuncFlags(int src, int dst)
2071 {
2072         int r = 0;
2073
2074         // a blendfunc allows colormod if:
2075         // a) it can never keep the destination pixel invariant, or
2076         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2077         // this is to prevent unintended side effects from colormod
2078
2079         // a blendfunc allows fog if:
2080         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2081         // this is to prevent unintended side effects from fog
2082
2083         // these checks are the output of fogeval.pl
2084
2085         r |= BLENDFUNC_ALLOWS_COLORMOD;
2086         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2087         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2088         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2089         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2090         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2091         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2092         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2093         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2094         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2095         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2098         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2099         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2100         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2101         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2102         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2103         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2104         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2105         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2106         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2107
2108         return r;
2109 }
2110
2111 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)
2112 {
2113         // select a permutation of the lighting shader appropriate to this
2114         // combination of texture, entity, light source, and fogging, only use the
2115         // minimum features necessary to avoid wasting rendering time in the
2116         // fragment shader on features that are not being used
2117         unsigned int permutation = 0;
2118         unsigned int mode = 0;
2119         int blendfuncflags;
2120         static float dummy_colormod[3] = {1, 1, 1};
2121         float *colormod = rsurface.colormod;
2122         float m16f[16];
2123         matrix4x4_t tempmatrix;
2124         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2125         if (r_trippy.integer && !notrippy)
2126                 permutation |= SHADERPERMUTATION_TRIPPY;
2127         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2128                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2129         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2130                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2131         if (rsurfacepass == RSURFPASS_BACKGROUND)
2132         {
2133                 // distorted background
2134                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2135                 {
2136                         mode = SHADERMODE_WATER;
2137                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2138                         {
2139                                 // this is the right thing to do for wateralpha
2140                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2141                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2142                         }
2143                         else
2144                         {
2145                                 // this is the right thing to do for entity alpha
2146                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2147                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2148                         }
2149                 }
2150                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2151                 {
2152                         mode = SHADERMODE_REFRACTION;
2153                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2154                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2155                 }
2156                 else
2157                 {
2158                         mode = SHADERMODE_GENERIC;
2159                         permutation |= SHADERPERMUTATION_DIFFUSE;
2160                         GL_BlendFunc(GL_ONE, GL_ZERO);
2161                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2162                 }
2163                 if (vid.allowalphatocoverage)
2164                         GL_AlphaToCoverage(false);
2165         }
2166         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2167         {
2168                 if (r_glsl_offsetmapping.integer)
2169                 {
2170                         switch(rsurface.texture->offsetmapping)
2171                         {
2172                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2173                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2174                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2175                         case OFFSETMAPPING_OFF: break;
2176                         }
2177                 }
2178                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2179                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2180                 // normalmap (deferred prepass), may use alpha test on diffuse
2181                 mode = SHADERMODE_DEFERREDGEOMETRY;
2182                 GL_BlendFunc(GL_ONE, GL_ZERO);
2183                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2184                 if (vid.allowalphatocoverage)
2185                         GL_AlphaToCoverage(false);
2186         }
2187         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2188         {
2189                 if (r_glsl_offsetmapping.integer)
2190                 {
2191                         switch(rsurface.texture->offsetmapping)
2192                         {
2193                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2194                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2195                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2196                         case OFFSETMAPPING_OFF: break;
2197                         }
2198                 }
2199                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2200                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2201                 // light source
2202                 mode = SHADERMODE_LIGHTSOURCE;
2203                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2204                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2205                 if (diffusescale > 0)
2206                         permutation |= SHADERPERMUTATION_DIFFUSE;
2207                 if (specularscale > 0)
2208                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2209                 if (r_refdef.fogenabled)
2210                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2211                 if (rsurface.texture->colormapping)
2212                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2213                 if (r_shadow_usingshadowmap2d)
2214                 {
2215                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2216                         if(r_shadow_shadowmapvsdct)
2217                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2218
2219                         if (r_shadow_shadowmapsampler)
2220                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2221                         if (r_shadow_shadowmappcf > 1)
2222                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2223                         else if (r_shadow_shadowmappcf)
2224                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2225                 }
2226                 if (rsurface.texture->reflectmasktexture)
2227                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2228                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2229                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2230                 if (vid.allowalphatocoverage)
2231                         GL_AlphaToCoverage(false);
2232         }
2233         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2234         {
2235                 if (r_glsl_offsetmapping.integer)
2236                 {
2237                         switch(rsurface.texture->offsetmapping)
2238                         {
2239                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2240                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2242                         case OFFSETMAPPING_OFF: break;
2243                         }
2244                 }
2245                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2246                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2247                 // unshaded geometry (fullbright or ambient model lighting)
2248                 mode = SHADERMODE_FLATCOLOR;
2249                 ambientscale = diffusescale = specularscale = 0;
2250                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2251                         permutation |= SHADERPERMUTATION_GLOW;
2252                 if (r_refdef.fogenabled)
2253                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2254                 if (rsurface.texture->colormapping)
2255                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2256                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2257                 {
2258                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2259                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2260
2261                         if (r_shadow_shadowmapsampler)
2262                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2263                         if (r_shadow_shadowmappcf > 1)
2264                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2265                         else if (r_shadow_shadowmappcf)
2266                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2267                 }
2268                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2269                         permutation |= SHADERPERMUTATION_REFLECTION;
2270                 if (rsurface.texture->reflectmasktexture)
2271                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2272                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2273                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2274                 // when using alphatocoverage, we don't need alphakill
2275                 if (vid.allowalphatocoverage)
2276                 {
2277                         if (r_transparent_alphatocoverage.integer)
2278                         {
2279                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2280                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2281                         }
2282                         else
2283                                 GL_AlphaToCoverage(false);
2284                 }
2285         }
2286         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2287         {
2288                 if (r_glsl_offsetmapping.integer)
2289                 {
2290                         switch(rsurface.texture->offsetmapping)
2291                         {
2292                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2293                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2294                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2295                         case OFFSETMAPPING_OFF: break;
2296                         }
2297                 }
2298                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2299                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2300                 // directional model lighting
2301                 mode = SHADERMODE_LIGHTDIRECTION;
2302                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2303                         permutation |= SHADERPERMUTATION_GLOW;
2304                 permutation |= SHADERPERMUTATION_DIFFUSE;
2305                 if (specularscale > 0)
2306                         permutation |= SHADERPERMUTATION_SPECULAR;
2307                 if (r_refdef.fogenabled)
2308                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2309                 if (rsurface.texture->colormapping)
2310                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2311                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2312                 {
2313                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2314                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2315
2316                         if (r_shadow_shadowmapsampler)
2317                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2318                         if (r_shadow_shadowmappcf > 1)
2319                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2320                         else if (r_shadow_shadowmappcf)
2321                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2322                 }
2323                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2324                         permutation |= SHADERPERMUTATION_REFLECTION;
2325                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2326                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2327                 if (rsurface.texture->reflectmasktexture)
2328                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2329                 if (r_shadow_bouncegridtexture)
2330                 {
2331                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2332                         if (r_shadow_bouncegriddirectional)
2333                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2334                 }
2335                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2336                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2337                 // when using alphatocoverage, we don't need alphakill
2338                 if (vid.allowalphatocoverage)
2339                 {
2340                         if (r_transparent_alphatocoverage.integer)
2341                         {
2342                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2343                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2344                         }
2345                         else
2346                                 GL_AlphaToCoverage(false);
2347                 }
2348         }
2349         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2350         {
2351                 if (r_glsl_offsetmapping.integer)
2352                 {
2353                         switch(rsurface.texture->offsetmapping)
2354                         {
2355                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2356                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2357                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2358                         case OFFSETMAPPING_OFF: break;
2359                         }
2360                 }
2361                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2362                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2363                 // ambient model lighting
2364                 mode = SHADERMODE_LIGHTDIRECTION;
2365                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2366                         permutation |= SHADERPERMUTATION_GLOW;
2367                 if (r_refdef.fogenabled)
2368                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2369                 if (rsurface.texture->colormapping)
2370                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2371                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2372                 {
2373                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2374                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2375
2376                         if (r_shadow_shadowmapsampler)
2377                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2378                         if (r_shadow_shadowmappcf > 1)
2379                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2380                         else if (r_shadow_shadowmappcf)
2381                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2382                 }
2383                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2384                         permutation |= SHADERPERMUTATION_REFLECTION;
2385                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2386                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2387                 if (rsurface.texture->reflectmasktexture)
2388                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2389                 if (r_shadow_bouncegridtexture)
2390                 {
2391                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2392                         if (r_shadow_bouncegriddirectional)
2393                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2394                 }
2395                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2396                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2397                 // when using alphatocoverage, we don't need alphakill
2398                 if (vid.allowalphatocoverage)
2399                 {
2400                         if (r_transparent_alphatocoverage.integer)
2401                         {
2402                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2403                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2404                         }
2405                         else
2406                                 GL_AlphaToCoverage(false);
2407                 }
2408         }
2409         else
2410         {
2411                 if (r_glsl_offsetmapping.integer)
2412                 {
2413                         switch(rsurface.texture->offsetmapping)
2414                         {
2415                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2416                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2417                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2418                         case OFFSETMAPPING_OFF: break;
2419                         }
2420                 }
2421                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2422                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2423                 // lightmapped wall
2424                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2425                         permutation |= SHADERPERMUTATION_GLOW;
2426                 if (r_refdef.fogenabled)
2427                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2428                 if (rsurface.texture->colormapping)
2429                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2430                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2431                 {
2432                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2433                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2434
2435                         if (r_shadow_shadowmapsampler)
2436                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2437                         if (r_shadow_shadowmappcf > 1)
2438                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2439                         else if (r_shadow_shadowmappcf)
2440                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2441                 }
2442                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2443                         permutation |= SHADERPERMUTATION_REFLECTION;
2444                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2445                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2446                 if (rsurface.texture->reflectmasktexture)
2447                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2448                 if (FAKELIGHT_ENABLED)
2449                 {
2450                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2451                         mode = SHADERMODE_FAKELIGHT;
2452                         permutation |= SHADERPERMUTATION_DIFFUSE;
2453                         if (specularscale > 0)
2454                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2455                 }
2456                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2457                 {
2458                         // deluxemapping (light direction texture)
2459                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2460                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2461                         else
2462                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2463                         permutation |= SHADERPERMUTATION_DIFFUSE;
2464                         if (specularscale > 0)
2465                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2466                 }
2467                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2468                 {
2469                         // fake deluxemapping (uniform light direction in tangentspace)
2470                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2471                         permutation |= SHADERPERMUTATION_DIFFUSE;
2472                         if (specularscale > 0)
2473                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2474                 }
2475                 else if (rsurface.uselightmaptexture)
2476                 {
2477                         // ordinary lightmapping (q1bsp, q3bsp)
2478                         mode = SHADERMODE_LIGHTMAP;
2479                 }
2480                 else
2481                 {
2482                         // ordinary vertex coloring (q3bsp)
2483                         mode = SHADERMODE_VERTEXCOLOR;
2484                 }
2485                 if (r_shadow_bouncegridtexture)
2486                 {
2487                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2488                         if (r_shadow_bouncegriddirectional)
2489                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2490                 }
2491                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2492                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2493                 // when using alphatocoverage, we don't need alphakill
2494                 if (vid.allowalphatocoverage)
2495                 {
2496                         if (r_transparent_alphatocoverage.integer)
2497                         {
2498                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2499                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2500                         }
2501                         else
2502                                 GL_AlphaToCoverage(false);
2503                 }
2504         }
2505         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2506                 colormod = dummy_colormod;
2507         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2508                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2509         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2510                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2511         switch(vid.renderpath)
2512         {
2513         case RENDERPATH_D3D9:
2514 #ifdef SUPPORTD3D
2515                 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);
2516                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2517                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2518                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2519                 if (mode == SHADERMODE_LIGHTSOURCE)
2520                 {
2521                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2522                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2523                 }
2524                 else
2525                 {
2526                         if (mode == SHADERMODE_LIGHTDIRECTION)
2527                         {
2528                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2529                         }
2530                 }
2531                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2532                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2533                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2534                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2535                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2536
2537                 if (mode == SHADERMODE_LIGHTSOURCE)
2538                 {
2539                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2540                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2541                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2542                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2543                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2544
2545                         // additive passes are only darkened by fog, not tinted
2546                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2547                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2548                 }
2549                 else
2550                 {
2551                         if (mode == SHADERMODE_FLATCOLOR)
2552                         {
2553                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2554                         }
2555                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2556                         {
2557                                 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]);
2558                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2559                                 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);
2560                                 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);
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2564                         }
2565                         else
2566                         {
2567                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2569                                 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);
2570                                 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);
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2572                         }
2573                         // additive passes are only darkened by fog, not tinted
2574                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2575                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2576                         else
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2578                         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);
2579                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2580                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2581                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2582                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2583                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2584                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2585                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2586                         if (mode == SHADERMODE_WATER)
2587                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2588                 }
2589                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2590                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2591                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2592                 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));
2593                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2594                 if (rsurface.texture->pantstexture)
2595                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2596                 else
2597                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2598                 if (rsurface.texture->shirttexture)
2599                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2600                 else
2601                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2602                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2603                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2604                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2605                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2606                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2607                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2608                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2609                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2610                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2611                         );
2612                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2613                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2614
2615                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2616                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2617                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2618                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2619                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2620                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2621                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2622                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2623                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2624                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2625                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2626                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2627                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2628                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2629                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2630                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2631                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2632                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2633                 {
2634                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2635                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2636                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2637                 }
2638                 else
2639                 {
2640                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2641                 }
2642 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2643 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2644                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2645                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2646                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2647                 {
2648                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2649                         if (rsurface.rtlight)
2650                         {
2651                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2652                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2653                         }
2654                 }
2655 #endif
2656                 break;
2657         case RENDERPATH_D3D10:
2658                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2659                 break;
2660         case RENDERPATH_D3D11:
2661                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2662                 break;
2663         case RENDERPATH_GL20:
2664         case RENDERPATH_GLES2:
2665                 if (!vid.useinterleavedarrays)
2666                 {
2667                         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);
2668                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2669                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2670                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2671                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2672                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2673                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2674                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2675                 }
2676                 else
2677                 {
2678                         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);
2679                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2680                 }
2681                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2682                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2683                 if (mode == SHADERMODE_LIGHTSOURCE)
2684                 {
2685                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2686                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2687                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2688                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2689                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2690                         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);
2691         
2692                         // additive passes are only darkened by fog, not tinted
2693                         if (r_glsl_permutation->loc_FogColor >= 0)
2694                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2695                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2696                 }
2697                 else
2698                 {
2699                         if (mode == SHADERMODE_FLATCOLOR)
2700                         {
2701                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2702                         }
2703                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2704                         {
2705                                 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]);
2706                                 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]);
2707                                 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);
2708                                 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);
2709                                 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);
2710                                 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]);
2711                                 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]);
2712                         }
2713                         else
2714                         {
2715                                 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]);
2716                                 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]);
2717                                 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);
2718                                 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);
2719                                 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);
2720                         }
2721                         // additive passes are only darkened by fog, not tinted
2722                         if (r_glsl_permutation->loc_FogColor >= 0)
2723                         {
2724                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2725                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2726                                 else
2727                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2728                         }
2729                         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);
2730                         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]);
2731                         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]);
2732                         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]);
2733                         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]);
2734                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2735                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2736                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2737                         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]);
2738                 }
2739                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2740                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2741                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2742                 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]);
2743                 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]);
2744
2745                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2746                 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));
2747                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2748                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2749                 {
2750                         if (rsurface.texture->pantstexture)
2751                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2752                         else
2753                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2754                 }
2755                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2756                 {
2757                         if (rsurface.texture->shirttexture)
2758                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2759                         else
2760                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2761                 }
2762                 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]);
2763                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2764                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2765                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2766                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2767                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2768                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2769                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2770                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2771                         );
2772                 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]);
2773                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2774                 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);}
2775                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2776
2777                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2778                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2779                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2780                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2781                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2782                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2783                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2784                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2785                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2786                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2787                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2788                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2789                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2790                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2791                 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);
2792                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2793                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2794                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2795                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2796                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2797                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2798                 {
2799                         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);
2800                         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);
2801                         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);
2802                 }
2803                 else
2804                 {
2805                         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);
2806                 }
2807                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2808                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2809                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2810                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2811                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2812                 {
2813                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2814                         if (rsurface.rtlight)
2815                         {
2816                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2817                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2818                         }
2819                 }
2820                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2821                 CHECKGLERROR
2822                 break;
2823         case RENDERPATH_GL11:
2824         case RENDERPATH_GL13:
2825         case RENDERPATH_GLES1:
2826                 break;
2827         case RENDERPATH_SOFT:
2828                 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);
2829                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2830                 R_SetupShader_SetPermutationSoft(mode, permutation);
2831                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2832                 if (mode == SHADERMODE_LIGHTSOURCE)
2833                 {
2834                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2835                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2836                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2837                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2838                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2839                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2840         
2841                         // additive passes are only darkened by fog, not tinted
2842                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2843                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2844                 }
2845                 else
2846                 {
2847                         if (mode == SHADERMODE_FLATCOLOR)
2848                         {
2849                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2850                         }
2851                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2852                         {
2853                                 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]);
2854                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2855                                 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);
2856                                 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);
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2858                                 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]);
2859                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2860                         }
2861                         else
2862                         {
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2864                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2865                                 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);
2866                                 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);
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2868                         }
2869                         // additive passes are only darkened by fog, not tinted
2870                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2872                         else
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2874                         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);
2875                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2876                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2877                         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]);
2878                         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]);
2879                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2880                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2881                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2882                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2883                 }
2884                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2885                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2886                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2887                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2888                 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]);
2889
2890                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2891                 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));
2892                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2893                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2894                 {
2895                         if (rsurface.texture->pantstexture)
2896                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2897                         else
2898                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2899                 }
2900                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2901                 {
2902                         if (rsurface.texture->shirttexture)
2903                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2904                         else
2905                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2906                 }
2907                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2908                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2909                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2910                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2911                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2912                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2913                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2914                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2915                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2916                         );
2917                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2918                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2919
2920                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2921                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2922                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2923                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2924                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2925                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2926                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2927                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2928                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2929                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2930                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2931                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2932                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2933                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2934                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2935                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2936                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2937                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2938                 {
2939                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2940                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2941                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2942                 }
2943                 else
2944                 {
2945                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2946                 }
2947 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2948 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2949                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2950                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2951                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2952                 {
2953                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2954                         if (rsurface.rtlight)
2955                         {
2956                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2957                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2958                         }
2959                 }
2960                 break;
2961         }
2962 }
2963
2964 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2965 {
2966         // select a permutation of the lighting shader appropriate to this
2967         // combination of texture, entity, light source, and fogging, only use the
2968         // minimum features necessary to avoid wasting rendering time in the
2969         // fragment shader on features that are not being used
2970         unsigned int permutation = 0;
2971         unsigned int mode = 0;
2972         const float *lightcolorbase = rtlight->currentcolor;
2973         float ambientscale = rtlight->ambientscale;
2974         float diffusescale = rtlight->diffusescale;
2975         float specularscale = rtlight->specularscale;
2976         // this is the location of the light in view space
2977         vec3_t viewlightorigin;
2978         // this transforms from view space (camera) to light space (cubemap)
2979         matrix4x4_t viewtolight;
2980         matrix4x4_t lighttoview;
2981         float viewtolight16f[16];
2982         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2983         // light source
2984         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2985         if (rtlight->currentcubemap != r_texture_whitecube)
2986                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2987         if (diffusescale > 0)
2988                 permutation |= SHADERPERMUTATION_DIFFUSE;
2989         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2990                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2991         if (r_shadow_usingshadowmap2d)
2992         {
2993                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2994                 if (r_shadow_shadowmapvsdct)
2995                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2996
2997                 if (r_shadow_shadowmapsampler)
2998                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2999                 if (r_shadow_shadowmappcf > 1)
3000                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3001                 else if (r_shadow_shadowmappcf)
3002                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3003         }
3004         if (vid.allowalphatocoverage)
3005                 GL_AlphaToCoverage(false);
3006         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3007         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3008         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3009         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3010         switch(vid.renderpath)
3011         {
3012         case RENDERPATH_D3D9:
3013 #ifdef SUPPORTD3D
3014                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3015                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3016                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3017                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3018                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3019                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3020                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3021                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3022                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3023                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3024                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3025
3026                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3027                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3028                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3029                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3030                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3031                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3032 #endif
3033                 break;
3034         case RENDERPATH_D3D10:
3035                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3036                 break;
3037         case RENDERPATH_D3D11:
3038                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3039                 break;
3040         case RENDERPATH_GL20:
3041         case RENDERPATH_GLES2:
3042                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3043                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3044                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3045                 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);
3046                 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);
3047                 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);
3048                 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]);
3049                 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]);
3050                 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));
3051                 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]);
3052                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3053
3054                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3055                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3056                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3057                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3058                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3059                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3060                 break;
3061         case RENDERPATH_GL11:
3062         case RENDERPATH_GL13:
3063         case RENDERPATH_GLES1:
3064                 break;
3065         case RENDERPATH_SOFT:
3066                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3067                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3068                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3069                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3070                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3071                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3072                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3073                 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]);
3074                 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));
3075                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3076                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3077
3078                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3079                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3080                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3081                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3082                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3083                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3084                 break;
3085         }
3086 }
3087
3088 #define SKINFRAME_HASH 1024
3089
3090 typedef struct
3091 {
3092         int loadsequence; // incremented each level change
3093         memexpandablearray_t array;
3094         skinframe_t *hash[SKINFRAME_HASH];
3095 }
3096 r_skinframe_t;
3097 r_skinframe_t r_skinframe;
3098
3099 void R_SkinFrame_PrepareForPurge(void)
3100 {
3101         r_skinframe.loadsequence++;
3102         // wrap it without hitting zero
3103         if (r_skinframe.loadsequence >= 200)
3104                 r_skinframe.loadsequence = 1;
3105 }
3106
3107 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3108 {
3109         if (!skinframe)
3110                 return;
3111         // mark the skinframe as used for the purging code
3112         skinframe->loadsequence = r_skinframe.loadsequence;
3113 }
3114
3115 void R_SkinFrame_Purge(void)
3116 {
3117         int i;
3118         skinframe_t *s;
3119         for (i = 0;i < SKINFRAME_HASH;i++)
3120         {
3121                 for (s = r_skinframe.hash[i];s;s = s->next)
3122                 {
3123                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3124                         {
3125                                 if (s->merged == s->base)
3126                                         s->merged = NULL;
3127                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3128                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3129                                 R_PurgeTexture(s->merged);s->merged = NULL;
3130                                 R_PurgeTexture(s->base  );s->base   = NULL;
3131                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3132                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3133                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3134                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3135                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3136                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3137                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3138                                 s->loadsequence = 0;
3139                         }
3140                 }
3141         }
3142 }
3143
3144 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3145         skinframe_t *item;
3146         char basename[MAX_QPATH];
3147
3148         Image_StripImageExtension(name, basename, sizeof(basename));
3149
3150         if( last == NULL ) {
3151                 int hashindex;
3152                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3153                 item = r_skinframe.hash[hashindex];
3154         } else {
3155                 item = last->next;
3156         }
3157
3158         // linearly search through the hash bucket
3159         for( ; item ; item = item->next ) {
3160                 if( !strcmp( item->basename, basename ) ) {
3161                         return item;
3162                 }
3163         }
3164         return NULL;
3165 }
3166
3167 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3168 {
3169         skinframe_t *item;
3170         int hashindex;
3171         char basename[MAX_QPATH];
3172
3173         Image_StripImageExtension(name, basename, sizeof(basename));
3174
3175         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3176         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3177                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3178                         break;
3179
3180         if (!item) {
3181                 rtexture_t *dyntexture;
3182                 // check whether its a dynamic texture
3183                 dyntexture = CL_GetDynTexture( basename );
3184                 if (!add && !dyntexture)
3185                         return NULL;
3186                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3187                 memset(item, 0, sizeof(*item));
3188                 strlcpy(item->basename, basename, sizeof(item->basename));
3189                 item->base = dyntexture; // either NULL or dyntexture handle
3190                 item->textureflags = textureflags;
3191                 item->comparewidth = comparewidth;
3192                 item->compareheight = compareheight;
3193                 item->comparecrc = comparecrc;
3194                 item->next = r_skinframe.hash[hashindex];
3195                 r_skinframe.hash[hashindex] = item;
3196         }
3197         else if( item->base == NULL )
3198         {
3199                 rtexture_t *dyntexture;
3200                 // check whether its a dynamic texture
3201                 // 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]
3202                 dyntexture = CL_GetDynTexture( basename );
3203                 item->base = dyntexture; // either NULL or dyntexture handle
3204         }
3205
3206         R_SkinFrame_MarkUsed(item);
3207         return item;
3208 }
3209
3210 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3211         { \
3212                 unsigned long long avgcolor[5], wsum; \
3213                 int pix, comp, w; \
3214                 avgcolor[0] = 0; \
3215                 avgcolor[1] = 0; \
3216                 avgcolor[2] = 0; \
3217                 avgcolor[3] = 0; \
3218                 avgcolor[4] = 0; \
3219                 wsum = 0; \
3220                 for(pix = 0; pix < cnt; ++pix) \
3221                 { \
3222                         w = 0; \
3223                         for(comp = 0; comp < 3; ++comp) \
3224                                 w += getpixel; \
3225                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3226                         { \
3227                                 ++wsum; \
3228                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3229                                 w = getpixel; \
3230                                 for(comp = 0; comp < 3; ++comp) \
3231                                         avgcolor[comp] += getpixel * w; \
3232                                 avgcolor[3] += w; \
3233                         } \
3234                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3235                         avgcolor[4] += getpixel; \
3236                 } \
3237                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3238                         avgcolor[3] = 1; \
3239                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3240                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3241                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3242                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3243         }
3244
3245 extern cvar_t gl_picmip;
3246 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3247 {
3248         int j;
3249         unsigned char *pixels;
3250         unsigned char *bumppixels;
3251         unsigned char *basepixels = NULL;
3252         int basepixels_width = 0;
3253         int basepixels_height = 0;
3254         skinframe_t *skinframe;
3255         rtexture_t *ddsbase = NULL;
3256         qboolean ddshasalpha = false;
3257         float ddsavgcolor[4];
3258         char basename[MAX_QPATH];
3259         int miplevel = R_PicmipForFlags(textureflags);
3260         int savemiplevel = miplevel;
3261         int mymiplevel;
3262
3263         if (cls.state == ca_dedicated)
3264                 return NULL;
3265
3266         // return an existing skinframe if already loaded
3267         // if loading of the first image fails, don't make a new skinframe as it
3268         // would cause all future lookups of this to be missing
3269         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3270         if (skinframe && skinframe->base)
3271                 return skinframe;
3272
3273         Image_StripImageExtension(name, basename, sizeof(basename));
3274
3275         // check for DDS texture file first
3276         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3277         {
3278                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3279                 if (basepixels == NULL)
3280                         return NULL;
3281         }
3282
3283         // FIXME handle miplevel
3284
3285         if (developer_loading.integer)
3286                 Con_Printf("loading skin \"%s\"\n", name);
3287
3288         // we've got some pixels to store, so really allocate this new texture now
3289         if (!skinframe)
3290                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3291         skinframe->stain = NULL;
3292         skinframe->merged = NULL;
3293         skinframe->base = NULL;
3294         skinframe->pants = NULL;
3295         skinframe->shirt = NULL;
3296         skinframe->nmap = NULL;
3297         skinframe->gloss = NULL;
3298         skinframe->glow = NULL;
3299         skinframe->fog = NULL;
3300         skinframe->reflect = NULL;
3301         skinframe->hasalpha = false;
3302
3303         if (ddsbase)
3304         {
3305                 skinframe->base = ddsbase;
3306                 skinframe->hasalpha = ddshasalpha;
3307                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3308                 if (r_loadfog && skinframe->hasalpha)
3309                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3310                 //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]);
3311         }
3312         else
3313         {
3314                 basepixels_width = image_width;
3315                 basepixels_height = image_height;
3316                 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);
3317                 if (textureflags & TEXF_ALPHA)
3318                 {
3319                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3320                         {
3321                                 if (basepixels[j] < 255)
3322                                 {
3323                                         skinframe->hasalpha = true;
3324                                         break;
3325                                 }
3326                         }
3327                         if (r_loadfog && skinframe->hasalpha)
3328                         {
3329                                 // has transparent pixels
3330                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3331                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3332                                 {
3333                                         pixels[j+0] = 255;
3334                                         pixels[j+1] = 255;
3335                                         pixels[j+2] = 255;
3336                                         pixels[j+3] = basepixels[j+3];
3337                                 }
3338                                 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);
3339                                 Mem_Free(pixels);
3340                         }
3341                 }
3342                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3343                 //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]);
3344                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3345                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3346                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3347                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3348         }
3349
3350         if (r_loaddds)
3351         {
3352                 mymiplevel = savemiplevel;
3353                 if (r_loadnormalmap)
3354                         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);
3355                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3356                 if (r_loadgloss)
3357                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3358                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3359                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3360                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3361         }
3362
3363         // _norm is the name used by tenebrae and has been adopted as standard
3364         if (r_loadnormalmap && skinframe->nmap == NULL)
3365         {
3366                 mymiplevel = savemiplevel;
3367                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3368                 {
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                         pixels = NULL;
3372                 }
3373                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3374                 {
3375                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3376                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3377                         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);
3378                         Mem_Free(pixels);
3379                         Mem_Free(bumppixels);
3380                 }
3381                 else if (r_shadow_bumpscale_basetexture.value > 0)
3382                 {
3383                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3384                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3385                         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);
3386                         Mem_Free(pixels);
3387                 }
3388                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3389                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3390         }
3391
3392         // _luma is supported only for tenebrae compatibility
3393         // _glow is the preferred name
3394         mymiplevel = savemiplevel;
3395         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))))
3396         {
3397                 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);
3398                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3399                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3400                 Mem_Free(pixels);pixels = NULL;
3401         }
3402
3403         mymiplevel = savemiplevel;
3404         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3405         {
3406                 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);
3407                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3408                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3409                 Mem_Free(pixels);
3410                 pixels = NULL;
3411         }
3412
3413         mymiplevel = savemiplevel;
3414         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3415         {
3416                 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);
3417                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3418                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3419                 Mem_Free(pixels);
3420                 pixels = NULL;
3421         }
3422
3423         mymiplevel = savemiplevel;
3424         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3425         {
3426                 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);
3427                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3428                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3429                 Mem_Free(pixels);
3430                 pixels = NULL;
3431         }
3432
3433         mymiplevel = savemiplevel;
3434         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3435         {
3436                 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);
3437                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3438                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3439                 Mem_Free(pixels);
3440                 pixels = NULL;
3441         }
3442
3443         if (basepixels)
3444                 Mem_Free(basepixels);
3445
3446         return skinframe;
3447 }
3448
3449 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3450 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3451 {
3452         int i;
3453         unsigned char *temp1, *temp2;
3454         skinframe_t *skinframe;
3455
3456         if (cls.state == ca_dedicated)
3457                 return NULL;
3458
3459         // if already loaded just return it, otherwise make a new skinframe
3460         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3461         if (skinframe && skinframe->base)
3462                 return skinframe;
3463
3464         skinframe->stain = NULL;
3465         skinframe->merged = NULL;
3466         skinframe->base = NULL;
3467         skinframe->pants = NULL;
3468         skinframe->shirt = NULL;
3469         skinframe->nmap = NULL;
3470         skinframe->gloss = NULL;
3471         skinframe->glow = NULL;
3472         skinframe->fog = NULL;
3473         skinframe->reflect = NULL;
3474         skinframe->hasalpha = false;
3475
3476         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3477         if (!skindata)
3478                 return NULL;
3479
3480         if (developer_loading.integer)
3481                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3482
3483         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3484         {
3485                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3486                 temp2 = temp1 + width * height * 4;
3487                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3488                 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);
3489                 Mem_Free(temp1);
3490         }
3491         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3492         if (textureflags & TEXF_ALPHA)
3493         {
3494                 for (i = 3;i < width * height * 4;i += 4)
3495                 {
3496                         if (skindata[i] < 255)
3497                         {
3498                                 skinframe->hasalpha = true;
3499                                 break;
3500                         }
3501                 }
3502                 if (r_loadfog && skinframe->hasalpha)
3503                 {
3504                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3505                         memcpy(fogpixels, skindata, width * height * 4);
3506                         for (i = 0;i < width * height * 4;i += 4)
3507                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3508                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3509                         Mem_Free(fogpixels);
3510                 }
3511         }
3512
3513         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3514         //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]);
3515
3516         return skinframe;
3517 }
3518
3519 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3520 {
3521         int i;
3522         int featuresmask;
3523         skinframe_t *skinframe;
3524
3525         if (cls.state == ca_dedicated)
3526                 return NULL;
3527
3528         // if already loaded just return it, otherwise make a new skinframe
3529         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3530         if (skinframe && skinframe->base)
3531                 return skinframe;
3532
3533         skinframe->stain = NULL;
3534         skinframe->merged = NULL;
3535         skinframe->base = NULL;
3536         skinframe->pants = NULL;
3537         skinframe->shirt = NULL;
3538         skinframe->nmap = NULL;
3539         skinframe->gloss = NULL;
3540         skinframe->glow = NULL;
3541         skinframe->fog = NULL;
3542         skinframe->reflect = NULL;
3543         skinframe->hasalpha = false;
3544
3545         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3546         if (!skindata)
3547                 return NULL;
3548
3549         if (developer_loading.integer)
3550                 Con_Printf("loading quake skin \"%s\"\n", name);
3551
3552         // 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)
3553         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3554         memcpy(skinframe->qpixels, skindata, width*height);
3555         skinframe->qwidth = width;
3556         skinframe->qheight = height;
3557
3558         featuresmask = 0;
3559         for (i = 0;i < width * height;i++)
3560                 featuresmask |= palette_featureflags[skindata[i]];
3561
3562         skinframe->hasalpha = false;
3563         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3564         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3565         skinframe->qgeneratemerged = true;
3566         skinframe->qgeneratebase = skinframe->qhascolormapping;
3567         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3568
3569         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3570         //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]);
3571
3572         return skinframe;
3573 }
3574
3575 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3576 {
3577         int width;
3578         int height;
3579         unsigned char *skindata;
3580
3581         if (!skinframe->qpixels)
3582                 return;
3583
3584         if (!skinframe->qhascolormapping)
3585                 colormapped = false;
3586
3587         if (colormapped)
3588         {
3589                 if (!skinframe->qgeneratebase)
3590                         return;
3591         }
3592         else
3593         {
3594                 if (!skinframe->qgeneratemerged)
3595                         return;
3596         }
3597
3598         width = skinframe->qwidth;
3599         height = skinframe->qheight;
3600         skindata = skinframe->qpixels;
3601
3602         if (skinframe->qgeneratenmap)
3603         {
3604                 unsigned char *temp1, *temp2;
3605                 skinframe->qgeneratenmap = false;
3606                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3607                 temp2 = temp1 + width * height * 4;
3608                 // use either a custom palette or the quake palette
3609                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3610                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3611                 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);
3612                 Mem_Free(temp1);
3613         }
3614
3615         if (skinframe->qgenerateglow)
3616         {
3617                 skinframe->qgenerateglow = false;
3618                 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
3619         }
3620
3621         if (colormapped)
3622         {
3623                 skinframe->qgeneratebase = false;
3624                 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);
3625                 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);
3626                 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);
3627         }
3628         else
3629         {
3630                 skinframe->qgeneratemerged = false;
3631                 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);
3632         }
3633
3634         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3635         {
3636                 Mem_Free(skinframe->qpixels);
3637                 skinframe->qpixels = NULL;
3638         }
3639 }
3640
3641 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)
3642 {
3643         int i;
3644         skinframe_t *skinframe;
3645
3646         if (cls.state == ca_dedicated)
3647                 return NULL;
3648
3649         // if already loaded just return it, otherwise make a new skinframe
3650         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3651         if (skinframe && skinframe->base)
3652                 return skinframe;
3653
3654         skinframe->stain = NULL;
3655         skinframe->merged = NULL;
3656         skinframe->base = NULL;
3657         skinframe->pants = NULL;
3658         skinframe->shirt = NULL;
3659         skinframe->nmap = NULL;
3660         skinframe->gloss = NULL;
3661         skinframe->glow = NULL;
3662         skinframe->fog = NULL;
3663         skinframe->reflect = NULL;
3664         skinframe->hasalpha = false;
3665
3666         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3667         if (!skindata)
3668                 return NULL;
3669
3670         if (developer_loading.integer)
3671                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3672
3673         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3674         if (textureflags & TEXF_ALPHA)
3675         {
3676                 for (i = 0;i < width * height;i++)
3677                 {
3678                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3679                         {
3680                                 skinframe->hasalpha = true;
3681                                 break;
3682                         }
3683                 }
3684                 if (r_loadfog && skinframe->hasalpha)
3685                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3686         }
3687
3688         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3689         //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]);
3690
3691         return skinframe;
3692 }
3693
3694 skinframe_t *R_SkinFrame_LoadMissing(void)
3695 {
3696         skinframe_t *skinframe;
3697
3698         if (cls.state == ca_dedicated)
3699                 return NULL;
3700
3701         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3702         skinframe->stain = NULL;
3703         skinframe->merged = NULL;
3704         skinframe->base = NULL;
3705         skinframe->pants = NULL;
3706         skinframe->shirt = NULL;
3707         skinframe->nmap = NULL;
3708         skinframe->gloss = NULL;
3709         skinframe->glow = NULL;
3710         skinframe->fog = NULL;
3711         skinframe->reflect = NULL;
3712         skinframe->hasalpha = false;
3713
3714         skinframe->avgcolor[0] = rand() / RAND_MAX;
3715         skinframe->avgcolor[1] = rand() / RAND_MAX;
3716         skinframe->avgcolor[2] = rand() / RAND_MAX;
3717         skinframe->avgcolor[3] = 1;
3718
3719         return skinframe;
3720 }
3721
3722 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3723 typedef struct suffixinfo_s
3724 {
3725         const char *suffix;
3726         qboolean flipx, flipy, flipdiagonal;
3727 }
3728 suffixinfo_t;
3729 static suffixinfo_t suffix[3][6] =
3730 {
3731         {
3732                 {"px",   false, false, false},
3733                 {"nx",   false, false, false},
3734                 {"py",   false, false, false},
3735                 {"ny",   false, false, false},
3736                 {"pz",   false, false, false},
3737                 {"nz",   false, false, false}
3738         },
3739         {
3740                 {"posx", false, false, false},
3741                 {"negx", false, false, false},
3742                 {"posy", false, false, false},
3743                 {"negy", false, false, false},
3744                 {"posz", false, false, false},
3745                 {"negz", false, false, false}
3746         },
3747         {
3748                 {"rt",    true, false,  true},
3749                 {"lf",   false,  true,  true},
3750                 {"ft",    true,  true, false},
3751                 {"bk",   false, false, false},
3752                 {"up",    true, false,  true},
3753                 {"dn",    true, false,  true}
3754         }
3755 };
3756
3757 static int componentorder[4] = {0, 1, 2, 3};
3758
3759 rtexture_t *R_LoadCubemap(const char *basename)
3760 {
3761         int i, j, cubemapsize;
3762         unsigned char *cubemappixels, *image_buffer;
3763         rtexture_t *cubemaptexture;
3764         char name[256];
3765         // must start 0 so the first loadimagepixels has no requested width/height
3766         cubemapsize = 0;
3767         cubemappixels = NULL;
3768         cubemaptexture = NULL;
3769         // keep trying different suffix groups (posx, px, rt) until one loads
3770         for (j = 0;j < 3 && !cubemappixels;j++)
3771         {
3772                 // load the 6 images in the suffix group
3773                 for (i = 0;i < 6;i++)
3774                 {
3775                         // generate an image name based on the base and and suffix
3776                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3777                         // load it
3778                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3779                         {
3780                                 // an image loaded, make sure width and height are equal
3781                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3782                                 {
3783                                         // if this is the first image to load successfully, allocate the cubemap memory
3784                                         if (!cubemappixels && image_width >= 1)
3785                                         {
3786                                                 cubemapsize = image_width;
3787                                                 // note this clears to black, so unavailable sides are black
3788                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3789                                         }
3790                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3791                                         if (cubemappixels)
3792                                                 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);
3793                                 }
3794                                 else
3795                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3796                                 // free the image
3797                                 Mem_Free(image_buffer);
3798                         }
3799                 }
3800         }
3801         // if a cubemap loaded, upload it
3802         if (cubemappixels)
3803         {
3804                 if (developer_loading.integer)
3805                         Con_Printf("loading cubemap \"%s\"\n", basename);
3806
3807                 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);
3808                 Mem_Free(cubemappixels);
3809         }
3810         else
3811         {
3812                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3813                 if (developer_loading.integer)
3814                 {
3815                         Con_Printf("(tried tried images ");
3816                         for (j = 0;j < 3;j++)
3817                                 for (i = 0;i < 6;i++)
3818                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3819                         Con_Print(" and was unable to find any of them).\n");
3820                 }
3821         }
3822         return cubemaptexture;
3823 }
3824
3825 rtexture_t *R_GetCubemap(const char *basename)
3826 {
3827         int i;
3828         for (i = 0;i < r_texture_numcubemaps;i++)
3829                 if (r_texture_cubemaps[i] != NULL)
3830                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3831                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3832         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3833                 return r_texture_whitecube;
3834         r_texture_numcubemaps++;
3835         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3836         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3837         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3838         return r_texture_cubemaps[i]->texture;
3839 }
3840
3841 void R_FreeCubemap(const char *basename)
3842 {
3843         int i;
3844
3845         for (i = 0;i < r_texture_numcubemaps;i++)
3846         {
3847                 if (r_texture_cubemaps[i] != NULL)
3848                 {
3849                         if (r_texture_cubemaps[i]->texture)
3850                         {
3851                                 if (developer_loading.integer)
3852                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3853                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3854                                 Mem_Free(r_texture_cubemaps[i]);
3855                                 r_texture_cubemaps[i] = NULL;
3856                         }
3857                 }
3858         }
3859 }
3860
3861 void R_FreeCubemaps(void)
3862 {
3863         int i;
3864         for (i = 0;i < r_texture_numcubemaps;i++)
3865         {
3866                 if (developer_loading.integer)
3867                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3868                 if (r_texture_cubemaps[i] != NULL)
3869                 {
3870                         if (r_texture_cubemaps[i]->texture)
3871                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3872                         Mem_Free(r_texture_cubemaps[i]);
3873                 }
3874         }
3875         r_texture_numcubemaps = 0;
3876 }
3877
3878 void R_Main_FreeViewCache(void)
3879 {
3880         if (r_refdef.viewcache.entityvisible)
3881                 Mem_Free(r_refdef.viewcache.entityvisible);
3882         if (r_refdef.viewcache.world_pvsbits)
3883                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3884         if (r_refdef.viewcache.world_leafvisible)
3885                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3886         if (r_refdef.viewcache.world_surfacevisible)
3887                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3888         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3889 }
3890
3891 void R_Main_ResizeViewCache(void)
3892 {
3893         int numentities = r_refdef.scene.numentities;
3894         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3895         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3896         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3897         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3898         if (r_refdef.viewcache.maxentities < numentities)
3899         {
3900                 r_refdef.viewcache.maxentities = numentities;
3901                 if (r_refdef.viewcache.entityvisible)
3902                         Mem_Free(r_refdef.viewcache.entityvisible);
3903                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3904         }
3905         if (r_refdef.viewcache.world_numclusters != numclusters)
3906         {
3907                 r_refdef.viewcache.world_numclusters = numclusters;
3908                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3909                 if (r_refdef.viewcache.world_pvsbits)
3910                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3911                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3912         }
3913         if (r_refdef.viewcache.world_numleafs != numleafs)
3914         {
3915                 r_refdef.viewcache.world_numleafs = numleafs;
3916                 if (r_refdef.viewcache.world_leafvisible)
3917                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3918                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3919         }
3920         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3921         {
3922                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3923                 if (r_refdef.viewcache.world_surfacevisible)
3924                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3925                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3926         }
3927 }
3928
3929 extern rtexture_t *loadingscreentexture;
3930 void gl_main_start(void)
3931 {
3932         loadingscreentexture = NULL;
3933         r_texture_blanknormalmap = NULL;
3934         r_texture_white = NULL;
3935         r_texture_grey128 = NULL;
3936         r_texture_black = NULL;
3937         r_texture_whitecube = NULL;
3938         r_texture_normalizationcube = NULL;
3939         r_texture_fogattenuation = NULL;
3940         r_texture_fogheighttexture = NULL;
3941         r_texture_gammaramps = NULL;
3942         r_texture_numcubemaps = 0;
3943
3944         r_loaddds = r_texture_dds_load.integer != 0;
3945         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3946
3947         switch(vid.renderpath)
3948         {
3949         case RENDERPATH_GL20:
3950         case RENDERPATH_D3D9:
3951         case RENDERPATH_D3D10:
3952         case RENDERPATH_D3D11:
3953         case RENDERPATH_SOFT:
3954         case RENDERPATH_GLES2:
3955                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3956                 Cvar_SetValueQuick(&gl_combine, 1);
3957                 Cvar_SetValueQuick(&r_glsl, 1);
3958                 r_loadnormalmap = true;
3959                 r_loadgloss = true;
3960                 r_loadfog = false;
3961                 break;
3962         case RENDERPATH_GL13:
3963         case RENDERPATH_GLES1:
3964                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3965                 Cvar_SetValueQuick(&gl_combine, 1);
3966                 Cvar_SetValueQuick(&r_glsl, 0);
3967                 r_loadnormalmap = false;
3968                 r_loadgloss = false;
3969                 r_loadfog = true;
3970                 break;
3971         case RENDERPATH_GL11:
3972                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3973                 Cvar_SetValueQuick(&gl_combine, 0);
3974                 Cvar_SetValueQuick(&r_glsl, 0);
3975                 r_loadnormalmap = false;
3976                 r_loadgloss = false;
3977                 r_loadfog = true;
3978                 break;
3979         }
3980
3981         R_AnimCache_Free();
3982         R_FrameData_Reset();
3983
3984         r_numqueries = 0;
3985         r_maxqueries = 0;
3986         memset(r_queries, 0, sizeof(r_queries));
3987
3988         r_qwskincache = NULL;
3989         r_qwskincache_size = 0;
3990
3991         // due to caching of texture_t references, the collision cache must be reset
3992         Collision_Cache_Reset(true);
3993
3994         // set up r_skinframe loading system for textures
3995         memset(&r_skinframe, 0, sizeof(r_skinframe));
3996         r_skinframe.loadsequence = 1;
3997         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3998
3999         r_main_texturepool = R_AllocTexturePool();
4000         R_BuildBlankTextures();
4001         R_BuildNoTexture();
4002         if (vid.support.arb_texture_cube_map)
4003         {
4004                 R_BuildWhiteCube();
4005                 R_BuildNormalizationCube();
4006         }
4007         r_texture_fogattenuation = NULL;
4008         r_texture_fogheighttexture = NULL;
4009         r_texture_gammaramps = NULL;
4010         //r_texture_fogintensity = NULL;
4011         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4012         memset(&r_waterstate, 0, sizeof(r_waterstate));
4013         r_glsl_permutation = NULL;
4014         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4015         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4016         glslshaderstring = NULL;
4017 #ifdef SUPPORTD3D
4018         r_hlsl_permutation = NULL;
4019         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4020         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4021 #endif
4022         hlslshaderstring = NULL;
4023         memset(&r_svbsp, 0, sizeof (r_svbsp));
4024
4025         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4026         r_texture_numcubemaps = 0;
4027
4028         r_refdef.fogmasktable_density = 0;
4029 }
4030
4031 void gl_main_shutdown(void)
4032 {
4033         R_AnimCache_Free();
4034         R_FrameData_Reset();
4035
4036         R_Main_FreeViewCache();
4037
4038         switch(vid.renderpath)
4039         {
4040         case RENDERPATH_GL11:
4041         case RENDERPATH_GL13:
4042         case RENDERPATH_GL20:
4043         case RENDERPATH_GLES1:
4044         case RENDERPATH_GLES2:
4045                 if (r_maxqueries)
4046                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4047                 break;
4048         case RENDERPATH_D3D9:
4049                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4050                 break;
4051         case RENDERPATH_D3D10:
4052                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4053                 break;
4054         case RENDERPATH_D3D11:
4055                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4056                 break;
4057         case RENDERPATH_SOFT:
4058                 break;
4059         }
4060
4061         r_numqueries = 0;
4062         r_maxqueries = 0;
4063         memset(r_queries, 0, sizeof(r_queries));
4064
4065         r_qwskincache = NULL;
4066         r_qwskincache_size = 0;
4067
4068         // clear out the r_skinframe state
4069         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4070         memset(&r_skinframe, 0, sizeof(r_skinframe));
4071
4072         if (r_svbsp.nodes)
4073                 Mem_Free(r_svbsp.nodes);
4074         memset(&r_svbsp, 0, sizeof (r_svbsp));
4075         R_FreeTexturePool(&r_main_texturepool);
4076         loadingscreentexture = NULL;
4077         r_texture_blanknormalmap = NULL;
4078         r_texture_white = NULL;
4079         r_texture_grey128 = NULL;
4080         r_texture_black = NULL;
4081         r_texture_whitecube = NULL;
4082         r_texture_normalizationcube = NULL;
4083         r_texture_fogattenuation = NULL;
4084         r_texture_fogheighttexture = NULL;
4085         r_texture_gammaramps = NULL;
4086         r_texture_numcubemaps = 0;
4087         //r_texture_fogintensity = NULL;
4088         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4089         memset(&r_waterstate, 0, sizeof(r_waterstate));
4090         R_GLSL_Restart_f();
4091
4092         r_glsl_permutation = NULL;
4093         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4094         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4095         glslshaderstring = NULL;
4096 #ifdef SUPPORTD3D
4097         r_hlsl_permutation = NULL;
4098         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4099         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4100 #endif
4101         hlslshaderstring = NULL;
4102 }
4103
4104 extern void CL_ParseEntityLump(char *entitystring);
4105 void gl_main_newmap(void)
4106 {
4107         // FIXME: move this code to client
4108         char *entities, entname[MAX_QPATH];
4109         if (r_qwskincache)
4110                 Mem_Free(r_qwskincache);
4111         r_qwskincache = NULL;
4112         r_qwskincache_size = 0;
4113         if (cl.worldmodel)
4114         {
4115                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4116                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4117                 {
4118                         CL_ParseEntityLump(entities);
4119                         Mem_Free(entities);
4120                         return;
4121                 }
4122                 if (cl.worldmodel->brush.entities)
4123                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4124         }
4125         R_Main_FreeViewCache();
4126
4127         R_FrameData_Reset();
4128 }
4129
4130 void GL_Main_Init(void)
4131 {
4132         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4133
4134         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4135         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4136         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4137         if (gamemode == GAME_NEHAHRA)
4138         {
4139                 Cvar_RegisterVariable (&gl_fogenable);
4140                 Cvar_RegisterVariable (&gl_fogdensity);
4141                 Cvar_RegisterVariable (&gl_fogred);
4142                 Cvar_RegisterVariable (&gl_foggreen);
4143                 Cvar_RegisterVariable (&gl_fogblue);
4144                 Cvar_RegisterVariable (&gl_fogstart);
4145                 Cvar_RegisterVariable (&gl_fogend);
4146                 Cvar_RegisterVariable (&gl_skyclip);
4147         }
4148         Cvar_RegisterVariable(&r_motionblur);
4149         Cvar_RegisterVariable(&r_damageblur);
4150         Cvar_RegisterVariable(&r_motionblur_averaging);
4151         Cvar_RegisterVariable(&r_motionblur_randomize);
4152         Cvar_RegisterVariable(&r_motionblur_minblur);
4153         Cvar_RegisterVariable(&r_motionblur_maxblur);
4154         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4155         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4156         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4157         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4158         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4159         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4160         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4161         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4162         Cvar_RegisterVariable(&r_equalize_entities_by);
4163         Cvar_RegisterVariable(&r_equalize_entities_to);
4164         Cvar_RegisterVariable(&r_depthfirst);
4165         Cvar_RegisterVariable(&r_useinfinitefarclip);
4166         Cvar_RegisterVariable(&r_farclip_base);
4167         Cvar_RegisterVariable(&r_farclip_world);
4168         Cvar_RegisterVariable(&r_nearclip);
4169         Cvar_RegisterVariable(&r_deformvertexes);
4170         Cvar_RegisterVariable(&r_transparent);
4171         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4172         Cvar_RegisterVariable(&r_showoverdraw);
4173         Cvar_RegisterVariable(&r_showbboxes);
4174         Cvar_RegisterVariable(&r_showsurfaces);
4175         Cvar_RegisterVariable(&r_showtris);
4176         Cvar_RegisterVariable(&r_shownormals);
4177         Cvar_RegisterVariable(&r_showlighting);
4178         Cvar_RegisterVariable(&r_showshadowvolumes);
4179         Cvar_RegisterVariable(&r_showcollisionbrushes);
4180         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4181         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4182         Cvar_RegisterVariable(&r_showdisabledepthtest);
4183         Cvar_RegisterVariable(&r_drawportals);
4184         Cvar_RegisterVariable(&r_drawentities);
4185         Cvar_RegisterVariable(&r_draw2d);
4186         Cvar_RegisterVariable(&r_drawworld);
4187         Cvar_RegisterVariable(&r_cullentities_trace);
4188         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4189         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4190         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4191         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4192         Cvar_RegisterVariable(&r_drawviewmodel);
4193         Cvar_RegisterVariable(&r_drawexteriormodel);
4194         Cvar_RegisterVariable(&r_speeds);
4195         Cvar_RegisterVariable(&r_fullbrights);
4196         Cvar_RegisterVariable(&r_wateralpha);
4197         Cvar_RegisterVariable(&r_dynamic);
4198         Cvar_RegisterVariable(&r_fakelight);
4199         Cvar_RegisterVariable(&r_fakelight_intensity);
4200         Cvar_RegisterVariable(&r_fullbright);
4201         Cvar_RegisterVariable(&r_shadows);
4202         Cvar_RegisterVariable(&r_shadows_darken);
4203         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4204         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4205         Cvar_RegisterVariable(&r_shadows_throwdistance);
4206         Cvar_RegisterVariable(&r_shadows_throwdirection);
4207         Cvar_RegisterVariable(&r_shadows_focus);
4208         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4209         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4210         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4211         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4212         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4213         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4214         Cvar_RegisterVariable(&r_fog_exp2);
4215         Cvar_RegisterVariable(&r_fog_clear);
4216         Cvar_RegisterVariable(&r_drawfog);
4217         Cvar_RegisterVariable(&r_transparentdepthmasking);
4218         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4219         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4220         Cvar_RegisterVariable(&r_texture_dds_load);
4221         Cvar_RegisterVariable(&r_texture_dds_save);
4222         Cvar_RegisterVariable(&r_textureunits);
4223         Cvar_RegisterVariable(&gl_combine);
4224         Cvar_RegisterVariable(&r_viewfbo);
4225         Cvar_RegisterVariable(&r_viewscale);
4226         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4227         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4228         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4229         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4230         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4231         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4232         Cvar_RegisterVariable(&r_glsl);
4233         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4234         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4235         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4236         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4237         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4238         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4239         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4240         Cvar_RegisterVariable(&r_glsl_postprocess);
4241         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4242         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4243         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4244         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4245         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4246         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4247         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4248         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4249
4250         Cvar_RegisterVariable(&r_water);
4251         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4252         Cvar_RegisterVariable(&r_water_clippingplanebias);
4253         Cvar_RegisterVariable(&r_water_refractdistort);
4254         Cvar_RegisterVariable(&r_water_reflectdistort);
4255         Cvar_RegisterVariable(&r_water_scissormode);
4256         Cvar_RegisterVariable(&r_water_lowquality);
4257
4258         Cvar_RegisterVariable(&r_lerpsprites);
4259         Cvar_RegisterVariable(&r_lerpmodels);
4260         Cvar_RegisterVariable(&r_lerplightstyles);
4261         Cvar_RegisterVariable(&r_waterscroll);
4262         Cvar_RegisterVariable(&r_bloom);
4263         Cvar_RegisterVariable(&r_bloom_colorscale);
4264         Cvar_RegisterVariable(&r_bloom_brighten);
4265         Cvar_RegisterVariable(&r_bloom_blur);
4266         Cvar_RegisterVariable(&r_bloom_resolution);
4267         Cvar_RegisterVariable(&r_bloom_colorexponent);
4268         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4269         Cvar_RegisterVariable(&r_hdr);
4270         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4271         Cvar_RegisterVariable(&r_hdr_glowintensity);
4272         Cvar_RegisterVariable(&r_hdr_range);
4273         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4274         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4275         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4276         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4277         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4278         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4279         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4280         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4281         Cvar_RegisterVariable(&developer_texturelogging);
4282         Cvar_RegisterVariable(&gl_lightmaps);
4283         Cvar_RegisterVariable(&r_test);
4284         Cvar_RegisterVariable(&r_glsl_saturation);
4285         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4286         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4287         Cvar_RegisterVariable(&r_framedatasize);
4288         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4289                 Cvar_SetValue("r_fullbrights", 0);
4290         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4291 }
4292
4293 extern void R_Textures_Init(void);
4294 extern void GL_Draw_Init(void);
4295 extern void GL_Main_Init(void);
4296 extern void R_Shadow_Init(void);
4297 extern void R_Sky_Init(void);
4298 extern void GL_Surf_Init(void);
4299 extern void R_Particles_Init(void);
4300 extern void R_Explosion_Init(void);
4301 extern void gl_backend_init(void);
4302 extern void Sbar_Init(void);
4303 extern void R_LightningBeams_Init(void);
4304 extern void Mod_RenderInit(void);
4305 extern void Font_Init(void);
4306
4307 void Render_Init(void)
4308 {
4309         gl_backend_init();
4310         R_Textures_Init();
4311         GL_Main_Init();
4312         Font_Init();
4313         GL_Draw_Init();
4314         R_Shadow_Init();
4315         R_Sky_Init();
4316         GL_Surf_Init();
4317         Sbar_Init();
4318         R_Particles_Init();
4319         R_Explosion_Init();
4320         R_LightningBeams_Init();
4321         Mod_RenderInit();
4322 }
4323
4324 /*
4325 ===============
4326 GL_Init
4327 ===============
4328 */
4329 extern char *ENGINE_EXTENSIONS;
4330 void GL_Init (void)
4331 {
4332         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4333         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4334         gl_version = (const char *)qglGetString(GL_VERSION);
4335         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4336
4337         if (!gl_extensions)
4338                 gl_extensions = "";
4339         if (!gl_platformextensions)
4340                 gl_platformextensions = "";
4341
4342         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4343         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4344         Con_Printf("GL_VERSION: %s\n", gl_version);
4345         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4346         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4347
4348         VID_CheckExtensions();
4349
4350         // LordHavoc: report supported extensions
4351         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4352
4353         // clear to black (loading plaque will be seen over this)
4354         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4355 }
4356
4357 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4358 {
4359         int i;
4360         mplane_t *p;
4361         if (r_trippy.integer)
4362                 return false;
4363         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4364         {
4365                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4366                 if (i == 4)
4367                         continue;
4368                 p = r_refdef.view.frustum + i;
4369                 switch(p->signbits)
4370                 {
4371                 default:
4372                 case 0:
4373                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4374                                 return true;
4375                         break;
4376                 case 1:
4377                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4378                                 return true;
4379                         break;
4380                 case 2:
4381                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4382                                 return true;
4383                         break;
4384                 case 3:
4385                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4386                                 return true;
4387                         break;
4388                 case 4:
4389                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4390                                 return true;
4391                         break;
4392                 case 5:
4393                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4394                                 return true;
4395                         break;
4396                 case 6:
4397                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4398                                 return true;
4399                         break;
4400                 case 7:
4401                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4402                                 return true;
4403                         break;
4404                 }
4405         }
4406         return false;
4407 }
4408
4409 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4410 {
4411         int i;
4412         const mplane_t *p;
4413         if (r_trippy.integer)
4414                 return false;
4415         for (i = 0;i < numplanes;i++)
4416         {
4417                 p = planes + i;
4418                 switch(p->signbits)
4419                 {
4420                 default:
4421                 case 0:
4422                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4423                                 return true;
4424                         break;
4425                 case 1:
4426                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4427                                 return true;
4428                         break;
4429                 case 2:
4430                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4431                                 return true;
4432                         break;
4433                 case 3:
4434                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 4:
4438                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 5:
4442                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 6:
4446                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 7:
4450                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 }
4454         }
4455         return false;
4456 }
4457
4458 //==================================================================================
4459
4460 // LordHavoc: this stores temporary data used within the same frame
4461
4462 typedef struct r_framedata_mem_s
4463 {
4464         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4465         size_t size; // how much usable space
4466         size_t current; // how much space in use
4467         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4468         size_t wantedsize; // how much space was allocated
4469         unsigned char *data; // start of real data (16byte aligned)
4470 }
4471 r_framedata_mem_t;
4472
4473 static r_framedata_mem_t *r_framedata_mem;
4474
4475 void R_FrameData_Reset(void)
4476 {
4477         while (r_framedata_mem)
4478         {
4479                 r_framedata_mem_t *next = r_framedata_mem->purge;
4480                 Mem_Free(r_framedata_mem);
4481                 r_framedata_mem = next;
4482         }
4483 }
4484
4485 void R_FrameData_Resize(void)
4486 {
4487         size_t wantedsize;
4488         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4489         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4490         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4491         {
4492                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4493                 newmem->wantedsize = wantedsize;
4494                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4495                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4496                 newmem->current = 0;
4497                 newmem->mark = 0;
4498                 newmem->purge = r_framedata_mem;
4499                 r_framedata_mem = newmem;
4500         }
4501 }
4502
4503 void R_FrameData_NewFrame(void)
4504 {
4505         R_FrameData_Resize();
4506         if (!r_framedata_mem)
4507                 return;
4508         // if we ran out of space on the last frame, free the old memory now
4509         while (r_framedata_mem->purge)
4510         {
4511                 // repeatedly remove the second item in the list, leaving only head
4512                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4513                 Mem_Free(r_framedata_mem->purge);
4514                 r_framedata_mem->purge = next;
4515         }
4516         // reset the current mem pointer
4517         r_framedata_mem->current = 0;
4518         r_framedata_mem->mark = 0;
4519 }
4520
4521 void *R_FrameData_Alloc(size_t size)
4522 {
4523         void *data;
4524
4525         // align to 16 byte boundary - the data pointer is already aligned, so we
4526         // only need to ensure the size of every allocation is also aligned
4527         size = (size + 15) & ~15;
4528
4529         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4530         {
4531                 // emergency - we ran out of space, allocate more memory
4532                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4533                 R_FrameData_Resize();
4534         }
4535
4536         data = r_framedata_mem->data + r_framedata_mem->current;
4537         r_framedata_mem->current += size;
4538
4539         // count the usage for stats
4540         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4541         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4542
4543         return (void *)data;
4544 }
4545
4546 void *R_FrameData_Store(size_t size, void *data)
4547 {
4548         void *d = R_FrameData_Alloc(size);
4549         if (d && data)
4550                 memcpy(d, data, size);
4551         return d;
4552 }
4553
4554 void R_FrameData_SetMark(void)
4555 {
4556         if (!r_framedata_mem)
4557                 return;
4558         r_framedata_mem->mark = r_framedata_mem->current;
4559 }
4560
4561 void R_FrameData_ReturnToMark(void)
4562 {
4563         if (!r_framedata_mem)
4564                 return;
4565         r_framedata_mem->current = r_framedata_mem->mark;
4566 }
4567
4568 //==================================================================================
4569
4570 // LordHavoc: animcache originally written by Echon, rewritten since then
4571
4572 /**
4573  * Animation cache prevents re-generating mesh data for an animated model
4574  * multiple times in one frame for lighting, shadowing, reflections, etc.
4575  */
4576
4577 void R_AnimCache_Free(void)
4578 {
4579 }
4580
4581 void R_AnimCache_ClearCache(void)
4582 {
4583         int i;
4584         entity_render_t *ent;
4585
4586         for (i = 0;i < r_refdef.scene.numentities;i++)
4587         {
4588                 ent = r_refdef.scene.entities[i];
4589                 ent->animcache_vertex3f = NULL;
4590                 ent->animcache_normal3f = NULL;
4591                 ent->animcache_svector3f = NULL;
4592                 ent->animcache_tvector3f = NULL;
4593                 ent->animcache_vertexmesh = NULL;
4594                 ent->animcache_vertex3fbuffer = NULL;
4595                 ent->animcache_vertexmeshbuffer = NULL;
4596         }
4597 }
4598
4599 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4600 {
4601         int i;
4602
4603         // check if we need the meshbuffers
4604         if (!vid.useinterleavedarrays)
4605                 return;
4606
4607         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4608                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4609         // TODO: upload vertex3f buffer?
4610         if (ent->animcache_vertexmesh)
4611         {
4612                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4613                 for (i = 0;i < numvertices;i++)
4614                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4615                 if (ent->animcache_svector3f)
4616                         for (i = 0;i < numvertices;i++)
4617                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4618                 if (ent->animcache_tvector3f)
4619                         for (i = 0;i < numvertices;i++)
4620                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4621                 if (ent->animcache_normal3f)
4622                         for (i = 0;i < numvertices;i++)
4623                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4624                 // TODO: upload vertexmeshbuffer?
4625         }
4626 }
4627
4628 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4629 {
4630         dp_model_t *model = ent->model;
4631         int numvertices;
4632         // see if it's already cached this frame
4633         if (ent->animcache_vertex3f)
4634         {
4635                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4636                 if (wantnormals || wanttangents)
4637                 {
4638                         if (ent->animcache_normal3f)
4639                                 wantnormals = false;
4640                         if (ent->animcache_svector3f)
4641                                 wanttangents = false;
4642                         if (wantnormals || wanttangents)
4643                         {
4644                                 numvertices = model->surfmesh.num_vertices;
4645                                 if (wantnormals)
4646                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4647                                 if (wanttangents)
4648                                 {
4649                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4650                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4651                                 }
4652                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4653                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4654                         }
4655                 }
4656         }
4657         else
4658         {
4659                 // see if this ent is worth caching
4660                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4661                         return false;
4662                 // get some memory for this entity and generate mesh data
4663                 numvertices = model->surfmesh.num_vertices;
4664                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4665                 if (wantnormals)
4666                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4667                 if (wanttangents)
4668                 {
4669                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4670                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4671                 }
4672                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4673                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4674         }
4675         return true;
4676 }
4677
4678 void R_AnimCache_CacheVisibleEntities(void)
4679 {
4680         int i;
4681         qboolean wantnormals = true;
4682         qboolean wanttangents = !r_showsurfaces.integer;
4683
4684         switch(vid.renderpath)
4685         {
4686         case RENDERPATH_GL20:
4687         case RENDERPATH_D3D9:
4688         case RENDERPATH_D3D10:
4689         case RENDERPATH_D3D11:
4690         case RENDERPATH_GLES2:
4691                 break;
4692         case RENDERPATH_GL11:
4693         case RENDERPATH_GL13:
4694         case RENDERPATH_GLES1:
4695                 wanttangents = false;
4696                 break;
4697         case RENDERPATH_SOFT:
4698                 break;
4699         }
4700
4701         if (r_shownormals.integer)
4702                 wanttangents = wantnormals = true;
4703
4704         // TODO: thread this
4705         // NOTE: R_PrepareRTLights() also caches entities
4706
4707         for (i = 0;i < r_refdef.scene.numentities;i++)
4708                 if (r_refdef.viewcache.entityvisible[i])
4709                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4710 }
4711
4712 //==================================================================================
4713
4714 extern cvar_t r_overheadsprites_pushback;
4715
4716 static void R_View_UpdateEntityLighting (void)
4717 {
4718         int i;
4719         entity_render_t *ent;
4720         vec3_t tempdiffusenormal, avg;
4721         vec_t f, fa, fd, fdd;
4722         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4723
4724         for (i = 0;i < r_refdef.scene.numentities;i++)
4725         {
4726                 ent = r_refdef.scene.entities[i];
4727
4728                 // skip unseen models
4729                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4730                         continue;
4731
4732                 // skip bsp models
4733                 if (ent->model && ent->model->brush.num_leafs)
4734                 {
4735                         // TODO: use modellight for r_ambient settings on world?
4736                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4737                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4738                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4739                         continue;
4740                 }
4741
4742                 // fetch the lighting from the worldmodel data
4743                 VectorClear(ent->modellight_ambient);
4744                 VectorClear(ent->modellight_diffuse);
4745                 VectorClear(tempdiffusenormal);
4746                 if (ent->flags & RENDER_LIGHT)
4747                 {
4748                         vec3_t org;
4749                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4750
4751                         // complete lightning for lit sprites
4752                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4753                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4754                         {
4755                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4756                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4757                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4758                         }
4759                         else
4760                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4761
4762                         if(ent->flags & RENDER_EQUALIZE)
4763                         {
4764                                 // first fix up ambient lighting...
4765                                 if(r_equalize_entities_minambient.value > 0)
4766                                 {
4767                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4768                                         if(fd > 0)
4769                                         {
4770                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4771                                                 if(fa < r_equalize_entities_minambient.value * fd)
4772                                                 {
4773                                                         // solve:
4774                                                         //   fa'/fd' = minambient
4775                                                         //   fa'+0.25*fd' = fa+0.25*fd
4776                                                         //   ...
4777                                                         //   fa' = fd' * minambient
4778                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4779                                                         //   ...
4780                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4781                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4782                                                         //   ...
4783                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4784                                                         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
4785                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4786                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4787                                                 }
4788                                         }
4789                                 }
4790
4791                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4792                                 {
4793                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4794                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4795                                         f = fa + 0.25 * fd;
4796                                         if(f > 0)
4797                                         {
4798                                                 // adjust brightness and saturation to target
4799                                                 avg[0] = avg[1] = avg[2] = fa / f;
4800                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4801                                                 avg[0] = avg[1] = avg[2] = fd / f;
4802                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4803                                         }
4804                                 }
4805                         }
4806                 }
4807                 else // highly rare
4808                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4809
4810                 // move the light direction into modelspace coordinates for lighting code
4811                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4812                 if(VectorLength2(ent->modellight_lightdir) == 0)
4813                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4814                 VectorNormalize(ent->modellight_lightdir);
4815         }
4816 }
4817
4818 #define MAX_LINEOFSIGHTTRACES 64
4819
4820 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4821 {
4822         int i;
4823         vec3_t boxmins, boxmaxs;
4824         vec3_t start;
4825         vec3_t end;
4826         dp_model_t *model = r_refdef.scene.worldmodel;
4827
4828         if (!model || !model->brush.TraceLineOfSight)
4829                 return true;
4830
4831         // expand the box a little
4832         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4833         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4834         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4835         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4836         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4837         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4838
4839         // return true if eye is inside enlarged box
4840         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4841                 return true;
4842
4843         // try center
4844         VectorCopy(eye, start);
4845         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4846         if (model->brush.TraceLineOfSight(model, start, end))
4847                 return true;
4848
4849         // try various random positions
4850         for (i = 0;i < numsamples;i++)
4851         {
4852                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4853                 if (model->brush.TraceLineOfSight(model, start, end))
4854                         return true;
4855         }
4856
4857         return false;
4858 }
4859
4860
4861 static void R_View_UpdateEntityVisible (void)
4862 {
4863         int i;
4864         int renderimask;
4865         int samples;
4866         entity_render_t *ent;
4867
4868         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4869                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4870                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4871                 :                                                          RENDER_EXTERIORMODEL;
4872         if (!r_drawviewmodel.integer)
4873                 renderimask |= RENDER_VIEWMODEL;
4874         if (!r_drawexteriormodel.integer)
4875                 renderimask |= RENDER_EXTERIORMODEL;
4876         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4877         {
4878                 // worldmodel can check visibility
4879                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4880                 for (i = 0;i < r_refdef.scene.numentities;i++)
4881                 {
4882                         ent = r_refdef.scene.entities[i];
4883                         if (!(ent->flags & renderimask))
4884                         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)))
4885                         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))
4886                                 r_refdef.viewcache.entityvisible[i] = true;
4887                 }
4888         }
4889         else
4890         {
4891                 // no worldmodel or it can't check visibility
4892                 for (i = 0;i < r_refdef.scene.numentities;i++)
4893                 {
4894                         ent = r_refdef.scene.entities[i];
4895                         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));
4896                 }
4897         }
4898         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4899                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4900         {
4901                 for (i = 0;i < r_refdef.scene.numentities;i++)
4902                 {
4903                         if (!r_refdef.viewcache.entityvisible[i])
4904                                 continue;
4905                         ent = r_refdef.scene.entities[i];
4906                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4907                         {
4908                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4909                                 if (samples < 0)
4910                                         continue; // temp entities do pvs only
4911                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4912                                         ent->last_trace_visibility = realtime;
4913                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4914                                         r_refdef.viewcache.entityvisible[i] = 0;
4915                         }
4916                 }
4917         }
4918 }
4919
4920 /// only used if skyrendermasked, and normally returns false
4921 int R_DrawBrushModelsSky (void)
4922 {
4923         int i, sky;
4924         entity_render_t *ent;
4925
4926         sky = false;
4927         for (i = 0;i < r_refdef.scene.numentities;i++)
4928         {
4929                 if (!r_refdef.viewcache.entityvisible[i])
4930                         continue;
4931                 ent = r_refdef.scene.entities[i];
4932                 if (!ent->model || !ent->model->DrawSky)
4933                         continue;
4934                 ent->model->DrawSky(ent);
4935                 sky = true;
4936         }
4937         return sky;
4938 }
4939
4940 static void R_DrawNoModel(entity_render_t *ent);
4941 static void R_DrawModels(void)
4942 {
4943         int i;
4944         entity_render_t *ent;
4945
4946         for (i = 0;i < r_refdef.scene.numentities;i++)
4947         {
4948                 if (!r_refdef.viewcache.entityvisible[i])
4949                         continue;
4950                 ent = r_refdef.scene.entities[i];
4951                 r_refdef.stats.entities++;
4952                 /*
4953                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4954                 {
4955                         vec3_t f, l, u, o;
4956                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4957                         Con_Printf("R_DrawModels\n");
4958                         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]);
4959                         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);
4960                         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);
4961                 }
4962                 */
4963                 if (ent->model && ent->model->Draw != NULL)
4964                         ent->model->Draw(ent);
4965                 else
4966                         R_DrawNoModel(ent);
4967         }
4968 }
4969
4970 static void R_DrawModelsDepth(void)
4971 {
4972         int i;
4973         entity_render_t *ent;
4974
4975         for (i = 0;i < r_refdef.scene.numentities;i++)
4976         {
4977                 if (!r_refdef.viewcache.entityvisible[i])
4978                         continue;
4979                 ent = r_refdef.scene.entities[i];
4980                 if (ent->model && ent->model->DrawDepth != NULL)
4981                         ent->model->DrawDepth(ent);
4982         }
4983 }
4984
4985 static void R_DrawModelsDebug(void)
4986 {
4987         int i;
4988         entity_render_t *ent;
4989
4990         for (i = 0;i < r_refdef.scene.numentities;i++)
4991         {
4992                 if (!r_refdef.viewcache.entityvisible[i])
4993                         continue;
4994                 ent = r_refdef.scene.entities[i];
4995                 if (ent->model && ent->model->DrawDebug != NULL)
4996                         ent->model->DrawDebug(ent);
4997         }
4998 }
4999
5000 static void R_DrawModelsAddWaterPlanes(void)
5001 {
5002         int i;
5003         entity_render_t *ent;
5004
5005         for (i = 0;i < r_refdef.scene.numentities;i++)
5006         {
5007                 if (!r_refdef.viewcache.entityvisible[i])
5008                         continue;
5009                 ent = r_refdef.scene.entities[i];
5010                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5011                         ent->model->DrawAddWaterPlanes(ent);
5012         }
5013 }
5014
5015 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5016 {
5017         if (r_hdr_irisadaptation.integer)
5018         {
5019                 vec3_t ambient;
5020                 vec3_t diffuse;
5021                 vec3_t diffusenormal;
5022                 vec_t brightness;
5023                 vec_t goal;
5024                 vec_t current;
5025                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5026                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5027                 brightness = max(0.0000001f, brightness);
5028                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5029                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5030                 current = r_hdr_irisadaptation_value.value;
5031                 if (current < goal)
5032                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5033                 else if (current > goal)
5034                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5035                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5036                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5037         }
5038         else if (r_hdr_irisadaptation_value.value != 1.0f)
5039                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5040 }
5041
5042 static void R_View_SetFrustum(const int *scissor)
5043 {
5044         int i;
5045         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5046         vec3_t forward, left, up, origin, v;
5047
5048         if(scissor)
5049         {
5050                 // flipped x coordinates (because x points left here)
5051                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5052                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5053
5054                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5055                 switch(vid.renderpath)
5056                 {
5057                         case RENDERPATH_D3D9:
5058                         case RENDERPATH_D3D10:
5059                         case RENDERPATH_D3D11:
5060                                 // non-flipped y coordinates
5061                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5062                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5063                                 break;
5064                         case RENDERPATH_SOFT:
5065                         case RENDERPATH_GL11:
5066                         case RENDERPATH_GL13:
5067                         case RENDERPATH_GL20:
5068                         case RENDERPATH_GLES1:
5069                         case RENDERPATH_GLES2:
5070                                 // non-flipped y coordinates
5071                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5072                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5073                                 break;
5074                 }
5075         }
5076
5077         // we can't trust r_refdef.view.forward and friends in reflected scenes
5078         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5079
5080 #if 0
5081         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5082         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5083         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5084         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5085         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5086         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5087         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5088         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5089         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5090         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5091         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5092         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5093 #endif
5094
5095 #if 0
5096         zNear = r_refdef.nearclip;
5097         nudge = 1.0 - 1.0 / (1<<23);
5098         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5099         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5100         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5101         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5102         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5103         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5104         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5105         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5106 #endif
5107
5108
5109
5110 #if 0
5111         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5112         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5113         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5114         r_refdef.view.frustum[0].dist = m[15] - m[12];
5115
5116         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5117         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5118         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5119         r_refdef.view.frustum[1].dist = m[15] + m[12];
5120
5121         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5122         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5123         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5124         r_refdef.view.frustum[2].dist = m[15] - m[13];
5125
5126         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5127         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5128         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5129         r_refdef.view.frustum[3].dist = m[15] + m[13];
5130
5131         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5132         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5133         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5134         r_refdef.view.frustum[4].dist = m[15] - m[14];
5135
5136         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5137         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5138         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5139         r_refdef.view.frustum[5].dist = m[15] + m[14];
5140 #endif
5141
5142         if (r_refdef.view.useperspective)
5143         {
5144                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5145                 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]);
5146                 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]);
5147                 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]);
5148                 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]);
5149
5150                 // then the normals from the corners relative to origin
5151                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5152                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5153                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5154                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5155
5156                 // in a NORMAL view, forward cross left == up
5157                 // in a REFLECTED view, forward cross left == down
5158                 // so our cross products above need to be adjusted for a left handed coordinate system
5159                 CrossProduct(forward, left, v);
5160                 if(DotProduct(v, up) < 0)
5161                 {
5162                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5163                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5164                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5165                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5166                 }
5167
5168                 // Leaving those out was a mistake, those were in the old code, and they
5169                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5170                 // I couldn't reproduce it after adding those normalizations. --blub
5171                 VectorNormalize(r_refdef.view.frustum[0].normal);
5172                 VectorNormalize(r_refdef.view.frustum[1].normal);
5173                 VectorNormalize(r_refdef.view.frustum[2].normal);
5174                 VectorNormalize(r_refdef.view.frustum[3].normal);
5175
5176                 // make the corners absolute
5177                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5178                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5179                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5180                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5181
5182                 // one more normal
5183                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5184
5185                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5186                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5187                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5188                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5189                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5190         }
5191         else
5192         {
5193                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5194                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5195                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5196                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5197                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5198                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5199                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5200                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5201                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5202                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5203         }
5204         r_refdef.view.numfrustumplanes = 5;
5205
5206         if (r_refdef.view.useclipplane)
5207         {
5208                 r_refdef.view.numfrustumplanes = 6;
5209                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5210         }
5211
5212         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5213                 PlaneClassify(r_refdef.view.frustum + i);
5214
5215         // LordHavoc: note to all quake engine coders, Quake had a special case
5216         // for 90 degrees which assumed a square view (wrong), so I removed it,
5217         // Quake2 has it disabled as well.
5218
5219         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5220         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5221         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5222         //PlaneClassify(&frustum[0]);
5223
5224         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5225         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5226         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5227         //PlaneClassify(&frustum[1]);
5228
5229         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5230         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5231         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5232         //PlaneClassify(&frustum[2]);
5233
5234         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5235         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5236         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5237         //PlaneClassify(&frustum[3]);
5238
5239         // nearclip plane
5240         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5241         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5242         //PlaneClassify(&frustum[4]);
5243 }
5244
5245 void R_View_UpdateWithScissor(const int *myscissor)
5246 {
5247         R_Main_ResizeViewCache();
5248         R_View_SetFrustum(myscissor);
5249         R_View_WorldVisibility(r_refdef.view.useclipplane);
5250         R_View_UpdateEntityVisible();
5251         R_View_UpdateEntityLighting();
5252 }
5253
5254 void R_View_Update(void)
5255 {
5256         R_Main_ResizeViewCache();
5257         R_View_SetFrustum(NULL);
5258         R_View_WorldVisibility(r_refdef.view.useclipplane);
5259         R_View_UpdateEntityVisible();
5260         R_View_UpdateEntityLighting();
5261 }
5262
5263 float viewscalefpsadjusted = 1.0f;
5264
5265 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5266 {
5267         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5268         scale = bound(0.03125f, scale, 1.0f);
5269         *outwidth = (int)ceil(width * scale);
5270         *outheight = (int)ceil(height * scale);
5271 }
5272
5273 void R_Mesh_SetMainRenderTargets(void)
5274 {
5275         if (r_bloomstate.fbo_framebuffer)
5276                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5277         else
5278                 R_Mesh_ResetRenderTargets();
5279 }
5280
5281 void R_SetupView(qboolean allowwaterclippingplane)
5282 {
5283         const float *customclipplane = NULL;
5284         float plane[4];
5285         int scaledwidth, scaledheight;
5286         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5287         {
5288                 // LordHavoc: couldn't figure out how to make this approach the
5289                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5290                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5291                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5292                         dist = r_refdef.view.clipplane.dist;
5293                 plane[0] = r_refdef.view.clipplane.normal[0];
5294                 plane[1] = r_refdef.view.clipplane.normal[1];
5295                 plane[2] = r_refdef.view.clipplane.normal[2];
5296                 plane[3] = -dist;
5297                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5298         }
5299
5300         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5301         if (!r_refdef.view.useperspective)
5302                 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);
5303         else if (vid.stencil && r_useinfinitefarclip.integer)
5304                 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);
5305         else
5306                 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);
5307         R_Mesh_SetMainRenderTargets();
5308         R_SetViewport(&r_refdef.view.viewport);
5309         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5310         {
5311                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5312                 float screenplane[4];
5313                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5314                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5315                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5316                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5317                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5318         }
5319 }
5320
5321 void R_EntityMatrix(const matrix4x4_t *matrix)
5322 {
5323         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5324         {
5325                 gl_modelmatrixchanged = false;
5326                 gl_modelmatrix = *matrix;
5327                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5328                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5329                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5330                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5331                 CHECKGLERROR
5332                 switch(vid.renderpath)
5333                 {
5334                 case RENDERPATH_D3D9:
5335 #ifdef SUPPORTD3D
5336                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5337                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5338 #endif
5339                         break;
5340                 case RENDERPATH_D3D10:
5341                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5342                         break;
5343                 case RENDERPATH_D3D11:
5344                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5345                         break;
5346                 case RENDERPATH_GL11:
5347                 case RENDERPATH_GL13:
5348                 case RENDERPATH_GLES1:
5349                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5350                         break;
5351                 case RENDERPATH_SOFT:
5352                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5353                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5354                         break;
5355                 case RENDERPATH_GL20:
5356                 case RENDERPATH_GLES2:
5357                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5358                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5359                         break;
5360                 }
5361         }
5362 }
5363
5364 void R_ResetViewRendering2D(void)
5365 {
5366         r_viewport_t viewport;
5367         DrawQ_Finish();
5368
5369         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5370         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);
5371         R_Mesh_ResetRenderTargets();
5372         R_SetViewport(&viewport);
5373         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5374         GL_Color(1, 1, 1, 1);
5375         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5376         GL_BlendFunc(GL_ONE, GL_ZERO);
5377         GL_ScissorTest(false);
5378         GL_DepthMask(false);
5379         GL_DepthRange(0, 1);
5380         GL_DepthTest(false);
5381         GL_DepthFunc(GL_LEQUAL);
5382         R_EntityMatrix(&identitymatrix);
5383         R_Mesh_ResetTextureState();
5384         GL_PolygonOffset(0, 0);
5385         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5386         switch(vid.renderpath)
5387         {
5388         case RENDERPATH_GL11:
5389         case RENDERPATH_GL13:
5390         case RENDERPATH_GL20:
5391         case RENDERPATH_GLES1:
5392         case RENDERPATH_GLES2:
5393                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5394                 break;
5395         case RENDERPATH_D3D9:
5396         case RENDERPATH_D3D10:
5397         case RENDERPATH_D3D11:
5398         case RENDERPATH_SOFT:
5399                 break;
5400         }
5401         GL_CullFace(GL_NONE);
5402 }
5403
5404 void R_ResetViewRendering3D(void)
5405 {
5406         DrawQ_Finish();
5407
5408         R_SetupView(true);
5409         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5410         GL_Color(1, 1, 1, 1);
5411         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5412         GL_BlendFunc(GL_ONE, GL_ZERO);
5413         GL_ScissorTest(true);
5414         GL_DepthMask(true);
5415         GL_DepthRange(0, 1);
5416         GL_DepthTest(true);
5417         GL_DepthFunc(GL_LEQUAL);
5418         R_EntityMatrix(&identitymatrix);
5419         R_Mesh_ResetTextureState();
5420         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5421         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5422         switch(vid.renderpath)
5423         {
5424         case RENDERPATH_GL11:
5425         case RENDERPATH_GL13:
5426         case RENDERPATH_GL20:
5427         case RENDERPATH_GLES1:
5428         case RENDERPATH_GLES2:
5429                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5430                 break;
5431         case RENDERPATH_D3D9:
5432         case RENDERPATH_D3D10:
5433         case RENDERPATH_D3D11:
5434         case RENDERPATH_SOFT:
5435                 break;
5436         }
5437         GL_CullFace(r_refdef.view.cullface_back);
5438 }
5439
5440 /*
5441 ================
5442 R_RenderView_UpdateViewVectors
5443 ================
5444 */
5445 static void R_RenderView_UpdateViewVectors(void)
5446 {
5447         // break apart the view matrix into vectors for various purposes
5448         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5449         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5450         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5451         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5452         // make an inverted copy of the view matrix for tracking sprites
5453         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5454 }
5455
5456 void R_RenderScene(void);
5457 void R_RenderWaterPlanes(void);
5458
5459 static void R_Water_StartFrame(void)
5460 {
5461         int i;
5462         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5463         r_waterstate_waterplane_t *p;
5464
5465         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5466                 return;
5467
5468         switch(vid.renderpath)
5469         {
5470         case RENDERPATH_GL20:
5471         case RENDERPATH_D3D9:
5472         case RENDERPATH_D3D10:
5473         case RENDERPATH_D3D11:
5474         case RENDERPATH_SOFT:
5475         case RENDERPATH_GLES2:
5476                 break;
5477         case RENDERPATH_GL11:
5478         case RENDERPATH_GL13:
5479         case RENDERPATH_GLES1:
5480                 return;
5481         }
5482
5483         // set waterwidth and waterheight to the water resolution that will be
5484         // used (often less than the screen resolution for faster rendering)
5485         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5486
5487         // calculate desired texture sizes
5488         // can't use water if the card does not support the texture size
5489         if (!r_water.integer || r_showsurfaces.integer)
5490                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5491         else if (vid.support.arb_texture_non_power_of_two)
5492         {
5493                 texturewidth = waterwidth;
5494                 textureheight = waterheight;
5495                 camerawidth = waterwidth;
5496                 cameraheight = waterheight;
5497         }
5498         else
5499         {
5500                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5501                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5502                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5503                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5504         }
5505
5506         // allocate textures as needed
5507         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5508         {
5509                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5510                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5511                 {
5512                         if (p->texture_refraction)
5513                                 R_FreeTexture(p->texture_refraction);
5514                         p->texture_refraction = NULL;
5515                         if (p->texture_reflection)
5516                                 R_FreeTexture(p->texture_reflection);
5517                         p->texture_reflection = NULL;
5518                         if (p->texture_camera)
5519                                 R_FreeTexture(p->texture_camera);
5520                         p->texture_camera = NULL;
5521                 }
5522                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5523                 r_waterstate.texturewidth = texturewidth;
5524                 r_waterstate.textureheight = textureheight;
5525                 r_waterstate.camerawidth = camerawidth;
5526                 r_waterstate.cameraheight = cameraheight;
5527         }
5528
5529         if (r_waterstate.texturewidth)
5530         {
5531                 int scaledwidth, scaledheight;
5532
5533                 r_waterstate.enabled = true;
5534
5535                 // when doing a reduced render (HDR) we want to use a smaller area
5536                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5537                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5538                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5539
5540                 // set up variables that will be used in shader setup
5541                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5542                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5543                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5544                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5545         }
5546
5547         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5548         r_waterstate.numwaterplanes = 0;
5549 }
5550
5551 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5552 {
5553         int triangleindex, planeindex;
5554         const int *e;
5555         vec3_t vert[3];
5556         vec3_t normal;
5557         vec3_t center;
5558         mplane_t plane;
5559         r_waterstate_waterplane_t *p;
5560         texture_t *t = R_GetCurrentTexture(surface->texture);
5561
5562         // just use the first triangle with a valid normal for any decisions
5563         VectorClear(normal);
5564         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5565         {
5566                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5567                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5568                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5569                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5570                 if (VectorLength2(normal) >= 0.001)
5571                         break;
5572         }
5573
5574         VectorCopy(normal, plane.normal);
5575         VectorNormalize(plane.normal);
5576         plane.dist = DotProduct(vert[0], plane.normal);
5577         PlaneClassify(&plane);
5578         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5579         {
5580                 // skip backfaces (except if nocullface is set)
5581                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5582                         return;
5583                 VectorNegate(plane.normal, plane.normal);
5584                 plane.dist *= -1;
5585                 PlaneClassify(&plane);
5586         }
5587
5588
5589         // find a matching plane if there is one
5590         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5591                 if(p->camera_entity == t->camera_entity)
5592                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5593                                 break;
5594         if (planeindex >= r_waterstate.maxwaterplanes)
5595                 return; // nothing we can do, out of planes
5596
5597         // if this triangle does not fit any known plane rendered this frame, add one
5598         if (planeindex >= r_waterstate.numwaterplanes)
5599         {
5600                 // store the new plane
5601                 r_waterstate.numwaterplanes++;
5602                 p->plane = plane;
5603                 // clear materialflags and pvs
5604                 p->materialflags = 0;
5605                 p->pvsvalid = false;
5606                 p->camera_entity = t->camera_entity;
5607                 VectorCopy(surface->mins, p->mins);
5608                 VectorCopy(surface->maxs, p->maxs);
5609         }
5610         else
5611         {
5612                 // merge mins/maxs
5613                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5614                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5615                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5616                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5617                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5618                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5619         }
5620         // merge this surface's materialflags into the waterplane
5621         p->materialflags |= t->currentmaterialflags;
5622         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5623         {
5624                 // merge this surface's PVS into the waterplane
5625                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5626                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5627                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5628                 {
5629                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5630                         p->pvsvalid = true;
5631                 }
5632         }
5633 }
5634
5635 extern cvar_t r_drawparticles;
5636 extern cvar_t r_drawdecals;
5637
5638 static void R_Water_ProcessPlanes(void)
5639 {
5640         int myscissor[4];
5641         r_refdef_view_t originalview;
5642         r_refdef_view_t myview;
5643         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;
5644         r_waterstate_waterplane_t *p;
5645         vec3_t visorigin;
5646
5647         originalview = r_refdef.view;
5648
5649         // lowquality hack, temporarily shut down some cvars and restore afterwards
5650         qualityreduction = r_water_lowquality.integer;
5651         if (qualityreduction > 0)
5652         {
5653                 if (qualityreduction >= 1)
5654                 {
5655                         old_r_shadows = r_shadows.integer;
5656                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5657                         old_r_dlight = r_shadow_realtime_dlight.integer;
5658                         Cvar_SetValueQuick(&r_shadows, 0);
5659                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5660                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5661                 }
5662                 if (qualityreduction >= 2)
5663                 {
5664                         old_r_dynamic = r_dynamic.integer;
5665                         old_r_particles = r_drawparticles.integer;
5666                         old_r_decals = r_drawdecals.integer;
5667                         Cvar_SetValueQuick(&r_dynamic, 0);
5668                         Cvar_SetValueQuick(&r_drawparticles, 0);
5669                         Cvar_SetValueQuick(&r_drawdecals, 0);
5670                 }
5671         }
5672
5673         // make sure enough textures are allocated
5674         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5675         {
5676                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5677                 {
5678                         if (!p->texture_refraction)
5679                                 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);
5680                         if (!p->texture_refraction)
5681                                 goto error;
5682                 }
5683                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5684                 {
5685                         if (!p->texture_camera)
5686                                 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);
5687                         if (!p->texture_camera)
5688                                 goto error;
5689                 }
5690
5691                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5692                 {
5693                         if (!p->texture_reflection)
5694                                 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);
5695                         if (!p->texture_reflection)
5696                                 goto error;
5697                 }
5698         }
5699
5700         // render views
5701         r_refdef.view = originalview;
5702         r_refdef.view.showdebug = false;
5703         r_refdef.view.width = r_waterstate.waterwidth;
5704         r_refdef.view.height = r_waterstate.waterheight;
5705         r_refdef.view.useclipplane = true;
5706         myview = r_refdef.view;
5707         r_waterstate.renderingscene = true;
5708         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5709         {
5710                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5711                 {
5712                         r_refdef.view = myview;
5713                         if(r_water_scissormode.integer)
5714                         {
5715                                 R_SetupView(true);
5716                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5717                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5718                         }
5719
5720                         // render reflected scene and copy into texture
5721                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5722                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5723                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5724                         r_refdef.view.clipplane = p->plane;
5725                         // reverse the cullface settings for this render
5726                         r_refdef.view.cullface_front = GL_FRONT;
5727                         r_refdef.view.cullface_back = GL_BACK;
5728                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5729                         {
5730                                 r_refdef.view.usecustompvs = true;
5731                                 if (p->pvsvalid)
5732                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5733                                 else
5734                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5735                         }
5736
5737                         R_ResetViewRendering3D();
5738                         R_ClearScreen(r_refdef.fogenabled);
5739                         if(r_water_scissormode.integer & 2)
5740                                 R_View_UpdateWithScissor(myscissor);
5741                         else
5742                                 R_View_Update();
5743                         if(r_water_scissormode.integer & 1)
5744                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5745                         R_RenderScene();
5746
5747                         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);
5748                 }
5749
5750                 // render the normal view scene and copy into texture
5751                 // (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)
5752                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5753                 {
5754                         r_refdef.view = myview;
5755                         if(r_water_scissormode.integer)
5756                         {
5757                                 R_SetupView(true);
5758                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5759                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5760                         }
5761
5762                         r_waterstate.renderingrefraction = true;
5763
5764                         r_refdef.view.clipplane = p->plane;
5765                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5766                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5767
5768                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5769                         {
5770                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5771                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5772                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5773                                 R_RenderView_UpdateViewVectors();
5774                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5775                                 {
5776                                         r_refdef.view.usecustompvs = true;
5777                                         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);
5778                                 }
5779                         }
5780
5781                         PlaneClassify(&r_refdef.view.clipplane);
5782
5783                         R_ResetViewRendering3D();
5784                         R_ClearScreen(r_refdef.fogenabled);
5785                         if(r_water_scissormode.integer & 2)
5786                                 R_View_UpdateWithScissor(myscissor);
5787                         else
5788                                 R_View_Update();
5789                         if(r_water_scissormode.integer & 1)
5790                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5791                         R_RenderScene();
5792
5793                         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);
5794                         r_waterstate.renderingrefraction = false;
5795                 }
5796                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5797                 {
5798                         r_refdef.view = myview;
5799
5800                         r_refdef.view.clipplane = p->plane;
5801                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5802                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5803
5804                         r_refdef.view.width = r_waterstate.camerawidth;
5805                         r_refdef.view.height = r_waterstate.cameraheight;
5806                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5807                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5808
5809                         if(p->camera_entity)
5810                         {
5811                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5812                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5813                         }
5814
5815                         // note: all of the view is used for displaying... so
5816                         // there is no use in scissoring
5817
5818                         // reverse the cullface settings for this render
5819                         r_refdef.view.cullface_front = GL_FRONT;
5820                         r_refdef.view.cullface_back = GL_BACK;
5821                         // also reverse the view matrix
5822                         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
5823                         R_RenderView_UpdateViewVectors();
5824                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5825                         {
5826                                 r_refdef.view.usecustompvs = true;
5827                                 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);
5828                         }
5829                         
5830                         // camera needs no clipplane
5831                         r_refdef.view.useclipplane = false;
5832
5833                         PlaneClassify(&r_refdef.view.clipplane);
5834
5835                         R_ResetViewRendering3D();
5836                         R_ClearScreen(r_refdef.fogenabled);
5837                         R_View_Update();
5838                         R_RenderScene();
5839
5840                         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);
5841                         r_waterstate.renderingrefraction = false;
5842                 }
5843
5844         }
5845         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5846         r_waterstate.renderingscene = false;
5847         r_refdef.view = originalview;
5848         R_ResetViewRendering3D();
5849         R_ClearScreen(r_refdef.fogenabled);
5850         R_View_Update();
5851         goto finish;
5852 error:
5853         r_refdef.view = originalview;
5854         r_waterstate.renderingscene = false;
5855         Cvar_SetValueQuick(&r_water, 0);
5856         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5857 finish:
5858         // lowquality hack, restore cvars
5859         if (qualityreduction > 0)
5860         {
5861                 if (qualityreduction >= 1)
5862                 {
5863                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5864                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5865                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5866                 }
5867                 if (qualityreduction >= 2)
5868                 {
5869                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5870                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5871                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5872                 }
5873         }
5874 }
5875
5876 void R_Bloom_StartFrame(void)
5877 {
5878         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5879         int viewwidth, viewheight;
5880         textype_t textype;
5881
5882         if (r_viewscale_fpsscaling.integer)
5883         {
5884                 double actualframetime;
5885                 double targetframetime;
5886                 double adjust;
5887                 actualframetime = r_refdef.lastdrawscreentime;
5888                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5889                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5890                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5891                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5892                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5893                 viewscalefpsadjusted += adjust;
5894                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5895         }
5896         else
5897                 viewscalefpsadjusted = 1.0f;
5898
5899         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5900
5901         switch(vid.renderpath)
5902         {
5903         case RENDERPATH_GL20:
5904         case RENDERPATH_D3D9:
5905         case RENDERPATH_D3D10:
5906         case RENDERPATH_D3D11:
5907         case RENDERPATH_SOFT:
5908         case RENDERPATH_GLES2:
5909                 break;
5910         case RENDERPATH_GL11:
5911         case RENDERPATH_GL13:
5912         case RENDERPATH_GLES1:
5913                 return;
5914         }
5915
5916         // set bloomwidth and bloomheight to the bloom resolution that will be
5917         // used (often less than the screen resolution for faster rendering)
5918         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5919         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5920         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5921         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5922         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5923
5924         // calculate desired texture sizes
5925         if (vid.support.arb_texture_non_power_of_two)
5926         {
5927                 screentexturewidth = vid.width;
5928                 screentextureheight = vid.height;
5929                 bloomtexturewidth = r_bloomstate.bloomwidth;
5930                 bloomtextureheight = r_bloomstate.bloomheight;
5931         }
5932         else
5933         {
5934                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5935                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5936                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5937                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5938         }
5939
5940         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))
5941         {
5942                 Cvar_SetValueQuick(&r_hdr, 0);
5943                 Cvar_SetValueQuick(&r_bloom, 0);
5944                 Cvar_SetValueQuick(&r_motionblur, 0);
5945                 Cvar_SetValueQuick(&r_damageblur, 0);
5946         }
5947
5948         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)
5949                 screentexturewidth = screentextureheight = 0;
5950         if (!r_hdr.integer && !r_bloom.integer)
5951                 bloomtexturewidth = bloomtextureheight = 0;
5952
5953         textype = TEXTYPE_COLORBUFFER;
5954         switch (vid.renderpath)
5955         {
5956         case RENDERPATH_GL20:
5957         case RENDERPATH_GLES2:
5958                 if (vid.support.ext_framebuffer_object)
5959                 {
5960                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5961                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5962                 }
5963                 break;
5964         case RENDERPATH_GL11:
5965         case RENDERPATH_GL13:
5966         case RENDERPATH_GLES1:
5967         case RENDERPATH_D3D9:
5968         case RENDERPATH_D3D10:
5969         case RENDERPATH_D3D11:
5970         case RENDERPATH_SOFT:
5971                 break;
5972         }
5973
5974         // allocate textures as needed
5975         if (r_bloomstate.screentexturewidth != screentexturewidth
5976          || r_bloomstate.screentextureheight != screentextureheight
5977          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5978          || r_bloomstate.bloomtextureheight != bloomtextureheight
5979          || r_bloomstate.texturetype != textype
5980          || r_bloomstate.viewfbo != r_viewfbo.integer)
5981         {
5982                 if (r_bloomstate.texture_bloom)
5983                         R_FreeTexture(r_bloomstate.texture_bloom);
5984                 r_bloomstate.texture_bloom = NULL;
5985                 if (r_bloomstate.texture_screen)
5986                         R_FreeTexture(r_bloomstate.texture_screen);
5987                 r_bloomstate.texture_screen = NULL;
5988                 if (r_bloomstate.fbo_framebuffer)
5989                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5990                 r_bloomstate.fbo_framebuffer = 0;
5991                 if (r_bloomstate.texture_framebuffercolor)
5992                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5993                 r_bloomstate.texture_framebuffercolor = NULL;
5994                 if (r_bloomstate.texture_framebufferdepth)
5995                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5996                 r_bloomstate.texture_framebufferdepth = NULL;
5997                 r_bloomstate.screentexturewidth = screentexturewidth;
5998                 r_bloomstate.screentextureheight = screentextureheight;
5999                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6000                         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);
6001                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6002                 {
6003                         // FIXME: choose depth bits based on a cvar
6004                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6005                         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);
6006                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6007                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6008                         // render depth into one texture and normalmap into the other
6009                         if (qglDrawBuffer)
6010                         {
6011                                 int status;
6012                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6013                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6014                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
6015                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
6016                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6017                         }
6018                 }
6019                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6020                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6021                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6022                         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);
6023                 r_bloomstate.viewfbo = r_viewfbo.integer;
6024                 r_bloomstate.texturetype = textype;
6025         }
6026
6027         // when doing a reduced render (HDR) we want to use a smaller area
6028         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6029         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6030         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6031         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6032         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6033
6034         // set up a texcoord array for the full resolution screen image
6035         // (we have to keep this around to copy back during final render)
6036         r_bloomstate.screentexcoord2f[0] = 0;
6037         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6038         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6039         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6040         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6041         r_bloomstate.screentexcoord2f[5] = 0;
6042         r_bloomstate.screentexcoord2f[6] = 0;
6043         r_bloomstate.screentexcoord2f[7] = 0;
6044
6045         // set up a texcoord array for the reduced resolution bloom image
6046         // (which will be additive blended over the screen image)
6047         r_bloomstate.bloomtexcoord2f[0] = 0;
6048         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6049         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6050         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6051         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6052         r_bloomstate.bloomtexcoord2f[5] = 0;
6053         r_bloomstate.bloomtexcoord2f[6] = 0;
6054         r_bloomstate.bloomtexcoord2f[7] = 0;
6055
6056         switch(vid.renderpath)
6057         {
6058         case RENDERPATH_GL11:
6059         case RENDERPATH_GL13:
6060         case RENDERPATH_GL20:
6061         case RENDERPATH_SOFT:
6062         case RENDERPATH_GLES1:
6063         case RENDERPATH_GLES2:
6064                 break;
6065         case RENDERPATH_D3D9:
6066         case RENDERPATH_D3D10:
6067         case RENDERPATH_D3D11:
6068                 {
6069                         int i;
6070                         for (i = 0;i < 4;i++)
6071                         {
6072                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6073                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6074                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6075                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6076                         }
6077                 }
6078                 break;
6079         }
6080
6081         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6082         {
6083                 r_bloomstate.enabled = true;
6084                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6085         }
6086
6087         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);
6088
6089         if (r_bloomstate.fbo_framebuffer)
6090                 r_refdef.view.clear = true;
6091 }
6092
6093 void R_Bloom_CopyBloomTexture(float colorscale)
6094 {
6095         r_refdef.stats.bloom++;
6096
6097         // scale down screen texture to the bloom texture size
6098         CHECKGLERROR
6099         R_Mesh_SetMainRenderTargets();
6100         R_SetViewport(&r_bloomstate.viewport);
6101         GL_BlendFunc(GL_ONE, GL_ZERO);
6102         GL_Color(colorscale, colorscale, colorscale, 1);
6103         // 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...
6104         switch(vid.renderpath)
6105         {
6106         case RENDERPATH_GL11:
6107         case RENDERPATH_GL13:
6108         case RENDERPATH_GL20:
6109         case RENDERPATH_GLES1:
6110         case RENDERPATH_GLES2:
6111         case RENDERPATH_SOFT:
6112                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6113                 break;
6114         case RENDERPATH_D3D9:
6115         case RENDERPATH_D3D10:
6116         case RENDERPATH_D3D11:
6117                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6118                 break;
6119         }
6120         // TODO: do boxfilter scale-down in shader?
6121         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6122         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6123         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6124
6125         // we now have a bloom image in the framebuffer
6126         // copy it into the bloom image texture for later processing
6127         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);
6128         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6129 }
6130
6131 void R_Bloom_CopyHDRTexture(void)
6132 {
6133         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);
6134         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6135 }
6136
6137 void R_Bloom_MakeTexture(void)
6138 {
6139         int x, range, dir;
6140         float xoffset, yoffset, r, brighten;
6141
6142         r_refdef.stats.bloom++;
6143
6144         R_ResetViewRendering2D();
6145
6146         // we have a bloom image in the framebuffer
6147         CHECKGLERROR
6148         R_SetViewport(&r_bloomstate.viewport);
6149
6150         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6151         {
6152                 x *= 2;
6153                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6154                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6155                 GL_Color(r,r,r,1);
6156                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6157                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6158                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6159                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6160
6161                 // copy the vertically blurred bloom view to a texture
6162                 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);
6163                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6164         }
6165
6166         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6167         brighten = r_bloom_brighten.value;
6168         if (r_bloomstate.hdr)
6169                 brighten *= r_hdr_range.value;
6170         brighten = sqrt(brighten);
6171         if(range >= 1)
6172                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6173         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6174
6175         for (dir = 0;dir < 2;dir++)
6176         {
6177                 // blend on at multiple vertical offsets to achieve a vertical blur
6178                 // TODO: do offset blends using GLSL
6179                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6180                 GL_BlendFunc(GL_ONE, GL_ZERO);
6181                 for (x = -range;x <= range;x++)
6182                 {
6183                         if (!dir){xoffset = 0;yoffset = x;}
6184                         else {xoffset = x;yoffset = 0;}
6185                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6186                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6187                         // compute a texcoord array with the specified x and y offset
6188                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6189                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6190                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6191                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6192                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6193                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6194                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6195                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6196                         // this r value looks like a 'dot' particle, fading sharply to
6197                         // black at the edges
6198                         // (probably not realistic but looks good enough)
6199                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6200                         //r = brighten/(range*2+1);
6201                         r = brighten / (range * 2 + 1);
6202                         if(range >= 1)
6203                                 r *= (1 - x*x/(float)(range*range));
6204                         GL_Color(r, r, r, 1);
6205                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6206                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6207                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6208                         GL_BlendFunc(GL_ONE, GL_ONE);
6209                 }
6210
6211                 // copy the vertically blurred bloom view to a texture
6212                 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);
6213                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6214         }
6215 }
6216
6217 void R_HDR_RenderBloomTexture(void)
6218 {
6219         int oldwidth, oldheight;
6220         float oldcolorscale;
6221         qboolean oldwaterstate;
6222
6223         oldwaterstate = r_waterstate.enabled;
6224         oldcolorscale = r_refdef.view.colorscale;
6225         oldwidth = r_refdef.view.width;
6226         oldheight = r_refdef.view.height;
6227         r_refdef.view.width = r_bloomstate.bloomwidth;
6228         r_refdef.view.height = r_bloomstate.bloomheight;
6229
6230         if(r_hdr.integer < 2)
6231                 r_waterstate.enabled = false;
6232
6233         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6234         // TODO: add exposure compensation features
6235         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6236
6237         r_refdef.view.showdebug = false;
6238         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6239
6240         R_ResetViewRendering3D();
6241
6242         R_ClearScreen(r_refdef.fogenabled);
6243         if (r_timereport_active)
6244                 R_TimeReport("HDRclear");
6245
6246         R_View_Update();
6247         if (r_timereport_active)
6248                 R_TimeReport("visibility");
6249
6250         // only do secondary renders with HDR if r_hdr is 2 or higher
6251         r_waterstate.numwaterplanes = 0;
6252         if (r_waterstate.enabled)
6253                 R_RenderWaterPlanes();
6254
6255         r_refdef.view.showdebug = true;
6256         R_RenderScene();
6257         r_waterstate.numwaterplanes = 0;
6258
6259         R_ResetViewRendering2D();
6260
6261         R_Bloom_CopyHDRTexture();
6262         R_Bloom_MakeTexture();
6263
6264         // restore the view settings
6265         r_waterstate.enabled = oldwaterstate;
6266         r_refdef.view.width = oldwidth;
6267         r_refdef.view.height = oldheight;
6268         r_refdef.view.colorscale = oldcolorscale;
6269
6270         R_ResetViewRendering3D();
6271
6272         R_ClearScreen(r_refdef.fogenabled);
6273         if (r_timereport_active)
6274                 R_TimeReport("viewclear");
6275 }
6276
6277 static void R_BlendView(void)
6278 {
6279         unsigned int permutation;
6280         float uservecs[4][4];
6281
6282         switch (vid.renderpath)
6283         {
6284         case RENDERPATH_GL20:
6285         case RENDERPATH_D3D9:
6286         case RENDERPATH_D3D10:
6287         case RENDERPATH_D3D11:
6288         case RENDERPATH_SOFT:
6289         case RENDERPATH_GLES2:
6290                 permutation =
6291                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6292                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6293                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6294                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6295                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6296
6297                 if (r_bloomstate.texture_screen)
6298                 {
6299                         // make sure the buffer is available
6300                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6301
6302                         R_ResetViewRendering2D();
6303                         R_Mesh_SetMainRenderTargets();
6304
6305                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6306                         {
6307                                 // declare variables
6308                                 float blur_factor, blur_mouseaccel, blur_velocity;
6309                                 static float blur_average; 
6310                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6311
6312                                 // set a goal for the factoring
6313                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6314                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6315                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6316                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6317                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6318                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6319
6320                                 // from the goal, pick an averaged value between goal and last value
6321                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6322                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6323                                 
6324                                 // enforce minimum amount of blur 
6325                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6326                                 
6327                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6328
6329                                 // calculate values into a standard alpha
6330                                 cl.motionbluralpha = 1 - exp(-
6331                                                 (
6332                                                  (r_motionblur.value * blur_factor / 80)
6333                                                  +
6334                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6335                                                 )
6336                                                 /
6337                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6338                                           );
6339                                 
6340                                 // randomization for the blur value to combat persistent ghosting
6341                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6342                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6343                                 
6344                                 // apply the blur
6345                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6346                                 {
6347                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6348                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6349                                         switch(vid.renderpath)
6350                                         {
6351                                         case RENDERPATH_GL11:
6352                                         case RENDERPATH_GL13:
6353                                         case RENDERPATH_GL20:
6354                                         case RENDERPATH_GLES1:
6355                                         case RENDERPATH_GLES2:
6356                                         case RENDERPATH_SOFT:
6357                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6358                                                 break;
6359                                         case RENDERPATH_D3D9:
6360                                         case RENDERPATH_D3D10:
6361                                         case RENDERPATH_D3D11:
6362                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6363                                                 break;
6364                                         }
6365                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6366                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6367                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6368                                 }
6369                                 
6370                                 // updates old view angles for next pass 
6371                                 VectorCopy(cl.viewangles, blur_oldangles);
6372                         }
6373
6374                         // copy view into the screen texture
6375                         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);
6376                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6377                 }
6378                 else if (!r_bloomstate.texture_bloom)
6379                 {
6380                         // we may still have to do view tint...
6381                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6382                         {
6383                                 // apply a color tint to the whole view
6384                                 R_ResetViewRendering2D();
6385                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6386                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6387                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6388                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6389                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6390                         }
6391                         break; // no screen processing, no bloom, skip it
6392                 }
6393
6394                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6395                 {
6396                         // render simple bloom effect
6397                         // copy the screen and shrink it and darken it for the bloom process
6398                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6399                         // make the bloom texture
6400                         R_Bloom_MakeTexture();
6401                 }
6402
6403 #if _MSC_VER >= 1400
6404 #define sscanf sscanf_s
6405 #endif
6406                 memset(uservecs, 0, sizeof(uservecs));
6407                 if (r_glsl_postprocess_uservec1_enable.integer)
6408                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6409                 if (r_glsl_postprocess_uservec2_enable.integer)
6410                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6411                 if (r_glsl_postprocess_uservec3_enable.integer)
6412                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6413                 if (r_glsl_postprocess_uservec4_enable.integer)
6414                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6415
6416                 R_ResetViewRendering2D();
6417                 GL_Color(1, 1, 1, 1);
6418                 GL_BlendFunc(GL_ONE, GL_ZERO);
6419
6420                 switch(vid.renderpath)
6421                 {
6422                 case RENDERPATH_GL20:
6423                 case RENDERPATH_GLES2:
6424                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6425                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6426                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6427                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6428                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6429                         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]);
6430                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6431                         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]);
6432                         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]);
6433                         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]);
6434                         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]);
6435                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6436                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6437                         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);
6438                         break;
6439                 case RENDERPATH_D3D9:
6440 #ifdef SUPPORTD3D
6441                         // 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...
6442                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6443                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6444                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6445                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6446                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6447                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6448                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6449                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6450                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6451                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6452                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6453                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6454                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6455                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6456 #endif
6457                         break;
6458                 case RENDERPATH_D3D10:
6459                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6460                         break;
6461                 case RENDERPATH_D3D11:
6462                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6463                         break;
6464                 case RENDERPATH_SOFT:
6465                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6466                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6467                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6468                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6469                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6470                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6471                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6472                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6473                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6474                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6475                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6476                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6477                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6478                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6479                         break;
6480                 default:
6481                         break;
6482                 }
6483                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6484                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6485                 break;
6486         case RENDERPATH_GL11:
6487         case RENDERPATH_GL13:
6488         case RENDERPATH_GLES1:
6489                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6490                 {
6491                         // apply a color tint to the whole view
6492                         R_ResetViewRendering2D();
6493                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6494                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6495                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6496                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6497                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6498                 }
6499                 break;
6500         }
6501 }
6502
6503 matrix4x4_t r_waterscrollmatrix;
6504
6505 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6506 {
6507         if (r_refdef.fog_density)
6508         {
6509                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6510                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6511                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6512
6513                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6514                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6515                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6516                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6517
6518                 {
6519                         vec3_t fogvec;
6520                         VectorCopy(r_refdef.fogcolor, fogvec);
6521                         //   color.rgb *= ContrastBoost * SceneBrightness;
6522                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6523                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6524                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6525                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6526                 }
6527         }
6528 }
6529
6530 void R_UpdateVariables(void)
6531 {
6532         R_Textures_Frame();
6533
6534         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6535
6536         r_refdef.farclip = r_farclip_base.value;
6537         if (r_refdef.scene.worldmodel)
6538                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6539         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6540
6541         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6542                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6543         r_refdef.polygonfactor = 0;
6544         r_refdef.polygonoffset = 0;
6545         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6546         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6547
6548         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6549         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6550         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6551         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6552         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6553         if (FAKELIGHT_ENABLED)
6554         {
6555                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6556         }
6557         if (r_showsurfaces.integer)
6558         {
6559                 r_refdef.scene.rtworld = false;
6560                 r_refdef.scene.rtworldshadows = false;
6561                 r_refdef.scene.rtdlight = false;
6562                 r_refdef.scene.rtdlightshadows = false;
6563                 r_refdef.lightmapintensity = 0;
6564         }
6565
6566         if (gamemode == GAME_NEHAHRA)
6567         {
6568                 if (gl_fogenable.integer)
6569                 {
6570                         r_refdef.oldgl_fogenable = true;
6571                         r_refdef.fog_density = gl_fogdensity.value;
6572                         r_refdef.fog_red = gl_fogred.value;
6573                         r_refdef.fog_green = gl_foggreen.value;
6574                         r_refdef.fog_blue = gl_fogblue.value;
6575                         r_refdef.fog_alpha = 1;
6576                         r_refdef.fog_start = 0;
6577                         r_refdef.fog_end = gl_skyclip.value;
6578                         r_refdef.fog_height = 1<<30;
6579                         r_refdef.fog_fadedepth = 128;
6580                 }
6581                 else if (r_refdef.oldgl_fogenable)
6582                 {
6583                         r_refdef.oldgl_fogenable = false;
6584                         r_refdef.fog_density = 0;
6585                         r_refdef.fog_red = 0;
6586                         r_refdef.fog_green = 0;
6587                         r_refdef.fog_blue = 0;
6588                         r_refdef.fog_alpha = 0;
6589                         r_refdef.fog_start = 0;
6590                         r_refdef.fog_end = 0;
6591                         r_refdef.fog_height = 1<<30;
6592                         r_refdef.fog_fadedepth = 128;
6593                 }
6594         }
6595
6596         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6597         r_refdef.fog_start = max(0, r_refdef.fog_start);
6598         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6599
6600         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6601
6602         if (r_refdef.fog_density && r_drawfog.integer)
6603         {
6604                 r_refdef.fogenabled = true;
6605                 // this is the point where the fog reaches 0.9986 alpha, which we
6606                 // consider a good enough cutoff point for the texture
6607                 // (0.9986 * 256 == 255.6)
6608                 if (r_fog_exp2.integer)
6609                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6610                 else
6611                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6612                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6613                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6614                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6615                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6616                         R_BuildFogHeightTexture();
6617                 // fog color was already set
6618                 // update the fog texture
6619                 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)
6620                         R_BuildFogTexture();
6621                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6622                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6623         }
6624         else
6625                 r_refdef.fogenabled = false;
6626
6627         switch(vid.renderpath)
6628         {
6629         case RENDERPATH_GL20:
6630         case RENDERPATH_D3D9:
6631         case RENDERPATH_D3D10:
6632         case RENDERPATH_D3D11:
6633         case RENDERPATH_SOFT:
6634         case RENDERPATH_GLES2:
6635                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6636                 {
6637                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6638                         {
6639                                 // build GLSL gamma texture
6640 #define RAMPWIDTH 256
6641                                 unsigned short ramp[RAMPWIDTH * 3];
6642                                 unsigned char rampbgr[RAMPWIDTH][4];
6643                                 int i;
6644
6645                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6646
6647                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6648                                 for(i = 0; i < RAMPWIDTH; ++i)
6649                                 {
6650                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6651                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6652                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6653                                         rampbgr[i][3] = 0;
6654                                 }
6655                                 if (r_texture_gammaramps)
6656                                 {
6657                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6658                                 }
6659                                 else
6660                                 {
6661                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6662                                 }
6663                         }
6664                 }
6665                 else
6666                 {
6667                         // remove GLSL gamma texture
6668                 }
6669                 break;
6670         case RENDERPATH_GL11:
6671         case RENDERPATH_GL13:
6672         case RENDERPATH_GLES1:
6673                 break;
6674         }
6675 }
6676
6677 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6678 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6679 /*
6680 ================
6681 R_SelectScene
6682 ================
6683 */
6684 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6685         if( scenetype != r_currentscenetype ) {
6686                 // store the old scenetype
6687                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6688                 r_currentscenetype = scenetype;
6689                 // move in the new scene
6690                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6691         }
6692 }
6693
6694 /*
6695 ================
6696 R_GetScenePointer
6697 ================
6698 */
6699 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6700 {
6701         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6702         if( scenetype == r_currentscenetype ) {
6703                 return &r_refdef.scene;
6704         } else {
6705                 return &r_scenes_store[ scenetype ];
6706         }
6707 }
6708
6709 /*
6710 ================
6711 R_RenderView
6712 ================
6713 */
6714 int dpsoftrast_test;
6715 extern void R_Shadow_UpdateBounceGridTexture(void);
6716 extern cvar_t r_shadow_bouncegrid;
6717 void R_RenderView(void)
6718 {
6719         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6720
6721         dpsoftrast_test = r_test.integer;
6722
6723         if (r_timereport_active)
6724                 R_TimeReport("start");
6725         r_textureframe++; // used only by R_GetCurrentTexture
6726         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6727
6728         if(R_CompileShader_CheckStaticParms())
6729                 R_GLSL_Restart_f();
6730
6731         if (!r_drawentities.integer)
6732                 r_refdef.scene.numentities = 0;
6733
6734         R_AnimCache_ClearCache();
6735         R_FrameData_NewFrame();
6736
6737         /* adjust for stereo display */
6738         if(R_Stereo_Active())
6739         {
6740                 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);
6741                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6742         }
6743
6744         if (r_refdef.view.isoverlay)
6745         {
6746                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6747                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6748                 R_TimeReport("depthclear");
6749
6750                 r_refdef.view.showdebug = false;
6751
6752                 r_waterstate.enabled = false;
6753                 r_waterstate.numwaterplanes = 0;
6754
6755                 R_RenderScene();
6756
6757                 r_refdef.view.matrix = originalmatrix;
6758
6759                 CHECKGLERROR
6760                 return;
6761         }
6762
6763         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6764         {
6765                 r_refdef.view.matrix = originalmatrix;
6766                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6767         }
6768
6769         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6770
6771         R_RenderView_UpdateViewVectors();
6772
6773         R_Shadow_UpdateWorldLightSelection();
6774
6775         R_Bloom_StartFrame();
6776         R_Water_StartFrame();
6777
6778         CHECKGLERROR
6779         if (r_timereport_active)
6780                 R_TimeReport("viewsetup");
6781
6782         R_ResetViewRendering3D();
6783
6784         if (r_refdef.view.clear || r_refdef.fogenabled)
6785         {
6786                 R_ClearScreen(r_refdef.fogenabled);
6787                 if (r_timereport_active)
6788                         R_TimeReport("viewclear");
6789         }
6790         r_refdef.view.clear = true;
6791
6792         // this produces a bloom texture to be used in R_BlendView() later
6793         if (r_bloomstate.hdr)
6794         {
6795                 R_HDR_RenderBloomTexture();
6796                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6797                 r_textureframe++; // used only by R_GetCurrentTexture
6798         }
6799
6800         r_refdef.view.showdebug = true;
6801
6802         R_View_Update();
6803         if (r_timereport_active)
6804                 R_TimeReport("visibility");
6805
6806         R_Shadow_UpdateBounceGridTexture();
6807         if (r_timereport_active && r_shadow_bouncegrid.integer)
6808                 R_TimeReport("bouncegrid");
6809
6810         r_waterstate.numwaterplanes = 0;
6811         if (r_waterstate.enabled)
6812                 R_RenderWaterPlanes();
6813
6814         R_RenderScene();
6815         r_waterstate.numwaterplanes = 0;
6816
6817         R_BlendView();
6818         if (r_timereport_active)
6819                 R_TimeReport("blendview");
6820
6821         GL_Scissor(0, 0, vid.width, vid.height);
6822         GL_ScissorTest(false);
6823
6824         r_refdef.view.matrix = originalmatrix;
6825
6826         CHECKGLERROR
6827 }
6828
6829 void R_RenderWaterPlanes(void)
6830 {
6831         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6832         {
6833                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6834                 if (r_timereport_active)
6835                         R_TimeReport("waterworld");
6836         }
6837
6838         // don't let sound skip if going slow
6839         if (r_refdef.scene.extraupdate)
6840                 S_ExtraUpdate ();
6841
6842         R_DrawModelsAddWaterPlanes();
6843         if (r_timereport_active)
6844                 R_TimeReport("watermodels");
6845
6846         if (r_waterstate.numwaterplanes)
6847         {
6848                 R_Water_ProcessPlanes();
6849                 if (r_timereport_active)
6850                         R_TimeReport("waterscenes");
6851         }
6852 }
6853
6854 extern void R_DrawLightningBeams (void);
6855 extern void VM_CL_AddPolygonsToMeshQueue (void);
6856 extern void R_DrawPortals (void);
6857 extern cvar_t cl_locs_show;
6858 static void R_DrawLocs(void);
6859 static void R_DrawEntityBBoxes(void);
6860 static void R_DrawModelDecals(void);
6861 extern void R_DrawModelShadows(void);
6862 extern void R_DrawModelShadowMaps(void);
6863 extern cvar_t cl_decals_newsystem;
6864 extern qboolean r_shadow_usingdeferredprepass;
6865 void R_RenderScene(void)
6866 {
6867         qboolean shadowmapping = false;
6868
6869         if (r_timereport_active)
6870                 R_TimeReport("beginscene");
6871
6872         r_refdef.stats.renders++;
6873
6874         R_UpdateFogColor();
6875
6876         // don't let sound skip if going slow
6877         if (r_refdef.scene.extraupdate)
6878                 S_ExtraUpdate ();
6879
6880         R_MeshQueue_BeginScene();
6881
6882         R_SkyStartFrame();
6883
6884         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);
6885
6886         if (r_timereport_active)
6887                 R_TimeReport("skystartframe");
6888
6889         if (cl.csqc_vidvars.drawworld)
6890         {
6891                 // don't let sound skip if going slow
6892                 if (r_refdef.scene.extraupdate)
6893                         S_ExtraUpdate ();
6894
6895                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6896                 {
6897                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6898                         if (r_timereport_active)
6899                                 R_TimeReport("worldsky");
6900                 }
6901
6902                 if (R_DrawBrushModelsSky() && r_timereport_active)
6903                         R_TimeReport("bmodelsky");
6904
6905                 if (skyrendermasked && skyrenderlater)
6906                 {
6907                         // we have to force off the water clipping plane while rendering sky
6908                         R_SetupView(false);
6909                         R_Sky();
6910                         R_SetupView(true);
6911                         if (r_timereport_active)
6912                                 R_TimeReport("sky");
6913                 }
6914         }
6915
6916         R_AnimCache_CacheVisibleEntities();
6917         if (r_timereport_active)
6918                 R_TimeReport("animation");
6919
6920         R_Shadow_PrepareLights();
6921         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6922                 R_Shadow_PrepareModelShadows();
6923         if (r_timereport_active)
6924                 R_TimeReport("preparelights");
6925
6926         if (R_Shadow_ShadowMappingEnabled())
6927                 shadowmapping = true;
6928
6929         if (r_shadow_usingdeferredprepass)
6930                 R_Shadow_DrawPrepass();
6931
6932         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6933         {
6934                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6935                 if (r_timereport_active)
6936                         R_TimeReport("worlddepth");
6937         }
6938         if (r_depthfirst.integer >= 2)
6939         {
6940                 R_DrawModelsDepth();
6941                 if (r_timereport_active)
6942                         R_TimeReport("modeldepth");
6943         }
6944
6945         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6946         {
6947                 R_DrawModelShadowMaps();
6948                 R_ResetViewRendering3D();
6949                 // don't let sound skip if going slow
6950                 if (r_refdef.scene.extraupdate)
6951                         S_ExtraUpdate ();
6952         }
6953
6954         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6955         {
6956                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6957                 if (r_timereport_active)
6958                         R_TimeReport("world");
6959         }
6960
6961         // don't let sound skip if going slow
6962         if (r_refdef.scene.extraupdate)
6963                 S_ExtraUpdate ();
6964
6965         R_DrawModels();
6966         if (r_timereport_active)
6967                 R_TimeReport("models");
6968
6969         // don't let sound skip if going slow
6970         if (r_refdef.scene.extraupdate)
6971                 S_ExtraUpdate ();
6972
6973         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6974         {
6975                 R_DrawModelShadows();
6976                 R_ResetViewRendering3D();
6977                 // don't let sound skip if going slow
6978                 if (r_refdef.scene.extraupdate)
6979                         S_ExtraUpdate ();
6980         }
6981
6982         if (!r_shadow_usingdeferredprepass)
6983         {
6984                 R_Shadow_DrawLights();
6985                 if (r_timereport_active)
6986                         R_TimeReport("rtlights");
6987         }
6988
6989         // don't let sound skip if going slow
6990         if (r_refdef.scene.extraupdate)
6991                 S_ExtraUpdate ();
6992
6993         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6994         {
6995                 R_DrawModelShadows();
6996                 R_ResetViewRendering3D();
6997                 // don't let sound skip if going slow
6998                 if (r_refdef.scene.extraupdate)
6999                         S_ExtraUpdate ();
7000         }
7001
7002         if (cl.csqc_vidvars.drawworld)
7003         {
7004                 if (cl_decals_newsystem.integer)
7005                 {
7006                         R_DrawModelDecals();
7007                         if (r_timereport_active)
7008                                 R_TimeReport("modeldecals");
7009                 }
7010                 else
7011                 {
7012                         R_DrawDecals();
7013                         if (r_timereport_active)
7014                                 R_TimeReport("decals");
7015                 }
7016
7017                 R_DrawParticles();
7018                 if (r_timereport_active)
7019                         R_TimeReport("particles");
7020
7021                 R_DrawExplosions();
7022                 if (r_timereport_active)
7023                         R_TimeReport("explosions");
7024
7025                 R_DrawLightningBeams();
7026                 if (r_timereport_active)
7027                         R_TimeReport("lightning");
7028         }
7029
7030         VM_CL_AddPolygonsToMeshQueue();
7031
7032         if (r_refdef.view.showdebug)
7033         {
7034                 if (cl_locs_show.integer)
7035                 {
7036                         R_DrawLocs();
7037                         if (r_timereport_active)
7038                                 R_TimeReport("showlocs");
7039                 }
7040
7041                 if (r_drawportals.integer)
7042                 {
7043                         R_DrawPortals();
7044                         if (r_timereport_active)
7045                                 R_TimeReport("portals");
7046                 }
7047
7048                 if (r_showbboxes.value > 0)
7049                 {
7050                         R_DrawEntityBBoxes();
7051                         if (r_timereport_active)
7052                                 R_TimeReport("bboxes");
7053                 }
7054         }
7055
7056         if (r_transparent.integer)
7057         {
7058                 R_MeshQueue_RenderTransparent();
7059                 if (r_timereport_active)
7060                         R_TimeReport("drawtrans");
7061         }
7062
7063         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))
7064         {
7065                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7066                 if (r_timereport_active)
7067                         R_TimeReport("worlddebug");
7068                 R_DrawModelsDebug();
7069                 if (r_timereport_active)
7070                         R_TimeReport("modeldebug");
7071         }
7072
7073         if (cl.csqc_vidvars.drawworld)
7074         {
7075                 R_Shadow_DrawCoronas();
7076                 if (r_timereport_active)
7077                         R_TimeReport("coronas");
7078         }
7079
7080 #if 0
7081         {
7082                 GL_DepthTest(false);
7083                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7084                 GL_Color(1, 1, 1, 1);
7085                 qglBegin(GL_POLYGON);
7086                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7087                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7088                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7089                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7090                 qglEnd();
7091                 qglBegin(GL_POLYGON);
7092                 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]);
7093                 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]);
7094                 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]);
7095                 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]);
7096                 qglEnd();
7097                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7098         }
7099 #endif
7100
7101         // don't let sound skip if going slow
7102         if (r_refdef.scene.extraupdate)
7103                 S_ExtraUpdate ();
7104
7105         R_ResetViewRendering2D();
7106 }
7107
7108 static const unsigned short bboxelements[36] =
7109 {
7110         5, 1, 3, 5, 3, 7,
7111         6, 2, 0, 6, 0, 4,
7112         7, 3, 2, 7, 2, 6,
7113         4, 0, 1, 4, 1, 5,
7114         4, 5, 7, 4, 7, 6,
7115         1, 0, 2, 1, 2, 3,
7116 };
7117
7118 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7119 {
7120         int i;
7121         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7122
7123         RSurf_ActiveWorldEntity();
7124
7125         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7126         GL_DepthMask(false);
7127         GL_DepthRange(0, 1);
7128         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7129 //      R_Mesh_ResetTextureState();
7130
7131         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7132         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7133         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7134         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7135         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7136         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7137         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7138         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7139         R_FillColors(color4f, 8, cr, cg, cb, ca);
7140         if (r_refdef.fogenabled)
7141         {
7142                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7143                 {
7144                         f1 = RSurf_FogVertex(v);
7145                         f2 = 1 - f1;
7146                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7147                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7148                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7149                 }
7150         }
7151         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7152         R_Mesh_ResetTextureState();
7153         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7154         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7155 }
7156
7157 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7158 {
7159         int i;
7160         float color[4];
7161         prvm_edict_t *edict;
7162         prvm_prog_t *prog_save = prog;
7163
7164         // this function draws bounding boxes of server entities
7165         if (!sv.active)
7166                 return;
7167
7168         GL_CullFace(GL_NONE);
7169         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7170
7171         prog = 0;
7172         SV_VM_Begin();
7173         for (i = 0;i < numsurfaces;i++)
7174         {
7175                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7176                 switch ((int)PRVM_serveredictfloat(edict, solid))
7177                 {
7178                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7179                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7180                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7181                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7182                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7183                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7184                 }
7185                 color[3] *= r_showbboxes.value;
7186                 color[3] = bound(0, color[3], 1);
7187                 GL_DepthTest(!r_showdisabledepthtest.integer);
7188                 GL_CullFace(r_refdef.view.cullface_front);
7189                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7190         }
7191         SV_VM_End();
7192         prog = prog_save;
7193 }
7194
7195 static void R_DrawEntityBBoxes(void)
7196 {
7197         int i;
7198         prvm_edict_t *edict;
7199         vec3_t center;
7200         prvm_prog_t *prog_save = prog;
7201
7202         // this function draws bounding boxes of server entities
7203         if (!sv.active)
7204                 return;
7205
7206         prog = 0;
7207         SV_VM_Begin();
7208         for (i = 0;i < prog->num_edicts;i++)
7209         {
7210                 edict = PRVM_EDICT_NUM(i);
7211                 if (edict->priv.server->free)
7212                         continue;
7213                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7214                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7215                         continue;
7216                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7217                         continue;
7218                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7219                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7220         }
7221         SV_VM_End();
7222         prog = prog_save;
7223 }
7224
7225 static const int nomodelelement3i[24] =
7226 {
7227         5, 2, 0,
7228         5, 1, 2,
7229         5, 0, 3,
7230         5, 3, 1,
7231         0, 2, 4,
7232         2, 1, 4,
7233         3, 0, 4,
7234         1, 3, 4
7235 };
7236
7237 static const unsigned short nomodelelement3s[24] =
7238 {
7239         5, 2, 0,
7240         5, 1, 2,
7241         5, 0, 3,
7242         5, 3, 1,
7243         0, 2, 4,
7244         2, 1, 4,
7245         3, 0, 4,
7246         1, 3, 4
7247 };
7248
7249 static const float nomodelvertex3f[6*3] =
7250 {
7251         -16,   0,   0,
7252          16,   0,   0,
7253           0, -16,   0,
7254           0,  16,   0,
7255           0,   0, -16,
7256           0,   0,  16
7257 };
7258
7259 static const float nomodelcolor4f[6*4] =
7260 {
7261         0.0f, 0.0f, 0.5f, 1.0f,
7262         0.0f, 0.0f, 0.5f, 1.0f,
7263         0.0f, 0.5f, 0.0f, 1.0f,
7264         0.0f, 0.5f, 0.0f, 1.0f,
7265         0.5f, 0.0f, 0.0f, 1.0f,
7266         0.5f, 0.0f, 0.0f, 1.0f
7267 };
7268
7269 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7270 {
7271         int i;
7272         float f1, f2, *c;
7273         float color4f[6*4];
7274
7275         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);
7276
7277         // this is only called once per entity so numsurfaces is always 1, and
7278         // surfacelist is always {0}, so this code does not handle batches
7279
7280         if (rsurface.ent_flags & RENDER_ADDITIVE)
7281         {
7282                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7283                 GL_DepthMask(false);
7284         }
7285         else if (rsurface.colormod[3] < 1)
7286         {
7287                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7288                 GL_DepthMask(false);
7289         }
7290         else
7291         {
7292                 GL_BlendFunc(GL_ONE, GL_ZERO);
7293                 GL_DepthMask(true);
7294         }
7295         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7296         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7297         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7298         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7299         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7300         for (i = 0, c = color4f;i < 6;i++, c += 4)
7301         {
7302                 c[0] *= rsurface.colormod[0];
7303                 c[1] *= rsurface.colormod[1];
7304                 c[2] *= rsurface.colormod[2];
7305                 c[3] *= rsurface.colormod[3];
7306         }
7307         if (r_refdef.fogenabled)
7308         {
7309                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7310                 {
7311                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7312                         f2 = 1 - f1;
7313                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7314                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7315                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7316                 }
7317         }
7318 //      R_Mesh_ResetTextureState();
7319         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7320         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7321         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7322 }
7323
7324 void R_DrawNoModel(entity_render_t *ent)
7325 {
7326         vec3_t org;
7327         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7328         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7329                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7330         else
7331                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7332 }
7333
7334 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7335 {
7336         vec3_t right1, right2, diff, normal;
7337
7338         VectorSubtract (org2, org1, normal);
7339
7340         // calculate 'right' vector for start
7341         VectorSubtract (r_refdef.view.origin, org1, diff);
7342         CrossProduct (normal, diff, right1);
7343         VectorNormalize (right1);
7344
7345         // calculate 'right' vector for end
7346         VectorSubtract (r_refdef.view.origin, org2, diff);
7347         CrossProduct (normal, diff, right2);
7348         VectorNormalize (right2);
7349
7350         vert[ 0] = org1[0] + width * right1[0];
7351         vert[ 1] = org1[1] + width * right1[1];
7352         vert[ 2] = org1[2] + width * right1[2];
7353         vert[ 3] = org1[0] - width * right1[0];
7354         vert[ 4] = org1[1] - width * right1[1];
7355         vert[ 5] = org1[2] - width * right1[2];
7356         vert[ 6] = org2[0] - width * right2[0];
7357         vert[ 7] = org2[1] - width * right2[1];
7358         vert[ 8] = org2[2] - width * right2[2];
7359         vert[ 9] = org2[0] + width * right2[0];
7360         vert[10] = org2[1] + width * right2[1];
7361         vert[11] = org2[2] + width * right2[2];
7362 }
7363
7364 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)
7365 {
7366         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7367         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7368         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7369         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7370         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7371         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7372         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7373         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7374         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7375         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7376         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7377         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7378 }
7379
7380 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7381 {
7382         int i;
7383         float *vertex3f;
7384         float v[3];
7385         VectorSet(v, x, y, z);
7386         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7387                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7388                         break;
7389         if (i == mesh->numvertices)
7390         {
7391                 if (mesh->numvertices < mesh->maxvertices)
7392                 {
7393                         VectorCopy(v, vertex3f);
7394                         mesh->numvertices++;
7395                 }
7396                 return mesh->numvertices;
7397         }
7398         else
7399                 return i;
7400 }
7401
7402 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7403 {
7404         int i;
7405         int *e, element[3];
7406         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7407         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7408         e = mesh->element3i + mesh->numtriangles * 3;
7409         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7410         {
7411                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[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 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7424 {
7425         int i;
7426         int *e, element[3];
7427         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7428         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7429         e = mesh->element3i + mesh->numtriangles * 3;
7430         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7431         {
7432                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7433                 if (mesh->numtriangles < mesh->maxtriangles)
7434                 {
7435                         *e++ = element[0];
7436                         *e++ = element[1];
7437                         *e++ = element[2];
7438                         mesh->numtriangles++;
7439                 }
7440                 element[1] = element[2];
7441         }
7442 }
7443
7444 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7445 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7446 {
7447         int planenum, planenum2;
7448         int w;
7449         int tempnumpoints;
7450         mplane_t *plane, *plane2;
7451         double maxdist;
7452         double temppoints[2][256*3];
7453         // figure out how large a bounding box we need to properly compute this brush
7454         maxdist = 0;
7455         for (w = 0;w < numplanes;w++)
7456                 maxdist = max(maxdist, fabs(planes[w].dist));
7457         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7458         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7459         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7460         {
7461                 w = 0;
7462                 tempnumpoints = 4;
7463                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7464                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7465                 {
7466                         if (planenum2 == planenum)
7467                                 continue;
7468                         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);
7469                         w = !w;
7470                 }
7471                 if (tempnumpoints < 3)
7472                         continue;
7473                 // generate elements forming a triangle fan for this polygon
7474                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7475         }
7476 }
7477
7478 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)
7479 {
7480         texturelayer_t *layer;
7481         layer = t->currentlayers + t->currentnumlayers++;
7482         layer->type = type;
7483         layer->depthmask = depthmask;
7484         layer->blendfunc1 = blendfunc1;
7485         layer->blendfunc2 = blendfunc2;
7486         layer->texture = texture;
7487         layer->texmatrix = *matrix;
7488         layer->color[0] = r;
7489         layer->color[1] = g;
7490         layer->color[2] = b;
7491         layer->color[3] = a;
7492 }
7493
7494 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7495 {
7496         if(parms[0] == 0 && parms[1] == 0)
7497                 return false;
7498         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7499                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7500                         return false;
7501         return true;
7502 }
7503
7504 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7505 {
7506         double index, f;
7507         index = parms[2] + rsurface.shadertime * parms[3];
7508         index -= floor(index);
7509         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7510         {
7511         default:
7512         case Q3WAVEFUNC_NONE:
7513         case Q3WAVEFUNC_NOISE:
7514         case Q3WAVEFUNC_COUNT:
7515                 f = 0;
7516                 break;
7517         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7518         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7519         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7520         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7521         case Q3WAVEFUNC_TRIANGLE:
7522                 index *= 4;
7523                 f = index - floor(index);
7524                 if (index < 1)
7525                 {
7526                         // f = f;
7527                 }
7528                 else if (index < 2)
7529                         f = 1 - f;
7530                 else if (index < 3)
7531                         f = -f;
7532                 else
7533                         f = -(1 - f);
7534                 break;
7535         }
7536         f = parms[0] + parms[1] * f;
7537         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7538                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7539         return (float) f;
7540 }
7541
7542 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7543 {
7544         int w, h, idx;
7545         double f;
7546         double offsetd[2];
7547         float tcmat[12];
7548         matrix4x4_t matrix, temp;
7549         switch(tcmod->tcmod)
7550         {
7551                 case Q3TCMOD_COUNT:
7552                 case Q3TCMOD_NONE:
7553                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7554                                 matrix = r_waterscrollmatrix;
7555                         else
7556                                 matrix = identitymatrix;
7557                         break;
7558                 case Q3TCMOD_ENTITYTRANSLATE:
7559                         // this is used in Q3 to allow the gamecode to control texcoord
7560                         // scrolling on the entity, which is not supported in darkplaces yet.
7561                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7562                         break;
7563                 case Q3TCMOD_ROTATE:
7564                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7565                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7566                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7567                         break;
7568                 case Q3TCMOD_SCALE:
7569                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7570                         break;
7571                 case Q3TCMOD_SCROLL:
7572                         // extra care is needed because of precision breakdown with large values of time
7573                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7574                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7575                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7576                         break;
7577                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7578                         w = (int) tcmod->parms[0];
7579                         h = (int) tcmod->parms[1];
7580                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7581                         f = f - floor(f);
7582                         idx = (int) floor(f * w * h);
7583                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7584                         break;
7585                 case Q3TCMOD_STRETCH:
7586                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7587                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7588                         break;
7589                 case Q3TCMOD_TRANSFORM:
7590                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7591                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7592                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7593                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7594                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7595                         break;
7596                 case Q3TCMOD_TURBULENT:
7597                         // this is handled in the RSurf_PrepareVertices function
7598                         matrix = identitymatrix;
7599                         break;
7600         }
7601         temp = *texmatrix;
7602         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7603 }
7604
7605 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7606 {
7607         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7608         char name[MAX_QPATH];
7609         skinframe_t *skinframe;
7610         unsigned char pixels[296*194];
7611         strlcpy(cache->name, skinname, sizeof(cache->name));
7612         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7613         if (developer_loading.integer)
7614                 Con_Printf("loading %s\n", name);
7615         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7616         if (!skinframe || !skinframe->base)
7617         {
7618                 unsigned char *f;
7619                 fs_offset_t filesize;
7620                 skinframe = NULL;
7621                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7622                 if (f)
7623                 {
7624                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7625                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7626                         Mem_Free(f);
7627                 }
7628         }
7629         cache->skinframe = skinframe;
7630 }
7631
7632 texture_t *R_GetCurrentTexture(texture_t *t)
7633 {
7634         int i;
7635         const entity_render_t *ent = rsurface.entity;
7636         dp_model_t *model = ent->model;
7637         q3shaderinfo_layer_tcmod_t *tcmod;
7638
7639         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7640                 return t->currentframe;
7641         t->update_lastrenderframe = r_textureframe;
7642         t->update_lastrenderentity = (void *)ent;
7643
7644         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7645                 t->camera_entity = ent->entitynumber;
7646         else
7647                 t->camera_entity = 0;
7648
7649         // switch to an alternate material if this is a q1bsp animated material
7650         {
7651                 texture_t *texture = t;
7652                 int s = rsurface.ent_skinnum;
7653                 if ((unsigned int)s >= (unsigned int)model->numskins)
7654                         s = 0;
7655                 if (model->skinscenes)
7656                 {
7657                         if (model->skinscenes[s].framecount > 1)
7658                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7659                         else
7660                                 s = model->skinscenes[s].firstframe;
7661                 }
7662                 if (s > 0)
7663                         t = t + s * model->num_surfaces;
7664                 if (t->animated)
7665                 {
7666                         // use an alternate animation if the entity's frame is not 0,
7667                         // and only if the texture has an alternate animation
7668                         if (rsurface.ent_alttextures && t->anim_total[1])
7669                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7670                         else
7671                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7672                 }
7673                 texture->currentframe = t;
7674         }
7675
7676         // update currentskinframe to be a qw skin or animation frame
7677         if (rsurface.ent_qwskin >= 0)
7678         {
7679                 i = rsurface.ent_qwskin;
7680                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7681                 {
7682                         r_qwskincache_size = cl.maxclients;
7683                         if (r_qwskincache)
7684                                 Mem_Free(r_qwskincache);
7685                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7686                 }
7687                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7688                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7689                 t->currentskinframe = r_qwskincache[i].skinframe;
7690                 if (t->currentskinframe == NULL)
7691                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7692         }
7693         else if (t->numskinframes >= 2)
7694                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7695         if (t->backgroundnumskinframes >= 2)
7696                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7697
7698         t->currentmaterialflags = t->basematerialflags;
7699         t->currentalpha = rsurface.colormod[3];
7700         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7701                 t->currentalpha *= r_wateralpha.value;
7702         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7703                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7704         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7705                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7706         if (!(rsurface.ent_flags & RENDER_LIGHT))
7707                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7708         else if (FAKELIGHT_ENABLED)
7709         {
7710                 // no modellight if using fakelight for the map
7711         }
7712         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7713         {
7714                 // pick a model lighting mode
7715                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7716                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7717                 else
7718                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7719         }
7720         if (rsurface.ent_flags & RENDER_ADDITIVE)
7721                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7722         else if (t->currentalpha < 1)
7723                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7724         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7725                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7726         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7727                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7728         if (t->backgroundnumskinframes)
7729                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7730         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7731         {
7732                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7733                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7734         }
7735         else
7736                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7737         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7738         {
7739                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7740                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7741         }
7742         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7743                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7744
7745         // there is no tcmod
7746         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7747         {
7748                 t->currenttexmatrix = r_waterscrollmatrix;
7749                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7750         }
7751         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7752         {
7753                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7754                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7755         }
7756
7757         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7758                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7759         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7760                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7761
7762         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7763         if (t->currentskinframe->qpixels)
7764                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7765         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7766         if (!t->basetexture)
7767                 t->basetexture = r_texture_notexture;
7768         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7769         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7770         t->nmaptexture = t->currentskinframe->nmap;
7771         if (!t->nmaptexture)
7772                 t->nmaptexture = r_texture_blanknormalmap;
7773         t->glosstexture = r_texture_black;
7774         t->glowtexture = t->currentskinframe->glow;
7775         t->fogtexture = t->currentskinframe->fog;
7776         t->reflectmasktexture = t->currentskinframe->reflect;
7777         if (t->backgroundnumskinframes)
7778         {
7779                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7780                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7781                 t->backgroundglosstexture = r_texture_black;
7782                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7783                 if (!t->backgroundnmaptexture)
7784                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7785         }
7786         else
7787         {
7788                 t->backgroundbasetexture = r_texture_white;
7789                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7790                 t->backgroundglosstexture = r_texture_black;
7791                 t->backgroundglowtexture = NULL;
7792         }
7793         t->specularpower = r_shadow_glossexponent.value;
7794         // TODO: store reference values for these in the texture?
7795         t->specularscale = 0;
7796         if (r_shadow_gloss.integer > 0)
7797         {
7798                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7799                 {
7800                         if (r_shadow_glossintensity.value > 0)
7801                         {
7802                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7803                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7804                                 t->specularscale = r_shadow_glossintensity.value;
7805                         }
7806                 }
7807                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7808                 {
7809                         t->glosstexture = r_texture_white;
7810                         t->backgroundglosstexture = r_texture_white;
7811                         t->specularscale = r_shadow_gloss2intensity.value;
7812                         t->specularpower = r_shadow_gloss2exponent.value;
7813                 }
7814         }
7815         t->specularscale *= t->specularscalemod;
7816         t->specularpower *= t->specularpowermod;
7817
7818         // lightmaps mode looks bad with dlights using actual texturing, so turn
7819         // off the colormap and glossmap, but leave the normalmap on as it still
7820         // accurately represents the shading involved
7821         if (gl_lightmaps.integer)
7822         {
7823                 t->basetexture = r_texture_grey128;
7824                 t->pantstexture = r_texture_black;
7825                 t->shirttexture = r_texture_black;
7826                 t->nmaptexture = r_texture_blanknormalmap;
7827                 t->glosstexture = r_texture_black;
7828                 t->glowtexture = NULL;
7829                 t->fogtexture = NULL;
7830                 t->reflectmasktexture = NULL;
7831                 t->backgroundbasetexture = NULL;
7832                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7833                 t->backgroundglosstexture = r_texture_black;
7834                 t->backgroundglowtexture = NULL;
7835                 t->specularscale = 0;
7836                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7837         }
7838
7839         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7840         VectorClear(t->dlightcolor);
7841         t->currentnumlayers = 0;
7842         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7843         {
7844                 int blendfunc1, blendfunc2;
7845                 qboolean depthmask;
7846                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7847                 {
7848                         blendfunc1 = GL_SRC_ALPHA;
7849                         blendfunc2 = GL_ONE;
7850                 }
7851                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7852                 {
7853                         blendfunc1 = GL_SRC_ALPHA;
7854                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7855                 }
7856                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7857                 {
7858                         blendfunc1 = t->customblendfunc[0];
7859                         blendfunc2 = t->customblendfunc[1];
7860                 }
7861                 else
7862                 {
7863                         blendfunc1 = GL_ONE;
7864                         blendfunc2 = GL_ZERO;
7865                 }
7866                 // don't colormod evilblend textures
7867                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7868                         VectorSet(t->lightmapcolor, 1, 1, 1);
7869                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7870                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7871                 {
7872                         // fullbright is not affected by r_refdef.lightmapintensity
7873                         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]);
7874                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7875                                 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]);
7876                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7877                                 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]);
7878                 }
7879                 else
7880                 {
7881                         vec3_t ambientcolor;
7882                         float colorscale;
7883                         // set the color tint used for lights affecting this surface
7884                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7885                         colorscale = 2;
7886                         // q3bsp has no lightmap updates, so the lightstylevalue that
7887                         // would normally be baked into the lightmap must be
7888                         // applied to the color
7889                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7890                         if (model->type == mod_brushq3)
7891                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7892                         colorscale *= r_refdef.lightmapintensity;
7893                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7894                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7895                         // basic lit geometry
7896                         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]);
7897                         // add pants/shirt if needed
7898                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7899                                 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]);
7900                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7901                                 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]);
7902                         // now add ambient passes if needed
7903                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7904                         {
7905                                 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]);
7906                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7907                                         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]);
7908                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7909                                         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]);
7910                         }
7911                 }
7912                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7913                         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]);
7914                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7915                 {
7916                         // if this is opaque use alpha blend which will darken the earlier
7917                         // passes cheaply.
7918                         //
7919                         // if this is an alpha blended material, all the earlier passes
7920                         // were darkened by fog already, so we only need to add the fog
7921                         // color ontop through the fog mask texture
7922                         //
7923                         // if this is an additive blended material, all the earlier passes
7924                         // were darkened by fog already, and we should not add fog color
7925                         // (because the background was not darkened, there is no fog color
7926                         // that was lost behind it).
7927                         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]);
7928                 }
7929         }
7930
7931         return t->currentframe;
7932 }
7933
7934 rsurfacestate_t rsurface;
7935
7936 void RSurf_ActiveWorldEntity(void)
7937 {
7938         dp_model_t *model = r_refdef.scene.worldmodel;
7939         //if (rsurface.entity == r_refdef.scene.worldentity)
7940         //      return;
7941         rsurface.entity = r_refdef.scene.worldentity;
7942         rsurface.skeleton = NULL;
7943         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7944         rsurface.ent_skinnum = 0;
7945         rsurface.ent_qwskin = -1;
7946         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7947         rsurface.shadertime = r_refdef.scene.time;
7948         rsurface.matrix = identitymatrix;
7949         rsurface.inversematrix = identitymatrix;
7950         rsurface.matrixscale = 1;
7951         rsurface.inversematrixscale = 1;
7952         R_EntityMatrix(&identitymatrix);
7953         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7954         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7955         rsurface.fograngerecip = r_refdef.fograngerecip;
7956         rsurface.fogheightfade = r_refdef.fogheightfade;
7957         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7958         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7959         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7960         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7961         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7962         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7963         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7964         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7965         rsurface.colormod[3] = 1;
7966         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);
7967         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7968         rsurface.frameblend[0].lerp = 1;
7969         rsurface.ent_alttextures = false;
7970         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7971         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7972         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7973         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7974         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7975         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7976         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7977         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7978         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7979         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7980         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7981         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7982         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7983         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7984         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7985         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7986         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7987         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7988         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7989         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7990         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7991         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7992         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7993         rsurface.modelelement3i = model->surfmesh.data_element3i;
7994         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7995         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7996         rsurface.modelelement3s = model->surfmesh.data_element3s;
7997         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7998         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7999         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8000         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8001         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8002         rsurface.modelsurfaces = model->data_surfaces;
8003         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8004         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8005         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8006         rsurface.modelgeneratedvertex = false;
8007         rsurface.batchgeneratedvertex = false;
8008         rsurface.batchfirstvertex = 0;
8009         rsurface.batchnumvertices = 0;
8010         rsurface.batchfirsttriangle = 0;
8011         rsurface.batchnumtriangles = 0;
8012         rsurface.batchvertex3f  = NULL;
8013         rsurface.batchvertex3f_vertexbuffer = NULL;
8014         rsurface.batchvertex3f_bufferoffset = 0;
8015         rsurface.batchsvector3f = NULL;
8016         rsurface.batchsvector3f_vertexbuffer = NULL;
8017         rsurface.batchsvector3f_bufferoffset = 0;
8018         rsurface.batchtvector3f = NULL;
8019         rsurface.batchtvector3f_vertexbuffer = NULL;
8020         rsurface.batchtvector3f_bufferoffset = 0;
8021         rsurface.batchnormal3f  = NULL;
8022         rsurface.batchnormal3f_vertexbuffer = NULL;
8023         rsurface.batchnormal3f_bufferoffset = 0;
8024         rsurface.batchlightmapcolor4f = NULL;
8025         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8026         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8027         rsurface.batchtexcoordtexture2f = NULL;
8028         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8029         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8030         rsurface.batchtexcoordlightmap2f = NULL;
8031         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8032         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8033         rsurface.batchvertexmesh = NULL;
8034         rsurface.batchvertexmeshbuffer = NULL;
8035         rsurface.batchvertex3fbuffer = NULL;
8036         rsurface.batchelement3i = NULL;
8037         rsurface.batchelement3i_indexbuffer = NULL;
8038         rsurface.batchelement3i_bufferoffset = 0;
8039         rsurface.batchelement3s = NULL;
8040         rsurface.batchelement3s_indexbuffer = NULL;
8041         rsurface.batchelement3s_bufferoffset = 0;
8042         rsurface.passcolor4f = NULL;
8043         rsurface.passcolor4f_vertexbuffer = NULL;
8044         rsurface.passcolor4f_bufferoffset = 0;
8045 }
8046
8047 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8048 {
8049         dp_model_t *model = ent->model;
8050         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8051         //      return;
8052         rsurface.entity = (entity_render_t *)ent;
8053         rsurface.skeleton = ent->skeleton;
8054         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8055         rsurface.ent_skinnum = ent->skinnum;
8056         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;
8057         rsurface.ent_flags = ent->flags;
8058         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8059         rsurface.matrix = ent->matrix;
8060         rsurface.inversematrix = ent->inversematrix;
8061         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8062         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8063         R_EntityMatrix(&rsurface.matrix);
8064         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8065         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8066         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8067         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8068         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8069         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8070         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8071         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8072         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8073         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8074         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8075         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8076         rsurface.colormod[3] = ent->alpha;
8077         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8078         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8079         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8080         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8081         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8082         if (ent->model->brush.submodel && !prepass)
8083         {
8084                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8085                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8086         }
8087         if (model->surfmesh.isanimated && model->AnimateVertices)
8088         {
8089                 if (ent->animcache_vertex3f)
8090                 {
8091                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8092                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8093                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8094                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8095                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8096                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8097                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8098                 }
8099                 else if (wanttangents)
8100                 {
8101                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8102                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8103                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8104                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8105                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8106                         rsurface.modelvertexmesh = NULL;
8107                         rsurface.modelvertexmeshbuffer = NULL;
8108                         rsurface.modelvertex3fbuffer = NULL;
8109                 }
8110                 else if (wantnormals)
8111                 {
8112                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8113                         rsurface.modelsvector3f = NULL;
8114                         rsurface.modeltvector3f = NULL;
8115                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8116                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8117                         rsurface.modelvertexmesh = NULL;
8118                         rsurface.modelvertexmeshbuffer = NULL;
8119                         rsurface.modelvertex3fbuffer = NULL;
8120                 }
8121                 else
8122                 {
8123                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8124                         rsurface.modelsvector3f = NULL;
8125                         rsurface.modeltvector3f = NULL;
8126                         rsurface.modelnormal3f = NULL;
8127                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8128                         rsurface.modelvertexmesh = NULL;
8129                         rsurface.modelvertexmeshbuffer = NULL;
8130                         rsurface.modelvertex3fbuffer = NULL;
8131                 }
8132                 rsurface.modelvertex3f_vertexbuffer = 0;
8133                 rsurface.modelvertex3f_bufferoffset = 0;
8134                 rsurface.modelsvector3f_vertexbuffer = 0;
8135                 rsurface.modelsvector3f_bufferoffset = 0;
8136                 rsurface.modeltvector3f_vertexbuffer = 0;
8137                 rsurface.modeltvector3f_bufferoffset = 0;
8138                 rsurface.modelnormal3f_vertexbuffer = 0;
8139                 rsurface.modelnormal3f_bufferoffset = 0;
8140                 rsurface.modelgeneratedvertex = true;
8141         }
8142         else
8143         {
8144                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8145                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8146                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8147                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8148                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8149                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8150                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8151                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8152                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8153                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8154                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8155                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8156                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8157                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8158                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8159                 rsurface.modelgeneratedvertex = false;
8160         }
8161         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8162         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8163         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8164         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8165         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8166         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8167         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8168         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8169         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8170         rsurface.modelelement3i = model->surfmesh.data_element3i;
8171         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8172         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8173         rsurface.modelelement3s = model->surfmesh.data_element3s;
8174         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8175         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8176         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8177         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8178         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8179         rsurface.modelsurfaces = model->data_surfaces;
8180         rsurface.batchgeneratedvertex = false;
8181         rsurface.batchfirstvertex = 0;
8182         rsurface.batchnumvertices = 0;
8183         rsurface.batchfirsttriangle = 0;
8184         rsurface.batchnumtriangles = 0;
8185         rsurface.batchvertex3f  = NULL;
8186         rsurface.batchvertex3f_vertexbuffer = NULL;
8187         rsurface.batchvertex3f_bufferoffset = 0;
8188         rsurface.batchsvector3f = NULL;
8189         rsurface.batchsvector3f_vertexbuffer = NULL;
8190         rsurface.batchsvector3f_bufferoffset = 0;
8191         rsurface.batchtvector3f = NULL;
8192         rsurface.batchtvector3f_vertexbuffer = NULL;
8193         rsurface.batchtvector3f_bufferoffset = 0;
8194         rsurface.batchnormal3f  = NULL;
8195         rsurface.batchnormal3f_vertexbuffer = NULL;
8196         rsurface.batchnormal3f_bufferoffset = 0;
8197         rsurface.batchlightmapcolor4f = NULL;
8198         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8199         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8200         rsurface.batchtexcoordtexture2f = NULL;
8201         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8202         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8203         rsurface.batchtexcoordlightmap2f = NULL;
8204         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8205         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8206         rsurface.batchvertexmesh = NULL;
8207         rsurface.batchvertexmeshbuffer = NULL;
8208         rsurface.batchvertex3fbuffer = NULL;
8209         rsurface.batchelement3i = NULL;
8210         rsurface.batchelement3i_indexbuffer = NULL;
8211         rsurface.batchelement3i_bufferoffset = 0;
8212         rsurface.batchelement3s = NULL;
8213         rsurface.batchelement3s_indexbuffer = NULL;
8214         rsurface.batchelement3s_bufferoffset = 0;
8215         rsurface.passcolor4f = NULL;
8216         rsurface.passcolor4f_vertexbuffer = NULL;
8217         rsurface.passcolor4f_bufferoffset = 0;
8218 }
8219
8220 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)
8221 {
8222         rsurface.entity = r_refdef.scene.worldentity;
8223         rsurface.skeleton = NULL;
8224         rsurface.ent_skinnum = 0;
8225         rsurface.ent_qwskin = -1;
8226         rsurface.ent_flags = entflags;
8227         rsurface.shadertime = r_refdef.scene.time - shadertime;
8228         rsurface.modelnumvertices = numvertices;
8229         rsurface.modelnumtriangles = numtriangles;
8230         rsurface.matrix = *matrix;
8231         rsurface.inversematrix = *inversematrix;
8232         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8233         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8234         R_EntityMatrix(&rsurface.matrix);
8235         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8236         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8237         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8238         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8239         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8240         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8241         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8242         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8243         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8244         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8245         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8246         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8247         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);
8248         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8249         rsurface.frameblend[0].lerp = 1;
8250         rsurface.ent_alttextures = false;
8251         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8252         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8253         if (wanttangents)
8254         {
8255                 rsurface.modelvertex3f = (float *)vertex3f;
8256                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8257                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8258                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8259         }
8260         else if (wantnormals)
8261         {
8262                 rsurface.modelvertex3f = (float *)vertex3f;
8263                 rsurface.modelsvector3f = NULL;
8264                 rsurface.modeltvector3f = NULL;
8265                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8266         }
8267         else
8268         {
8269                 rsurface.modelvertex3f = (float *)vertex3f;
8270                 rsurface.modelsvector3f = NULL;
8271                 rsurface.modeltvector3f = NULL;
8272                 rsurface.modelnormal3f = NULL;
8273         }
8274         rsurface.modelvertexmesh = NULL;
8275         rsurface.modelvertexmeshbuffer = NULL;
8276         rsurface.modelvertex3fbuffer = NULL;
8277         rsurface.modelvertex3f_vertexbuffer = 0;
8278         rsurface.modelvertex3f_bufferoffset = 0;
8279         rsurface.modelsvector3f_vertexbuffer = 0;
8280         rsurface.modelsvector3f_bufferoffset = 0;
8281         rsurface.modeltvector3f_vertexbuffer = 0;
8282         rsurface.modeltvector3f_bufferoffset = 0;
8283         rsurface.modelnormal3f_vertexbuffer = 0;
8284         rsurface.modelnormal3f_bufferoffset = 0;
8285         rsurface.modelgeneratedvertex = true;
8286         rsurface.modellightmapcolor4f  = (float *)color4f;
8287         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8288         rsurface.modellightmapcolor4f_bufferoffset = 0;
8289         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8290         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8291         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8292         rsurface.modeltexcoordlightmap2f  = NULL;
8293         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8294         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8295         rsurface.modelelement3i = (int *)element3i;
8296         rsurface.modelelement3i_indexbuffer = NULL;
8297         rsurface.modelelement3i_bufferoffset = 0;
8298         rsurface.modelelement3s = (unsigned short *)element3s;
8299         rsurface.modelelement3s_indexbuffer = NULL;
8300         rsurface.modelelement3s_bufferoffset = 0;
8301         rsurface.modellightmapoffsets = NULL;
8302         rsurface.modelsurfaces = NULL;
8303         rsurface.batchgeneratedvertex = false;
8304         rsurface.batchfirstvertex = 0;
8305         rsurface.batchnumvertices = 0;
8306         rsurface.batchfirsttriangle = 0;
8307         rsurface.batchnumtriangles = 0;
8308         rsurface.batchvertex3f  = NULL;
8309         rsurface.batchvertex3f_vertexbuffer = NULL;
8310         rsurface.batchvertex3f_bufferoffset = 0;
8311         rsurface.batchsvector3f = NULL;
8312         rsurface.batchsvector3f_vertexbuffer = NULL;
8313         rsurface.batchsvector3f_bufferoffset = 0;
8314         rsurface.batchtvector3f = NULL;
8315         rsurface.batchtvector3f_vertexbuffer = NULL;
8316         rsurface.batchtvector3f_bufferoffset = 0;
8317         rsurface.batchnormal3f  = NULL;
8318         rsurface.batchnormal3f_vertexbuffer = NULL;
8319         rsurface.batchnormal3f_bufferoffset = 0;
8320         rsurface.batchlightmapcolor4f = NULL;
8321         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8322         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8323         rsurface.batchtexcoordtexture2f = NULL;
8324         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8325         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8326         rsurface.batchtexcoordlightmap2f = NULL;
8327         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8328         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8329         rsurface.batchvertexmesh = NULL;
8330         rsurface.batchvertexmeshbuffer = NULL;
8331         rsurface.batchvertex3fbuffer = NULL;
8332         rsurface.batchelement3i = NULL;
8333         rsurface.batchelement3i_indexbuffer = NULL;
8334         rsurface.batchelement3i_bufferoffset = 0;
8335         rsurface.batchelement3s = NULL;
8336         rsurface.batchelement3s_indexbuffer = NULL;
8337         rsurface.batchelement3s_bufferoffset = 0;
8338         rsurface.passcolor4f = NULL;
8339         rsurface.passcolor4f_vertexbuffer = NULL;
8340         rsurface.passcolor4f_bufferoffset = 0;
8341
8342         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8343         {
8344                 if ((wantnormals || wanttangents) && !normal3f)
8345                 {
8346                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8347                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8348                 }
8349                 if (wanttangents && !svector3f)
8350                 {
8351                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8352                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8353                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8354                 }
8355         }
8356 }
8357
8358 float RSurf_FogPoint(const float *v)
8359 {
8360         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8361         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8362         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8363         float FogHeightFade = r_refdef.fogheightfade;
8364         float fogfrac;
8365         unsigned int fogmasktableindex;
8366         if (r_refdef.fogplaneviewabove)
8367                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8368         else
8369                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8370         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8371         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8372 }
8373
8374 float RSurf_FogVertex(const float *v)
8375 {
8376         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8377         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8378         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8379         float FogHeightFade = rsurface.fogheightfade;
8380         float fogfrac;
8381         unsigned int fogmasktableindex;
8382         if (r_refdef.fogplaneviewabove)
8383                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8384         else
8385                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8386         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8387         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8388 }
8389
8390 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8391 {
8392         int i;
8393         for (i = 0;i < numelements;i++)
8394                 outelement3i[i] = inelement3i[i] + adjust;
8395 }
8396
8397 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8398 extern cvar_t gl_vbo;
8399 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8400 {
8401         int deformindex;
8402         int firsttriangle;
8403         int numtriangles;
8404         int firstvertex;
8405         int endvertex;
8406         int numvertices;
8407         int surfacefirsttriangle;
8408         int surfacenumtriangles;
8409         int surfacefirstvertex;
8410         int surfaceendvertex;
8411         int surfacenumvertices;
8412         int batchnumvertices;
8413         int batchnumtriangles;
8414         int needsupdate;
8415         int i, j;
8416         qboolean gaps;
8417         qboolean dynamicvertex;
8418         float amplitude;
8419         float animpos;
8420         float scale;
8421         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8422         float waveparms[4];
8423         q3shaderinfo_deform_t *deform;
8424         const msurface_t *surface, *firstsurface;
8425         r_vertexmesh_t *vertexmesh;
8426         if (!texturenumsurfaces)
8427                 return;
8428         // find vertex range of this surface batch
8429         gaps = false;
8430         firstsurface = texturesurfacelist[0];
8431         firsttriangle = firstsurface->num_firsttriangle;
8432         batchnumvertices = 0;
8433         batchnumtriangles = 0;
8434         firstvertex = endvertex = firstsurface->num_firstvertex;
8435         for (i = 0;i < texturenumsurfaces;i++)
8436         {
8437                 surface = texturesurfacelist[i];
8438                 if (surface != firstsurface + i)
8439                         gaps = true;
8440                 surfacefirstvertex = surface->num_firstvertex;
8441                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8442                 surfacenumvertices = surface->num_vertices;
8443                 surfacenumtriangles = surface->num_triangles;
8444                 if (firstvertex > surfacefirstvertex)
8445                         firstvertex = surfacefirstvertex;
8446                 if (endvertex < surfaceendvertex)
8447                         endvertex = surfaceendvertex;
8448                 batchnumvertices += surfacenumvertices;
8449                 batchnumtriangles += surfacenumtriangles;
8450         }
8451
8452         // we now know the vertex range used, and if there are any gaps in it
8453         rsurface.batchfirstvertex = firstvertex;
8454         rsurface.batchnumvertices = endvertex - firstvertex;
8455         rsurface.batchfirsttriangle = firsttriangle;
8456         rsurface.batchnumtriangles = batchnumtriangles;
8457
8458         // this variable holds flags for which properties have been updated that
8459         // may require regenerating vertexmesh array...
8460         needsupdate = 0;
8461
8462         // check if any dynamic vertex processing must occur
8463         dynamicvertex = false;
8464
8465         // if there is a chance of animated vertex colors, it's a dynamic batch
8466         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8467         {
8468                 dynamicvertex = true;
8469                 batchneed |= BATCHNEED_NOGAPS;
8470                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8471         }
8472
8473         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8474         {
8475                 switch (deform->deform)
8476                 {
8477                 default:
8478                 case Q3DEFORM_PROJECTIONSHADOW:
8479                 case Q3DEFORM_TEXT0:
8480                 case Q3DEFORM_TEXT1:
8481                 case Q3DEFORM_TEXT2:
8482                 case Q3DEFORM_TEXT3:
8483                 case Q3DEFORM_TEXT4:
8484                 case Q3DEFORM_TEXT5:
8485                 case Q3DEFORM_TEXT6:
8486                 case Q3DEFORM_TEXT7:
8487                 case Q3DEFORM_NONE:
8488                         break;
8489                 case Q3DEFORM_AUTOSPRITE:
8490                         dynamicvertex = true;
8491                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8492                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8493                         break;
8494                 case Q3DEFORM_AUTOSPRITE2:
8495                         dynamicvertex = true;
8496                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8497                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8498                         break;
8499                 case Q3DEFORM_NORMAL:
8500                         dynamicvertex = true;
8501                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8502                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8503                         break;
8504                 case Q3DEFORM_WAVE:
8505                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8506                                 break; // if wavefunc is a nop, ignore this transform
8507                         dynamicvertex = true;
8508                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8509                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8510                         break;
8511                 case Q3DEFORM_BULGE:
8512                         dynamicvertex = true;
8513                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8514                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8515                         break;
8516                 case Q3DEFORM_MOVE:
8517                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8518                                 break; // if wavefunc is a nop, ignore this transform
8519                         dynamicvertex = true;
8520                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8521                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8522                         break;
8523                 }
8524         }
8525         switch(rsurface.texture->tcgen.tcgen)
8526         {
8527         default:
8528         case Q3TCGEN_TEXTURE:
8529                 break;
8530         case Q3TCGEN_LIGHTMAP:
8531                 dynamicvertex = true;
8532                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8533                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8534                 break;
8535         case Q3TCGEN_VECTOR:
8536                 dynamicvertex = true;
8537                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8538                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8539                 break;
8540         case Q3TCGEN_ENVIRONMENT:
8541                 dynamicvertex = true;
8542                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8543                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8544                 break;
8545         }
8546         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8547         {
8548                 dynamicvertex = true;
8549                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8550                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8551         }
8552
8553         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8554         {
8555                 dynamicvertex = true;
8556                 batchneed |= BATCHNEED_NOGAPS;
8557                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8558         }
8559
8560         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8561         {
8562                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8563                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8564                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8565                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8566                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8567                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8568                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8569         }
8570
8571         // when the model data has no vertex buffer (dynamic mesh), we need to
8572         // eliminate gaps
8573         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8574                 batchneed |= BATCHNEED_NOGAPS;
8575
8576         // if needsupdate, we have to do a dynamic vertex batch for sure
8577         if (needsupdate & batchneed)
8578                 dynamicvertex = true;
8579
8580         // see if we need to build vertexmesh from arrays
8581         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8582                 dynamicvertex = true;
8583
8584         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8585         // also some drivers strongly dislike firstvertex
8586         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8587                 dynamicvertex = true;
8588
8589         rsurface.batchvertex3f = rsurface.modelvertex3f;
8590         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8591         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8592         rsurface.batchsvector3f = rsurface.modelsvector3f;
8593         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8594         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8595         rsurface.batchtvector3f = rsurface.modeltvector3f;
8596         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8597         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8598         rsurface.batchnormal3f = rsurface.modelnormal3f;
8599         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8600         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8601         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8602         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8603         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8604         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8605         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8606         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8607         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8608         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8609         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8610         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8611         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8612         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8613         rsurface.batchelement3i = rsurface.modelelement3i;
8614         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8615         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8616         rsurface.batchelement3s = rsurface.modelelement3s;
8617         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8618         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8619
8620         // if any dynamic vertex processing has to occur in software, we copy the
8621         // entire surface list together before processing to rebase the vertices
8622         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8623         //
8624         // if any gaps exist and we do not have a static vertex buffer, we have to
8625         // copy the surface list together to avoid wasting upload bandwidth on the
8626         // vertices in the gaps.
8627         //
8628         // if gaps exist and we have a static vertex buffer, we still have to
8629         // combine the index buffer ranges into one dynamic index buffer.
8630         //
8631         // in all cases we end up with data that can be drawn in one call.
8632
8633         if (!dynamicvertex)
8634         {
8635                 // static vertex data, just set pointers...
8636                 rsurface.batchgeneratedvertex = false;
8637                 // if there are gaps, we want to build a combined index buffer,
8638                 // otherwise use the original static buffer with an appropriate offset
8639                 if (gaps)
8640                 {
8641                         // build a new triangle elements array for this batch
8642                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8643                         rsurface.batchfirsttriangle = 0;
8644                         numtriangles = 0;
8645                         for (i = 0;i < texturenumsurfaces;i++)
8646                         {
8647                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8648                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8649                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8650                                 numtriangles += surfacenumtriangles;
8651                         }
8652                         rsurface.batchelement3i_indexbuffer = NULL;
8653                         rsurface.batchelement3i_bufferoffset = 0;
8654                         rsurface.batchelement3s = NULL;
8655                         rsurface.batchelement3s_indexbuffer = NULL;
8656                         rsurface.batchelement3s_bufferoffset = 0;
8657                         if (endvertex <= 65536)
8658                         {
8659                                 // make a 16bit (unsigned short) index array if possible
8660                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8661                                 for (i = 0;i < numtriangles*3;i++)
8662                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8663                         }
8664                 }
8665                 return;
8666         }
8667
8668         // something needs software processing, do it for real...
8669         // we only directly handle separate array data in this case and then
8670         // generate interleaved data if needed...
8671         rsurface.batchgeneratedvertex = true;
8672
8673         // now copy the vertex data into a combined array and make an index array
8674         // (this is what Quake3 does all the time)
8675         //if (gaps || rsurface.batchfirstvertex)
8676         {
8677                 rsurface.batchvertex3fbuffer = NULL;
8678                 rsurface.batchvertexmesh = NULL;
8679                 rsurface.batchvertexmeshbuffer = NULL;
8680                 rsurface.batchvertex3f = NULL;
8681                 rsurface.batchvertex3f_vertexbuffer = NULL;
8682                 rsurface.batchvertex3f_bufferoffset = 0;
8683                 rsurface.batchsvector3f = NULL;
8684                 rsurface.batchsvector3f_vertexbuffer = NULL;
8685                 rsurface.batchsvector3f_bufferoffset = 0;
8686                 rsurface.batchtvector3f = NULL;
8687                 rsurface.batchtvector3f_vertexbuffer = NULL;
8688                 rsurface.batchtvector3f_bufferoffset = 0;
8689                 rsurface.batchnormal3f = NULL;
8690                 rsurface.batchnormal3f_vertexbuffer = NULL;
8691                 rsurface.batchnormal3f_bufferoffset = 0;
8692                 rsurface.batchlightmapcolor4f = NULL;
8693                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8694                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8695                 rsurface.batchtexcoordtexture2f = NULL;
8696                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8697                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8698                 rsurface.batchtexcoordlightmap2f = NULL;
8699                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8700                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8701                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8702                 rsurface.batchelement3i_indexbuffer = NULL;
8703                 rsurface.batchelement3i_bufferoffset = 0;
8704                 rsurface.batchelement3s = NULL;
8705                 rsurface.batchelement3s_indexbuffer = NULL;
8706                 rsurface.batchelement3s_bufferoffset = 0;
8707                 // we'll only be setting up certain arrays as needed
8708                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8709                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8710                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8711                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8712                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8713                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8714                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8715                 {
8716                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8717                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8718                 }
8719                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8720                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8721                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8722                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8723                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8724                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8725                 numvertices = 0;
8726                 numtriangles = 0;
8727                 for (i = 0;i < texturenumsurfaces;i++)
8728                 {
8729                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8730                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8731                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8732                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8733                         // copy only the data requested
8734                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8735                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8736                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8737                         {
8738                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8739                                 {
8740                                         if (rsurface.batchvertex3f)
8741                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8742                                         else
8743                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8744                                 }
8745                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8746                                 {
8747                                         if (rsurface.modelnormal3f)
8748                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8749                                         else
8750                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8751                                 }
8752                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8753                                 {
8754                                         if (rsurface.modelsvector3f)
8755                                         {
8756                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8757                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8758                                         }
8759                                         else
8760                                         {
8761                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8762                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8763                                         }
8764                                 }
8765                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8766                                 {
8767                                         if (rsurface.modellightmapcolor4f)
8768                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8769                                         else
8770                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8771                                 }
8772                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8773                                 {
8774                                         if (rsurface.modeltexcoordtexture2f)
8775                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8776                                         else
8777                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8778                                 }
8779                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8780                                 {
8781                                         if (rsurface.modeltexcoordlightmap2f)
8782                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8783                                         else
8784                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8785                                 }
8786                         }
8787                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8788                         numvertices += surfacenumvertices;
8789                         numtriangles += surfacenumtriangles;
8790                 }
8791
8792                 // generate a 16bit index array as well if possible
8793                 // (in general, dynamic batches fit)
8794                 if (numvertices <= 65536)
8795                 {
8796                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8797                         for (i = 0;i < numtriangles*3;i++)
8798                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8799                 }
8800
8801                 // since we've copied everything, the batch now starts at 0
8802                 rsurface.batchfirstvertex = 0;
8803                 rsurface.batchnumvertices = batchnumvertices;
8804                 rsurface.batchfirsttriangle = 0;
8805                 rsurface.batchnumtriangles = batchnumtriangles;
8806         }
8807
8808         // q1bsp surfaces rendered in vertex color mode have to have colors
8809         // calculated based on lightstyles
8810         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8811         {
8812                 // generate color arrays for the surfaces in this list
8813                 int c[4];
8814                 int scale;
8815                 int size3;
8816                 const int *offsets;
8817                 const unsigned char *lm;
8818                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8819                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8820                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8821                 numvertices = 0;
8822                 for (i = 0;i < texturenumsurfaces;i++)
8823                 {
8824                         surface = texturesurfacelist[i];
8825                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8826                         surfacenumvertices = surface->num_vertices;
8827                         if (surface->lightmapinfo->samples)
8828                         {
8829                                 for (j = 0;j < surfacenumvertices;j++)
8830                                 {
8831                                         lm = surface->lightmapinfo->samples + offsets[j];
8832                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8833                                         VectorScale(lm, scale, c);
8834                                         if (surface->lightmapinfo->styles[1] != 255)
8835                                         {
8836                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8837                                                 lm += size3;
8838                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8839                                                 VectorMA(c, scale, lm, c);
8840                                                 if (surface->lightmapinfo->styles[2] != 255)
8841                                                 {
8842                                                         lm += size3;
8843                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8844                                                         VectorMA(c, scale, lm, c);
8845                                                         if (surface->lightmapinfo->styles[3] != 255)
8846                                                         {
8847                                                                 lm += size3;
8848                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8849                                                                 VectorMA(c, scale, lm, c);
8850                                                         }
8851                                                 }
8852                                         }
8853                                         c[0] >>= 7;
8854                                         c[1] >>= 7;
8855                                         c[2] >>= 7;
8856                                         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);
8857                                         numvertices++;
8858                                 }
8859                         }
8860                         else
8861                         {
8862                                 for (j = 0;j < surfacenumvertices;j++)
8863                                 {
8864                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8865                                         numvertices++;
8866                                 }
8867                         }
8868                 }
8869         }
8870
8871         // if vertices are deformed (sprite flares and things in maps, possibly
8872         // water waves, bulges and other deformations), modify the copied vertices
8873         // in place
8874         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8875         {
8876                 switch (deform->deform)
8877                 {
8878                 default:
8879                 case Q3DEFORM_PROJECTIONSHADOW:
8880                 case Q3DEFORM_TEXT0:
8881                 case Q3DEFORM_TEXT1:
8882                 case Q3DEFORM_TEXT2:
8883                 case Q3DEFORM_TEXT3:
8884                 case Q3DEFORM_TEXT4:
8885                 case Q3DEFORM_TEXT5:
8886                 case Q3DEFORM_TEXT6:
8887                 case Q3DEFORM_TEXT7:
8888                 case Q3DEFORM_NONE:
8889                         break;
8890                 case Q3DEFORM_AUTOSPRITE:
8891                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8892                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8893                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8894                         VectorNormalize(newforward);
8895                         VectorNormalize(newright);
8896                         VectorNormalize(newup);
8897 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8898 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8899 //                      rsurface.batchvertex3f_bufferoffset = 0;
8900 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8901 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8902 //                      rsurface.batchsvector3f_bufferoffset = 0;
8903 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8904 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8905 //                      rsurface.batchtvector3f_bufferoffset = 0;
8906 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8907 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8908 //                      rsurface.batchnormal3f_bufferoffset = 0;
8909                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8910                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8911                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8912                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8913                                 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);
8914                         // a single autosprite surface can contain multiple sprites...
8915                         for (j = 0;j < batchnumvertices - 3;j += 4)
8916                         {
8917                                 VectorClear(center);
8918                                 for (i = 0;i < 4;i++)
8919                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8920                                 VectorScale(center, 0.25f, center);
8921                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8922                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8923                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8924                                 for (i = 0;i < 4;i++)
8925                                 {
8926                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8927                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8928                                 }
8929                         }
8930                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8931                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8932                         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);
8933                         break;
8934                 case Q3DEFORM_AUTOSPRITE2:
8935                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8936                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8937                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8938                         VectorNormalize(newforward);
8939                         VectorNormalize(newright);
8940                         VectorNormalize(newup);
8941 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8942 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8943 //                      rsurface.batchvertex3f_bufferoffset = 0;
8944                         {
8945                                 const float *v1, *v2;
8946                                 vec3_t start, end;
8947                                 float f, l;
8948                                 struct
8949                                 {
8950                                         float length2;
8951                                         const float *v1;
8952                                         const float *v2;
8953                                 }
8954                                 shortest[2];
8955                                 memset(shortest, 0, sizeof(shortest));
8956                                 // a single autosprite surface can contain multiple sprites...
8957                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8958                                 {
8959                                         VectorClear(center);
8960                                         for (i = 0;i < 4;i++)
8961                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8962                                         VectorScale(center, 0.25f, center);
8963                                         // find the two shortest edges, then use them to define the
8964                                         // axis vectors for rotating around the central axis
8965                                         for (i = 0;i < 6;i++)
8966                                         {
8967                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8968                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8969                                                 l = VectorDistance2(v1, v2);
8970                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8971                                                 if (v1[2] != v2[2])
8972                                                         l += (1.0f / 1024.0f);
8973                                                 if (shortest[0].length2 > l || i == 0)
8974                                                 {
8975                                                         shortest[1] = shortest[0];
8976                                                         shortest[0].length2 = l;
8977                                                         shortest[0].v1 = v1;
8978                                                         shortest[0].v2 = v2;
8979                                                 }
8980                                                 else if (shortest[1].length2 > l || i == 1)
8981                                                 {
8982                                                         shortest[1].length2 = l;
8983                                                         shortest[1].v1 = v1;
8984                                                         shortest[1].v2 = v2;
8985                                                 }
8986                                         }
8987                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8988                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8989                                         // this calculates the right vector from the shortest edge
8990                                         // and the up vector from the edge midpoints
8991                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8992                                         VectorNormalize(right);
8993                                         VectorSubtract(end, start, up);
8994                                         VectorNormalize(up);
8995                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8996                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8997                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8998                                         VectorNegate(forward, forward);
8999                                         VectorReflect(forward, 0, up, forward);
9000                                         VectorNormalize(forward);
9001                                         CrossProduct(up, forward, newright);
9002                                         VectorNormalize(newright);
9003                                         // rotate the quad around the up axis vector, this is made
9004                                         // especially easy by the fact we know the quad is flat,
9005                                         // so we only have to subtract the center position and
9006                                         // measure distance along the right vector, and then
9007                                         // multiply that by the newright vector and add back the
9008                                         // center position
9009                                         // we also need to subtract the old position to undo the
9010                                         // displacement from the center, which we do with a
9011                                         // DotProduct, the subtraction/addition of center is also
9012                                         // optimized into DotProducts here
9013                                         l = DotProduct(right, center);
9014                                         for (i = 0;i < 4;i++)
9015                                         {
9016                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9017                                                 f = DotProduct(right, v1) - l;
9018                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9019                                         }
9020                                 }
9021                         }
9022                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9023                         {
9024 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9025 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9026 //                              rsurface.batchnormal3f_bufferoffset = 0;
9027                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9028                         }
9029                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9030                         {
9031 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9032 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9033 //                              rsurface.batchsvector3f_bufferoffset = 0;
9034 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9035 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9036 //                              rsurface.batchtvector3f_bufferoffset = 0;
9037                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9038                         }
9039                         break;
9040                 case Q3DEFORM_NORMAL:
9041                         // deform the normals to make reflections wavey
9042                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9043                         rsurface.batchnormal3f_vertexbuffer = NULL;
9044                         rsurface.batchnormal3f_bufferoffset = 0;
9045                         for (j = 0;j < batchnumvertices;j++)
9046                         {
9047                                 float vertex[3];
9048                                 float *normal = rsurface.batchnormal3f + 3*j;
9049                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9050                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9051                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9052                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9053                                 VectorNormalize(normal);
9054                         }
9055                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9056                         {
9057 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9058 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9059 //                              rsurface.batchsvector3f_bufferoffset = 0;
9060 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9061 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9062 //                              rsurface.batchtvector3f_bufferoffset = 0;
9063                                 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);
9064                         }
9065                         break;
9066                 case Q3DEFORM_WAVE:
9067                         // deform vertex array to make wavey water and flags and such
9068                         waveparms[0] = deform->waveparms[0];
9069                         waveparms[1] = deform->waveparms[1];
9070                         waveparms[2] = deform->waveparms[2];
9071                         waveparms[3] = deform->waveparms[3];
9072                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9073                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9074                         // this is how a divisor of vertex influence on deformation
9075                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9076                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9077 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9078 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9079 //                      rsurface.batchvertex3f_bufferoffset = 0;
9080 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9081 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9082 //                      rsurface.batchnormal3f_bufferoffset = 0;
9083                         for (j = 0;j < batchnumvertices;j++)
9084                         {
9085                                 // if the wavefunc depends on time, evaluate it per-vertex
9086                                 if (waveparms[3])
9087                                 {
9088                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9089                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9090                                 }
9091                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9092                         }
9093                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9094                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9095                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9096                         {
9097 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9098 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9099 //                              rsurface.batchsvector3f_bufferoffset = 0;
9100 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9101 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9102 //                              rsurface.batchtvector3f_bufferoffset = 0;
9103                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9104                         }
9105                         break;
9106                 case Q3DEFORM_BULGE:
9107                         // deform vertex array to make the surface have moving bulges
9108 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9109 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9110 //                      rsurface.batchvertex3f_bufferoffset = 0;
9111 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9112 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9113 //                      rsurface.batchnormal3f_bufferoffset = 0;
9114                         for (j = 0;j < batchnumvertices;j++)
9115                         {
9116                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9117                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9118                         }
9119                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9120                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9121                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9122                         {
9123 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9124 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9125 //                              rsurface.batchsvector3f_bufferoffset = 0;
9126 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9127 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9128 //                              rsurface.batchtvector3f_bufferoffset = 0;
9129                                 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);
9130                         }
9131                         break;
9132                 case Q3DEFORM_MOVE:
9133                         // deform vertex array
9134                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9135                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9136                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9137                         VectorScale(deform->parms, scale, waveparms);
9138 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9139 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9140 //                      rsurface.batchvertex3f_bufferoffset = 0;
9141                         for (j = 0;j < batchnumvertices;j++)
9142                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9143                         break;
9144                 }
9145         }
9146
9147         // generate texcoords based on the chosen texcoord source
9148         switch(rsurface.texture->tcgen.tcgen)
9149         {
9150         default:
9151         case Q3TCGEN_TEXTURE:
9152                 break;
9153         case Q3TCGEN_LIGHTMAP:
9154 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9155 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9156 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9157                 if (rsurface.batchtexcoordlightmap2f)
9158                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9159                 break;
9160         case Q3TCGEN_VECTOR:
9161 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9162 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9163 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9164                 for (j = 0;j < batchnumvertices;j++)
9165                 {
9166                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9167                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9168                 }
9169                 break;
9170         case Q3TCGEN_ENVIRONMENT:
9171                 // make environment reflections using a spheremap
9172                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9173                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9174                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9175                 for (j = 0;j < batchnumvertices;j++)
9176                 {
9177                         // identical to Q3A's method, but executed in worldspace so
9178                         // carried models can be shiny too
9179
9180                         float viewer[3], d, reflected[3], worldreflected[3];
9181
9182                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9183                         // VectorNormalize(viewer);
9184
9185                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9186
9187                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9188                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9189                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9190                         // note: this is proportinal to viewer, so we can normalize later
9191
9192                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9193                         VectorNormalize(worldreflected);
9194
9195                         // note: this sphere map only uses world x and z!
9196                         // so positive and negative y will LOOK THE SAME.
9197                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9198                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9199                 }
9200                 break;
9201         }
9202         // the only tcmod that needs software vertex processing is turbulent, so
9203         // check for it here and apply the changes if needed
9204         // and we only support that as the first one
9205         // (handling a mixture of turbulent and other tcmods would be problematic
9206         //  without punting it entirely to a software path)
9207         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9208         {
9209                 amplitude = rsurface.texture->tcmods[0].parms[1];
9210                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9211 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9212 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9213 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9214                 for (j = 0;j < batchnumvertices;j++)
9215                 {
9216                         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);
9217                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9218                 }
9219         }
9220
9221         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9222         {
9223                 // convert the modified arrays to vertex structs
9224 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9225 //              rsurface.batchvertexmeshbuffer = NULL;
9226                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9227                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9228                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9229                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9230                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9231                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9232                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9233                 {
9234                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9235                         {
9236                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9237                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9238                         }
9239                 }
9240                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9241                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9242                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9243                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9244                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9245                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9246                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9247                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9248                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9249         }
9250 }
9251
9252 void RSurf_DrawBatch(void)
9253 {
9254         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9255         // through the pipeline, killing it earlier in the pipeline would have
9256         // per-surface overhead rather than per-batch overhead, so it's best to
9257         // reject it here, before it hits glDraw.
9258         if (rsurface.batchnumtriangles == 0)
9259                 return;
9260 #if 0
9261         // batch debugging code
9262         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9263         {
9264                 int i;
9265                 int j;
9266                 int c;
9267                 const int *e;
9268                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9269                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9270                 {
9271                         c = e[i];
9272                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9273                         {
9274                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9275                                 {
9276                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9277                                                 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);
9278                                         break;
9279                                 }
9280                         }
9281                 }
9282         }
9283 #endif
9284         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);
9285 }
9286
9287 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9288 {
9289         // pick the closest matching water plane
9290         int planeindex, vertexindex, bestplaneindex = -1;
9291         float d, bestd;
9292         vec3_t vert;
9293         const float *v;
9294         r_waterstate_waterplane_t *p;
9295         qboolean prepared = false;
9296         bestd = 0;
9297         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9298         {
9299                 if(p->camera_entity != rsurface.texture->camera_entity)
9300                         continue;
9301                 d = 0;
9302                 if(!prepared)
9303                 {
9304                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9305                         prepared = true;
9306                         if(rsurface.batchnumvertices == 0)
9307                                 break;
9308                 }
9309                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9310                 {
9311                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9312                         d += fabs(PlaneDiff(vert, &p->plane));
9313                 }
9314                 if (bestd > d || bestplaneindex < 0)
9315                 {
9316                         bestd = d;
9317                         bestplaneindex = planeindex;
9318                 }
9319         }
9320         return bestplaneindex;
9321         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9322         // this situation though, as it might be better to render single larger
9323         // batches with useless stuff (backface culled for example) than to
9324         // render multiple smaller batches
9325 }
9326
9327 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9328 {
9329         int i;
9330         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9331         rsurface.passcolor4f_vertexbuffer = 0;
9332         rsurface.passcolor4f_bufferoffset = 0;
9333         for (i = 0;i < rsurface.batchnumvertices;i++)
9334                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9335 }
9336
9337 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9338 {
9339         int i;
9340         float f;
9341         const float *v;
9342         const float *c;
9343         float *c2;
9344         if (rsurface.passcolor4f)
9345         {
9346                 // generate color arrays
9347                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9348                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9349                 rsurface.passcolor4f_vertexbuffer = 0;
9350                 rsurface.passcolor4f_bufferoffset = 0;
9351                 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)
9352                 {
9353                         f = RSurf_FogVertex(v);
9354                         c2[0] = c[0] * f;
9355                         c2[1] = c[1] * f;
9356                         c2[2] = c[2] * f;
9357                         c2[3] = c[3];
9358                 }
9359         }
9360         else
9361         {
9362                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9363                 rsurface.passcolor4f_vertexbuffer = 0;
9364                 rsurface.passcolor4f_bufferoffset = 0;
9365                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9366                 {
9367                         f = RSurf_FogVertex(v);
9368                         c2[0] = f;
9369                         c2[1] = f;
9370                         c2[2] = f;
9371                         c2[3] = 1;
9372                 }
9373         }
9374 }
9375
9376 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9377 {
9378         int i;
9379         float f;
9380         const float *v;
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, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9390         {
9391                 f = RSurf_FogVertex(v);
9392                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9393                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9394                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9395                 c2[3] = c[3];
9396         }
9397 }
9398
9399 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9400 {
9401         int i;
9402         const float *c;
9403         float *c2;
9404         if (!rsurface.passcolor4f)
9405                 return;
9406         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9407         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9408         rsurface.passcolor4f_vertexbuffer = 0;
9409         rsurface.passcolor4f_bufferoffset = 0;
9410         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9411         {
9412                 c2[0] = c[0] * r;
9413                 c2[1] = c[1] * g;
9414                 c2[2] = c[2] * b;
9415                 c2[3] = c[3] * a;
9416         }
9417 }
9418
9419 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9420 {
9421         int i;
9422         const float *c;
9423         float *c2;
9424         if (!rsurface.passcolor4f)
9425                 return;
9426         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9427         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9428         rsurface.passcolor4f_vertexbuffer = 0;
9429         rsurface.passcolor4f_bufferoffset = 0;
9430         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9431         {
9432                 c2[0] = c[0] + r_refdef.scene.ambient;
9433                 c2[1] = c[1] + r_refdef.scene.ambient;
9434                 c2[2] = c[2] + r_refdef.scene.ambient;
9435                 c2[3] = c[3];
9436         }
9437 }
9438
9439 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9440 {
9441         // TODO: optimize
9442         rsurface.passcolor4f = NULL;
9443         rsurface.passcolor4f_vertexbuffer = 0;
9444         rsurface.passcolor4f_bufferoffset = 0;
9445         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9446         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9447         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9448         GL_Color(r, g, b, a);
9449         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9450         RSurf_DrawBatch();
9451 }
9452
9453 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9454 {
9455         // TODO: optimize applyfog && applycolor case
9456         // just apply fog if necessary, and tint the fog color array if necessary
9457         rsurface.passcolor4f = NULL;
9458         rsurface.passcolor4f_vertexbuffer = 0;
9459         rsurface.passcolor4f_bufferoffset = 0;
9460         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9461         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9462         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9463         GL_Color(r, g, b, a);
9464         RSurf_DrawBatch();
9465 }
9466
9467 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9468 {
9469         // TODO: optimize
9470         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9471         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9472         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9473         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9474         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9475         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9476         GL_Color(r, g, b, a);
9477         RSurf_DrawBatch();
9478 }
9479
9480 static void RSurf_DrawBatch_GL11_ClampColor(void)
9481 {
9482         int i;
9483         const float *c1;
9484         float *c2;
9485         if (!rsurface.passcolor4f)
9486                 return;
9487         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9488         {
9489                 c2[0] = bound(0.0f, c1[0], 1.0f);
9490                 c2[1] = bound(0.0f, c1[1], 1.0f);
9491                 c2[2] = bound(0.0f, c1[2], 1.0f);
9492                 c2[3] = bound(0.0f, c1[3], 1.0f);
9493         }
9494 }
9495
9496 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9497 {
9498         int i;
9499         float f;
9500         const float *v;
9501         const float *n;
9502         float *c;
9503         //vec3_t eyedir;
9504
9505         // fake shading
9506         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9507         rsurface.passcolor4f_vertexbuffer = 0;
9508         rsurface.passcolor4f_bufferoffset = 0;
9509         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)
9510         {
9511                 f = -DotProduct(r_refdef.view.forward, n);
9512                 f = max(0, f);
9513                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9514                 f *= r_refdef.lightmapintensity;
9515                 Vector4Set(c, f, f, f, 1);
9516         }
9517 }
9518
9519 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9520 {
9521         RSurf_DrawBatch_GL11_ApplyFakeLight();
9522         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9523         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9524         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9525         GL_Color(r, g, b, a);
9526         RSurf_DrawBatch();
9527 }
9528
9529 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9530 {
9531         int i;
9532         float f;
9533         float alpha;
9534         const float *v;
9535         const float *n;
9536         float *c;
9537         vec3_t ambientcolor;
9538         vec3_t diffusecolor;
9539         vec3_t lightdir;
9540         // TODO: optimize
9541         // model lighting
9542         VectorCopy(rsurface.modellight_lightdir, lightdir);
9543         f = 0.5f * r_refdef.lightmapintensity;
9544         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9545         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9546         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9547         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9548         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9549         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9550         alpha = *a;
9551         if (VectorLength2(diffusecolor) > 0)
9552         {
9553                 // q3-style directional shading
9554                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9555                 rsurface.passcolor4f_vertexbuffer = 0;
9556                 rsurface.passcolor4f_bufferoffset = 0;
9557                 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)
9558                 {
9559                         if ((f = DotProduct(n, lightdir)) > 0)
9560                                 VectorMA(ambientcolor, f, diffusecolor, c);
9561                         else
9562                                 VectorCopy(ambientcolor, c);
9563                         c[3] = alpha;
9564                 }
9565                 *r = 1;
9566                 *g = 1;
9567                 *b = 1;
9568                 *a = 1;
9569                 *applycolor = false;
9570         }
9571         else
9572         {
9573                 *r = ambientcolor[0];
9574                 *g = ambientcolor[1];
9575                 *b = ambientcolor[2];
9576                 rsurface.passcolor4f = NULL;
9577                 rsurface.passcolor4f_vertexbuffer = 0;
9578                 rsurface.passcolor4f_bufferoffset = 0;
9579         }
9580 }
9581
9582 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9583 {
9584         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9585         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9586         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9587         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9588         GL_Color(r, g, b, a);
9589         RSurf_DrawBatch();
9590 }
9591
9592 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9593 {
9594         int i;
9595         float f;
9596         const float *v;
9597         float *c;
9598
9599         // fake shading
9600         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9601         rsurface.passcolor4f_vertexbuffer = 0;
9602         rsurface.passcolor4f_bufferoffset = 0;
9603
9604         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9605         {
9606                 f = 1 - RSurf_FogVertex(v);
9607                 c[0] = r;
9608                 c[1] = g;
9609                 c[2] = b;
9610                 c[3] = f * a;
9611         }
9612 }
9613
9614 void RSurf_SetupDepthAndCulling(void)
9615 {
9616         // submodels are biased to avoid z-fighting with world surfaces that they
9617         // may be exactly overlapping (avoids z-fighting artifacts on certain
9618         // doors and things in Quake maps)
9619         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9620         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9621         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9622         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9623 }
9624
9625 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9626 {
9627         // transparent sky would be ridiculous
9628         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9629                 return;
9630         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9631         skyrenderlater = true;
9632         RSurf_SetupDepthAndCulling();
9633         GL_DepthMask(true);
9634         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9635         // skymasking on them, and Quake3 never did sky masking (unlike
9636         // software Quake and software Quake2), so disable the sky masking
9637         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9638         // and skymasking also looks very bad when noclipping outside the
9639         // level, so don't use it then either.
9640         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9641         {
9642                 R_Mesh_ResetTextureState();
9643                 if (skyrendermasked)
9644                 {
9645                         R_SetupShader_DepthOrShadow(false);
9646                         // depth-only (masking)
9647                         GL_ColorMask(0,0,0,0);
9648                         // just to make sure that braindead drivers don't draw
9649                         // anything despite that colormask...
9650                         GL_BlendFunc(GL_ZERO, GL_ONE);
9651                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9652                         if (rsurface.batchvertex3fbuffer)
9653                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9654                         else
9655                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9656                 }
9657                 else
9658                 {
9659                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9660                         // fog sky
9661                         GL_BlendFunc(GL_ONE, GL_ZERO);
9662                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9663                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9664                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9665                 }
9666                 RSurf_DrawBatch();
9667                 if (skyrendermasked)
9668                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9669         }
9670         R_Mesh_ResetTextureState();
9671         GL_Color(1, 1, 1, 1);
9672 }
9673
9674 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9675 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9676 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9677 {
9678         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9679                 return;
9680         if (prepass)
9681         {
9682                 // render screenspace normalmap to texture
9683                 GL_DepthMask(true);
9684                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9685                 RSurf_DrawBatch();
9686         }
9687
9688         // bind lightmap texture
9689
9690         // water/refraction/reflection/camera surfaces have to be handled specially
9691         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9692         {
9693                 int start, end, startplaneindex;
9694                 for (start = 0;start < texturenumsurfaces;start = end)
9695                 {
9696                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9697                         if(startplaneindex < 0)
9698                         {
9699                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9700                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9701                                 end = start + 1;
9702                                 continue;
9703                         }
9704                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9705                                 ;
9706                         // now that we have a batch using the same planeindex, render it
9707                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9708                         {
9709                                 // render water or distortion background
9710                                 GL_DepthMask(true);
9711                                 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);
9712                                 RSurf_DrawBatch();
9713                                 // blend surface on top
9714                                 GL_DepthMask(false);
9715                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9716                                 RSurf_DrawBatch();
9717                         }
9718                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9719                         {
9720                                 // render surface with reflection texture as input
9721                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9722                                 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);
9723                                 RSurf_DrawBatch();
9724                         }
9725                 }
9726                 return;
9727         }
9728
9729         // render surface batch normally
9730         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9731         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);
9732         RSurf_DrawBatch();
9733 }
9734
9735 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9736 {
9737         // OpenGL 1.3 path - anything not completely ancient
9738         qboolean applycolor;
9739         qboolean applyfog;
9740         int layerindex;
9741         const texturelayer_t *layer;
9742         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);
9743         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9744
9745         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9746         {
9747                 vec4_t layercolor;
9748                 int layertexrgbscale;
9749                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9750                 {
9751                         if (layerindex == 0)
9752                                 GL_AlphaTest(true);
9753                         else
9754                         {
9755                                 GL_AlphaTest(false);
9756                                 GL_DepthFunc(GL_EQUAL);
9757                         }
9758                 }
9759                 GL_DepthMask(layer->depthmask && writedepth);
9760                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9761                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9762                 {
9763                         layertexrgbscale = 4;
9764                         VectorScale(layer->color, 0.25f, layercolor);
9765                 }
9766                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9767                 {
9768                         layertexrgbscale = 2;
9769                         VectorScale(layer->color, 0.5f, layercolor);
9770                 }
9771                 else
9772                 {
9773                         layertexrgbscale = 1;
9774                         VectorScale(layer->color, 1.0f, layercolor);
9775                 }
9776                 layercolor[3] = layer->color[3];
9777                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9778                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9779                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9780                 switch (layer->type)
9781                 {
9782                 case TEXTURELAYERTYPE_LITTEXTURE:
9783                         // single-pass lightmapped texture with 2x rgbscale
9784                         R_Mesh_TexBind(0, r_texture_white);
9785                         R_Mesh_TexMatrix(0, NULL);
9786                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9787                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9788                         R_Mesh_TexBind(1, layer->texture);
9789                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9790                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9791                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9792                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9793                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9794                         else if (FAKELIGHT_ENABLED)
9795                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9796                         else if (rsurface.uselightmaptexture)
9797                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9798                         else
9799                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9800                         break;
9801                 case TEXTURELAYERTYPE_TEXTURE:
9802                         // singletexture unlit texture with transparency support
9803                         R_Mesh_TexBind(0, layer->texture);
9804                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9805                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9806                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9807                         R_Mesh_TexBind(1, 0);
9808                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9809                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9810                         break;
9811                 case TEXTURELAYERTYPE_FOG:
9812                         // singletexture fogging
9813                         if (layer->texture)
9814                         {
9815                                 R_Mesh_TexBind(0, layer->texture);
9816                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9817                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9818                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9819                         }
9820                         else
9821                         {
9822                                 R_Mesh_TexBind(0, 0);
9823                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9824                         }
9825                         R_Mesh_TexBind(1, 0);
9826                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9827                         // generate a color array for the fog pass
9828                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9829                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9830                         RSurf_DrawBatch();
9831                         break;
9832                 default:
9833                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9834                 }
9835         }
9836         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9837         {
9838                 GL_DepthFunc(GL_LEQUAL);
9839                 GL_AlphaTest(false);
9840         }
9841 }
9842
9843 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9844 {
9845         // OpenGL 1.1 - crusty old voodoo path
9846         qboolean applyfog;
9847         int layerindex;
9848         const texturelayer_t *layer;
9849         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);
9850         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9851
9852         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9853         {
9854                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9855                 {
9856                         if (layerindex == 0)
9857                                 GL_AlphaTest(true);
9858                         else
9859                         {
9860                                 GL_AlphaTest(false);
9861                                 GL_DepthFunc(GL_EQUAL);
9862                         }
9863                 }
9864                 GL_DepthMask(layer->depthmask && writedepth);
9865                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9866                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9867                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9868                 switch (layer->type)
9869                 {
9870                 case TEXTURELAYERTYPE_LITTEXTURE:
9871                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9872                         {
9873                                 // two-pass lit texture with 2x rgbscale
9874                                 // first the lightmap pass
9875                                 R_Mesh_TexBind(0, r_texture_white);
9876                                 R_Mesh_TexMatrix(0, NULL);
9877                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9878                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9879                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9880                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9881                                 else if (FAKELIGHT_ENABLED)
9882                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9883                                 else if (rsurface.uselightmaptexture)
9884                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9885                                 else
9886                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9887                                 // then apply the texture to it
9888                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
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] * 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);
9894                         }
9895                         else
9896                         {
9897                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9898                                 R_Mesh_TexBind(0, layer->texture);
9899                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9900                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9901                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9902                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9903                                         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);
9904                                 else
9905                                         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);
9906                         }
9907                         break;
9908                 case TEXTURELAYERTYPE_TEXTURE:
9909                         // singletexture unlit texture with transparency support
9910                         R_Mesh_TexBind(0, layer->texture);
9911                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9912                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9913                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9914                         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);
9915                         break;
9916                 case TEXTURELAYERTYPE_FOG:
9917                         // singletexture fogging
9918                         if (layer->texture)
9919                         {
9920                                 R_Mesh_TexBind(0, layer->texture);
9921                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9922                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9923                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9924                         }
9925                         else
9926                         {
9927                                 R_Mesh_TexBind(0, 0);
9928                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9929                         }
9930                         // generate a color array for the fog pass
9931                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9932                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9933                         RSurf_DrawBatch();
9934                         break;
9935                 default:
9936                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9937                 }
9938         }
9939         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9940         {
9941                 GL_DepthFunc(GL_LEQUAL);
9942                 GL_AlphaTest(false);
9943         }
9944 }
9945
9946 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9947 {
9948         int vi;
9949         int j;
9950         r_vertexgeneric_t *batchvertex;
9951         float c[4];
9952
9953 //      R_Mesh_ResetTextureState();
9954         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9955
9956         if(rsurface.texture && rsurface.texture->currentskinframe)
9957         {
9958                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9959                 c[3] *= rsurface.texture->currentalpha;
9960         }
9961         else
9962         {
9963                 c[0] = 1;
9964                 c[1] = 0;
9965                 c[2] = 1;
9966                 c[3] = 1;
9967         }
9968
9969         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9970         {
9971                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9972                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9973                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9974         }
9975
9976         // brighten it up (as texture value 127 means "unlit")
9977         c[0] *= 2 * r_refdef.view.colorscale;
9978         c[1] *= 2 * r_refdef.view.colorscale;
9979         c[2] *= 2 * r_refdef.view.colorscale;
9980
9981         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9982                 c[3] *= r_wateralpha.value;
9983
9984         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9985         {
9986                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9987                 GL_DepthMask(false);
9988         }
9989         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9990         {
9991                 GL_BlendFunc(GL_ONE, GL_ONE);
9992                 GL_DepthMask(false);
9993         }
9994         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9995         {
9996                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9997                 GL_DepthMask(false);
9998         }
9999         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10000         {
10001                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10002                 GL_DepthMask(false);
10003         }
10004         else
10005         {
10006                 GL_BlendFunc(GL_ONE, GL_ZERO);
10007                 GL_DepthMask(writedepth);
10008         }
10009
10010         if (r_showsurfaces.integer == 3)
10011         {
10012                 rsurface.passcolor4f = NULL;
10013
10014                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10015                 {
10016                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10017
10018                         rsurface.passcolor4f = NULL;
10019                         rsurface.passcolor4f_vertexbuffer = 0;
10020                         rsurface.passcolor4f_bufferoffset = 0;
10021                 }
10022                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10023                 {
10024                         qboolean applycolor = true;
10025                         float one = 1.0;
10026
10027                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10028
10029                         r_refdef.lightmapintensity = 1;
10030                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10031                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10032                 }
10033                 else if (FAKELIGHT_ENABLED)
10034                 {
10035                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10036
10037                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10038                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10039                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10040                 }
10041                 else
10042                 {
10043                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10044
10045                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10046                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10047                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10048                 }
10049
10050                 if(!rsurface.passcolor4f)
10051                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10052
10053                 RSurf_DrawBatch_GL11_ApplyAmbient();
10054                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10055                 if(r_refdef.fogenabled)
10056                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10057                 RSurf_DrawBatch_GL11_ClampColor();
10058
10059                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10060                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10061                 RSurf_DrawBatch();
10062         }
10063         else if (!r_refdef.view.showdebug)
10064         {
10065                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10066                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10067                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10068                 {
10069                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10070                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10071                 }
10072                 R_Mesh_PrepareVertices_Generic_Unlock();
10073                 RSurf_DrawBatch();
10074         }
10075         else if (r_showsurfaces.integer == 4)
10076         {
10077                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10078                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10079                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10080                 {
10081                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10082                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10083                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10084                 }
10085                 R_Mesh_PrepareVertices_Generic_Unlock();
10086                 RSurf_DrawBatch();
10087         }
10088         else if (r_showsurfaces.integer == 2)
10089         {
10090                 const int *e;
10091                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10092                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10093                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10094                 {
10095                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10096                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10097                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10098                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10099                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10100                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10101                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10102                 }
10103                 R_Mesh_PrepareVertices_Generic_Unlock();
10104                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10105         }
10106         else
10107         {
10108                 int texturesurfaceindex;
10109                 int k;
10110                 const msurface_t *surface;
10111                 float surfacecolor4f[4];
10112                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10113                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10114                 vi = 0;
10115                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10116                 {
10117                         surface = texturesurfacelist[texturesurfaceindex];
10118                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10119                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10120                         for (j = 0;j < surface->num_vertices;j++)
10121                         {
10122                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10123                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10124                                 vi++;
10125                         }
10126                 }
10127                 R_Mesh_PrepareVertices_Generic_Unlock();
10128                 RSurf_DrawBatch();
10129         }
10130 }
10131
10132 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10133 {
10134         CHECKGLERROR
10135         RSurf_SetupDepthAndCulling();
10136         if (r_showsurfaces.integer)
10137         {
10138                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10139                 return;
10140         }
10141         switch (vid.renderpath)
10142         {
10143         case RENDERPATH_GL20:
10144         case RENDERPATH_D3D9:
10145         case RENDERPATH_D3D10:
10146         case RENDERPATH_D3D11:
10147         case RENDERPATH_SOFT:
10148         case RENDERPATH_GLES2:
10149                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10150                 break;
10151         case RENDERPATH_GL13:
10152         case RENDERPATH_GLES1:
10153                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10154                 break;
10155         case RENDERPATH_GL11:
10156                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10157                 break;
10158         }
10159         CHECKGLERROR
10160 }
10161
10162 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10163 {
10164         CHECKGLERROR
10165         RSurf_SetupDepthAndCulling();
10166         if (r_showsurfaces.integer)
10167         {
10168                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10169                 return;
10170         }
10171         switch (vid.renderpath)
10172         {
10173         case RENDERPATH_GL20:
10174         case RENDERPATH_D3D9:
10175         case RENDERPATH_D3D10:
10176         case RENDERPATH_D3D11:
10177         case RENDERPATH_SOFT:
10178         case RENDERPATH_GLES2:
10179                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10180                 break;
10181         case RENDERPATH_GL13:
10182         case RENDERPATH_GLES1:
10183                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10184                 break;
10185         case RENDERPATH_GL11:
10186                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10187                 break;
10188         }
10189         CHECKGLERROR
10190 }
10191
10192 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10193 {
10194         int i, j;
10195         int texturenumsurfaces, endsurface;
10196         texture_t *texture;
10197         const msurface_t *surface;
10198         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10199
10200         // if the model is static it doesn't matter what value we give for
10201         // wantnormals and wanttangents, so this logic uses only rules applicable
10202         // to a model, knowing that they are meaningless otherwise
10203         if (ent == r_refdef.scene.worldentity)
10204                 RSurf_ActiveWorldEntity();
10205         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10206                 RSurf_ActiveModelEntity(ent, false, false, false);
10207         else
10208         {
10209                 switch (vid.renderpath)
10210                 {
10211                 case RENDERPATH_GL20:
10212                 case RENDERPATH_D3D9:
10213                 case RENDERPATH_D3D10:
10214                 case RENDERPATH_D3D11:
10215                 case RENDERPATH_SOFT:
10216                 case RENDERPATH_GLES2:
10217                         RSurf_ActiveModelEntity(ent, true, true, false);
10218                         break;
10219                 case RENDERPATH_GL11:
10220                 case RENDERPATH_GL13:
10221                 case RENDERPATH_GLES1:
10222                         RSurf_ActiveModelEntity(ent, true, false, false);
10223                         break;
10224                 }
10225         }
10226
10227         if (r_transparentdepthmasking.integer)
10228         {
10229                 qboolean setup = false;
10230                 for (i = 0;i < numsurfaces;i = j)
10231                 {
10232                         j = i + 1;
10233                         surface = rsurface.modelsurfaces + surfacelist[i];
10234                         texture = surface->texture;
10235                         rsurface.texture = R_GetCurrentTexture(texture);
10236                         rsurface.lightmaptexture = NULL;
10237                         rsurface.deluxemaptexture = NULL;
10238                         rsurface.uselightmaptexture = false;
10239                         // scan ahead until we find a different texture
10240                         endsurface = min(i + 1024, numsurfaces);
10241                         texturenumsurfaces = 0;
10242                         texturesurfacelist[texturenumsurfaces++] = surface;
10243                         for (;j < endsurface;j++)
10244                         {
10245                                 surface = rsurface.modelsurfaces + surfacelist[j];
10246                                 if (texture != surface->texture)
10247                                         break;
10248                                 texturesurfacelist[texturenumsurfaces++] = surface;
10249                         }
10250                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10251                                 continue;
10252                         // render the range of surfaces as depth
10253                         if (!setup)
10254                         {
10255                                 setup = true;
10256                                 GL_ColorMask(0,0,0,0);
10257                                 GL_Color(1,1,1,1);
10258                                 GL_DepthTest(true);
10259                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10260                                 GL_DepthMask(true);
10261 //                              R_Mesh_ResetTextureState();
10262                                 R_SetupShader_DepthOrShadow(false);
10263                         }
10264                         RSurf_SetupDepthAndCulling();
10265                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10266                         if (rsurface.batchvertex3fbuffer)
10267                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10268                         else
10269                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10270                         RSurf_DrawBatch();
10271                 }
10272                 if (setup)
10273                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10274         }
10275
10276         for (i = 0;i < numsurfaces;i = j)
10277         {
10278                 j = i + 1;
10279                 surface = rsurface.modelsurfaces + surfacelist[i];
10280                 texture = surface->texture;
10281                 rsurface.texture = R_GetCurrentTexture(texture);
10282                 // scan ahead until we find a different texture
10283                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10284                 texturenumsurfaces = 0;
10285                 texturesurfacelist[texturenumsurfaces++] = surface;
10286                 if(FAKELIGHT_ENABLED)
10287                 {
10288                         rsurface.lightmaptexture = NULL;
10289                         rsurface.deluxemaptexture = NULL;
10290                         rsurface.uselightmaptexture = false;
10291                         for (;j < endsurface;j++)
10292                         {
10293                                 surface = rsurface.modelsurfaces + surfacelist[j];
10294                                 if (texture != surface->texture)
10295                                         break;
10296                                 texturesurfacelist[texturenumsurfaces++] = surface;
10297                         }
10298                 }
10299                 else
10300                 {
10301                         rsurface.lightmaptexture = surface->lightmaptexture;
10302                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10303                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10304                         for (;j < endsurface;j++)
10305                         {
10306                                 surface = rsurface.modelsurfaces + surfacelist[j];
10307                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10308                                         break;
10309                                 texturesurfacelist[texturenumsurfaces++] = surface;
10310                         }
10311                 }
10312                 // render the range of surfaces
10313                 if (ent == r_refdef.scene.worldentity)
10314                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10315                 else
10316                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10317         }
10318         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10319 }
10320
10321 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10322 {
10323         // transparent surfaces get pushed off into the transparent queue
10324         int surfacelistindex;
10325         const msurface_t *surface;
10326         vec3_t tempcenter, center;
10327         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10328         {
10329                 surface = texturesurfacelist[surfacelistindex];
10330                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10331                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10332                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10333                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10334                 if (queueentity->transparent_offset) // transparent offset
10335                 {
10336                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10337                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10338                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10339                 }
10340                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10341         }
10342 }
10343
10344 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10345 {
10346         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10347                 return;
10348         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10349                 return;
10350         RSurf_SetupDepthAndCulling();
10351         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10352         if (rsurface.batchvertex3fbuffer)
10353                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10354         else
10355                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10356         RSurf_DrawBatch();
10357 }
10358
10359 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10360 {
10361         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10362         CHECKGLERROR
10363         if (depthonly)
10364                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10365         else if (prepass)
10366         {
10367                 if (!rsurface.texture->currentnumlayers)
10368                         return;
10369                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10370                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10371                 else
10372                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10373         }
10374         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10375                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10376         else if (!rsurface.texture->currentnumlayers)
10377                 return;
10378         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10379         {
10380                 // in the deferred case, transparent surfaces were queued during prepass
10381                 if (!r_shadow_usingdeferredprepass)
10382                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10383         }
10384         else
10385         {
10386                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10387                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10388         }
10389         CHECKGLERROR
10390 }
10391
10392 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10393 {
10394         int i, j;
10395         texture_t *texture;
10396         R_FrameData_SetMark();
10397         // break the surface list down into batches by texture and use of lightmapping
10398         for (i = 0;i < numsurfaces;i = j)
10399         {
10400                 j = i + 1;
10401                 // texture is the base texture pointer, rsurface.texture is the
10402                 // current frame/skin the texture is directing us to use (for example
10403                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10404                 // use skin 1 instead)
10405                 texture = surfacelist[i]->texture;
10406                 rsurface.texture = R_GetCurrentTexture(texture);
10407                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10408                 {
10409                         // if this texture is not the kind we want, skip ahead to the next one
10410                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10411                                 ;
10412                         continue;
10413                 }
10414                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10415                 {
10416                         rsurface.lightmaptexture = NULL;
10417                         rsurface.deluxemaptexture = NULL;
10418                         rsurface.uselightmaptexture = false;
10419                         // simply scan ahead until we find a different texture or lightmap state
10420                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10421                                 ;
10422                 }
10423                 else
10424                 {
10425                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10426                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10427                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10428                         // simply scan ahead until we find a different texture or lightmap state
10429                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10430                                 ;
10431                 }
10432                 // render the range of surfaces
10433                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10434         }
10435         R_FrameData_ReturnToMark();
10436 }
10437
10438 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10439 {
10440         CHECKGLERROR
10441         if (depthonly)
10442                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10443         else if (prepass)
10444         {
10445                 if (!rsurface.texture->currentnumlayers)
10446                         return;
10447                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10448                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10449                 else
10450                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10451         }
10452         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10453                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10454         else if (!rsurface.texture->currentnumlayers)
10455                 return;
10456         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10457         {
10458                 // in the deferred case, transparent surfaces were queued during prepass
10459                 if (!r_shadow_usingdeferredprepass)
10460                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10461         }
10462         else
10463         {
10464                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10465                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10466         }
10467         CHECKGLERROR
10468 }
10469
10470 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10471 {
10472         int i, j;
10473         texture_t *texture;
10474         R_FrameData_SetMark();
10475         // break the surface list down into batches by texture and use of lightmapping
10476         for (i = 0;i < numsurfaces;i = j)
10477         {
10478                 j = i + 1;
10479                 // texture is the base texture pointer, rsurface.texture is the
10480                 // current frame/skin the texture is directing us to use (for example
10481                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10482                 // use skin 1 instead)
10483                 texture = surfacelist[i]->texture;
10484                 rsurface.texture = R_GetCurrentTexture(texture);
10485                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10486                 {
10487                         // if this texture is not the kind we want, skip ahead to the next one
10488                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10489                                 ;
10490                         continue;
10491                 }
10492                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10493                 {
10494                         rsurface.lightmaptexture = NULL;
10495                         rsurface.deluxemaptexture = NULL;
10496                         rsurface.uselightmaptexture = false;
10497                         // simply scan ahead until we find a different texture or lightmap state
10498                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10499                                 ;
10500                 }
10501                 else
10502                 {
10503                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10504                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10505                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10506                         // simply scan ahead until we find a different texture or lightmap state
10507                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10508                                 ;
10509                 }
10510                 // render the range of surfaces
10511                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10512         }
10513         R_FrameData_ReturnToMark();
10514 }
10515
10516 float locboxvertex3f[6*4*3] =
10517 {
10518         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10519         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10520         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10521         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10522         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10523         1,0,0, 0,0,0, 0,1,0, 1,1,0
10524 };
10525
10526 unsigned short locboxelements[6*2*3] =
10527 {
10528          0, 1, 2, 0, 2, 3,
10529          4, 5, 6, 4, 6, 7,
10530          8, 9,10, 8,10,11,
10531         12,13,14, 12,14,15,
10532         16,17,18, 16,18,19,
10533         20,21,22, 20,22,23
10534 };
10535
10536 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10537 {
10538         int i, j;
10539         cl_locnode_t *loc = (cl_locnode_t *)ent;
10540         vec3_t mins, size;
10541         float vertex3f[6*4*3];
10542         CHECKGLERROR
10543         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10544         GL_DepthMask(false);
10545         GL_DepthRange(0, 1);
10546         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10547         GL_DepthTest(true);
10548         GL_CullFace(GL_NONE);
10549         R_EntityMatrix(&identitymatrix);
10550
10551 //      R_Mesh_ResetTextureState();
10552
10553         i = surfacelist[0];
10554         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10555                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10556                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10557                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10558
10559         if (VectorCompare(loc->mins, loc->maxs))
10560         {
10561                 VectorSet(size, 2, 2, 2);
10562                 VectorMA(loc->mins, -0.5f, size, mins);
10563         }
10564         else
10565         {
10566                 VectorCopy(loc->mins, mins);
10567                 VectorSubtract(loc->maxs, loc->mins, size);
10568         }
10569
10570         for (i = 0;i < 6*4*3;)
10571                 for (j = 0;j < 3;j++, i++)
10572                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10573
10574         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10575         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10576         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10577 }
10578
10579 void R_DrawLocs(void)
10580 {
10581         int index;
10582         cl_locnode_t *loc, *nearestloc;
10583         vec3_t center;
10584         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10585         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10586         {
10587                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10588                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10589         }
10590 }
10591
10592 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10593 {
10594         if (decalsystem->decals)
10595                 Mem_Free(decalsystem->decals);
10596         memset(decalsystem, 0, sizeof(*decalsystem));
10597 }
10598
10599 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)
10600 {
10601         tridecal_t *decal;
10602         tridecal_t *decals;
10603         int i;
10604
10605         // expand or initialize the system
10606         if (decalsystem->maxdecals <= decalsystem->numdecals)
10607         {
10608                 decalsystem_t old = *decalsystem;
10609                 qboolean useshortelements;
10610                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10611                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10612                 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)));
10613                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10614                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10615                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10616                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10617                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10618                 if (decalsystem->numdecals)
10619                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10620                 if (old.decals)
10621                         Mem_Free(old.decals);
10622                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10623                         decalsystem->element3i[i] = i;
10624                 if (useshortelements)
10625                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10626                                 decalsystem->element3s[i] = i;
10627         }
10628
10629         // grab a decal and search for another free slot for the next one
10630         decals = decalsystem->decals;
10631         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10632         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10633                 ;
10634         decalsystem->freedecal = i;
10635         if (decalsystem->numdecals <= i)
10636                 decalsystem->numdecals = i + 1;
10637
10638         // initialize the decal
10639         decal->lived = 0;
10640         decal->triangleindex = triangleindex;
10641         decal->surfaceindex = surfaceindex;
10642         decal->decalsequence = decalsequence;
10643         decal->color4f[0][0] = c0[0];
10644         decal->color4f[0][1] = c0[1];
10645         decal->color4f[0][2] = c0[2];
10646         decal->color4f[0][3] = 1;
10647         decal->color4f[1][0] = c1[0];
10648         decal->color4f[1][1] = c1[1];
10649         decal->color4f[1][2] = c1[2];
10650         decal->color4f[1][3] = 1;
10651         decal->color4f[2][0] = c2[0];
10652         decal->color4f[2][1] = c2[1];
10653         decal->color4f[2][2] = c2[2];
10654         decal->color4f[2][3] = 1;
10655         decal->vertex3f[0][0] = v0[0];
10656         decal->vertex3f[0][1] = v0[1];
10657         decal->vertex3f[0][2] = v0[2];
10658         decal->vertex3f[1][0] = v1[0];
10659         decal->vertex3f[1][1] = v1[1];
10660         decal->vertex3f[1][2] = v1[2];
10661         decal->vertex3f[2][0] = v2[0];
10662         decal->vertex3f[2][1] = v2[1];
10663         decal->vertex3f[2][2] = v2[2];
10664         decal->texcoord2f[0][0] = t0[0];
10665         decal->texcoord2f[0][1] = t0[1];
10666         decal->texcoord2f[1][0] = t1[0];
10667         decal->texcoord2f[1][1] = t1[1];
10668         decal->texcoord2f[2][0] = t2[0];
10669         decal->texcoord2f[2][1] = t2[1];
10670         TriangleNormal(v0, v1, v2, decal->plane);
10671         VectorNormalize(decal->plane);
10672         decal->plane[3] = DotProduct(v0, decal->plane);
10673 }
10674
10675 extern cvar_t cl_decals_bias;
10676 extern cvar_t cl_decals_models;
10677 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10678 // baseparms, parms, temps
10679 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)
10680 {
10681         int cornerindex;
10682         int index;
10683         float v[9][3];
10684         const float *vertex3f;
10685         const float *normal3f;
10686         int numpoints;
10687         float points[2][9][3];
10688         float temp[3];
10689         float tc[9][2];
10690         float f;
10691         float c[9][4];
10692         const int *e;
10693
10694         e = rsurface.modelelement3i + 3*triangleindex;
10695
10696         vertex3f = rsurface.modelvertex3f;
10697         normal3f = rsurface.modelnormal3f;
10698
10699         if (normal3f)
10700         {
10701                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10702                 {
10703                         index = 3*e[cornerindex];
10704                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10705                 }
10706         }
10707         else
10708         {
10709                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10710                 {
10711                         index = 3*e[cornerindex];
10712                         VectorCopy(vertex3f + index, v[cornerindex]);
10713                 }
10714         }
10715
10716         // cull backfaces
10717         //TriangleNormal(v[0], v[1], v[2], normal);
10718         //if (DotProduct(normal, localnormal) < 0.0f)
10719         //      continue;
10720         // clip by each of the box planes formed from the projection matrix
10721         // if anything survives, we emit the decal
10722         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]);
10723         if (numpoints < 3)
10724                 return;
10725         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]);
10726         if (numpoints < 3)
10727                 return;
10728         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]);
10729         if (numpoints < 3)
10730                 return;
10731         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]);
10732         if (numpoints < 3)
10733                 return;
10734         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]);
10735         if (numpoints < 3)
10736                 return;
10737         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]);
10738         if (numpoints < 3)
10739                 return;
10740         // some part of the triangle survived, so we have to accept it...
10741         if (dynamic)
10742         {
10743                 // dynamic always uses the original triangle
10744                 numpoints = 3;
10745                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10746                 {
10747                         index = 3*e[cornerindex];
10748                         VectorCopy(vertex3f + index, v[cornerindex]);
10749                 }
10750         }
10751         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10752         {
10753                 // convert vertex positions to texcoords
10754                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10755                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10756                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10757                 // calculate distance fade from the projection origin
10758                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10759                 f = bound(0.0f, f, 1.0f);
10760                 c[cornerindex][0] = r * f;
10761                 c[cornerindex][1] = g * f;
10762                 c[cornerindex][2] = b * f;
10763                 c[cornerindex][3] = 1.0f;
10764                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10765         }
10766         if (dynamic)
10767                 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);
10768         else
10769                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10770                         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);
10771 }
10772 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)
10773 {
10774         matrix4x4_t projection;
10775         decalsystem_t *decalsystem;
10776         qboolean dynamic;
10777         dp_model_t *model;
10778         const msurface_t *surface;
10779         const msurface_t *surfaces;
10780         const int *surfacelist;
10781         const texture_t *texture;
10782         int numtriangles;
10783         int numsurfacelist;
10784         int surfacelistindex;
10785         int surfaceindex;
10786         int triangleindex;
10787         float localorigin[3];
10788         float localnormal[3];
10789         float localmins[3];
10790         float localmaxs[3];
10791         float localsize;
10792         //float normal[3];
10793         float planes[6][4];
10794         float angles[3];
10795         bih_t *bih;
10796         int bih_triangles_count;
10797         int bih_triangles[256];
10798         int bih_surfaces[256];
10799
10800         decalsystem = &ent->decalsystem;
10801         model = ent->model;
10802         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10803         {
10804                 R_DecalSystem_Reset(&ent->decalsystem);
10805                 return;
10806         }
10807
10808         if (!model->brush.data_leafs && !cl_decals_models.integer)
10809         {
10810                 if (decalsystem->model)
10811                         R_DecalSystem_Reset(decalsystem);
10812                 return;
10813         }
10814
10815         if (decalsystem->model != model)
10816                 R_DecalSystem_Reset(decalsystem);
10817         decalsystem->model = model;
10818
10819         RSurf_ActiveModelEntity(ent, true, false, false);
10820
10821         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10822         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10823         VectorNormalize(localnormal);
10824         localsize = worldsize*rsurface.inversematrixscale;
10825         localmins[0] = localorigin[0] - localsize;
10826         localmins[1] = localorigin[1] - localsize;
10827         localmins[2] = localorigin[2] - localsize;
10828         localmaxs[0] = localorigin[0] + localsize;
10829         localmaxs[1] = localorigin[1] + localsize;
10830         localmaxs[2] = localorigin[2] + localsize;
10831
10832         //VectorCopy(localnormal, planes[4]);
10833         //VectorVectors(planes[4], planes[2], planes[0]);
10834         AnglesFromVectors(angles, localnormal, NULL, false);
10835         AngleVectors(angles, planes[0], planes[2], planes[4]);
10836         VectorNegate(planes[0], planes[1]);
10837         VectorNegate(planes[2], planes[3]);
10838         VectorNegate(planes[4], planes[5]);
10839         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10840         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10841         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10842         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10843         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10844         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10845
10846 #if 1
10847 // works
10848 {
10849         matrix4x4_t forwardprojection;
10850         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10851         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10852 }
10853 #else
10854 // broken
10855 {
10856         float projectionvector[4][3];
10857         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10858         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10859         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10860         projectionvector[0][0] = planes[0][0] * ilocalsize;
10861         projectionvector[0][1] = planes[1][0] * ilocalsize;
10862         projectionvector[0][2] = planes[2][0] * ilocalsize;
10863         projectionvector[1][0] = planes[0][1] * ilocalsize;
10864         projectionvector[1][1] = planes[1][1] * ilocalsize;
10865         projectionvector[1][2] = planes[2][1] * ilocalsize;
10866         projectionvector[2][0] = planes[0][2] * ilocalsize;
10867         projectionvector[2][1] = planes[1][2] * ilocalsize;
10868         projectionvector[2][2] = planes[2][2] * ilocalsize;
10869         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10870         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10871         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10872         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10873 }
10874 #endif
10875
10876         dynamic = model->surfmesh.isanimated;
10877         numsurfacelist = model->nummodelsurfaces;
10878         surfacelist = model->sortedmodelsurfaces;
10879         surfaces = model->data_surfaces;
10880
10881         bih = NULL;
10882         bih_triangles_count = -1;
10883         if(!dynamic)
10884         {
10885                 if(model->render_bih.numleafs)
10886                         bih = &model->render_bih;
10887                 else if(model->collision_bih.numleafs)
10888                         bih = &model->collision_bih;
10889         }
10890         if(bih)
10891                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10892         if(bih_triangles_count == 0)
10893                 return;
10894         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10895                 return;
10896         if(bih_triangles_count > 0)
10897         {
10898                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10899                 {
10900                         surfaceindex = bih_surfaces[triangleindex];
10901                         surface = surfaces + surfaceindex;
10902                         texture = surface->texture;
10903                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10904                                 continue;
10905                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10906                                 continue;
10907                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10908                 }
10909         }
10910         else
10911         {
10912                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10913                 {
10914                         surfaceindex = surfacelist[surfacelistindex];
10915                         surface = surfaces + surfaceindex;
10916                         // check cull box first because it rejects more than any other check
10917                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10918                                 continue;
10919                         // skip transparent surfaces
10920                         texture = surface->texture;
10921                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10922                                 continue;
10923                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10924                                 continue;
10925                         numtriangles = surface->num_triangles;
10926                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10927                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10928                 }
10929         }
10930 }
10931
10932 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10933 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)
10934 {
10935         int renderentityindex;
10936         float worldmins[3];
10937         float worldmaxs[3];
10938         entity_render_t *ent;
10939
10940         if (!cl_decals_newsystem.integer)
10941                 return;
10942
10943         worldmins[0] = worldorigin[0] - worldsize;
10944         worldmins[1] = worldorigin[1] - worldsize;
10945         worldmins[2] = worldorigin[2] - worldsize;
10946         worldmaxs[0] = worldorigin[0] + worldsize;
10947         worldmaxs[1] = worldorigin[1] + worldsize;
10948         worldmaxs[2] = worldorigin[2] + worldsize;
10949
10950         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10951
10952         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10953         {
10954                 ent = r_refdef.scene.entities[renderentityindex];
10955                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10956                         continue;
10957
10958                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10959         }
10960 }
10961
10962 typedef struct r_decalsystem_splatqueue_s
10963 {
10964         vec3_t worldorigin;
10965         vec3_t worldnormal;
10966         float color[4];
10967         float tcrange[4];
10968         float worldsize;
10969         int decalsequence;
10970 }
10971 r_decalsystem_splatqueue_t;
10972
10973 int r_decalsystem_numqueued = 0;
10974 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10975
10976 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)
10977 {
10978         r_decalsystem_splatqueue_t *queue;
10979
10980         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10981                 return;
10982
10983         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10984         VectorCopy(worldorigin, queue->worldorigin);
10985         VectorCopy(worldnormal, queue->worldnormal);
10986         Vector4Set(queue->color, r, g, b, a);
10987         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10988         queue->worldsize = worldsize;
10989         queue->decalsequence = cl.decalsequence++;
10990 }
10991
10992 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10993 {
10994         int i;
10995         r_decalsystem_splatqueue_t *queue;
10996
10997         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10998                 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);
10999         r_decalsystem_numqueued = 0;
11000 }
11001
11002 extern cvar_t cl_decals_max;
11003 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11004 {
11005         int i;
11006         decalsystem_t *decalsystem = &ent->decalsystem;
11007         int numdecals;
11008         int killsequence;
11009         tridecal_t *decal;
11010         float frametime;
11011         float lifetime;
11012
11013         if (!decalsystem->numdecals)
11014                 return;
11015
11016         if (r_showsurfaces.integer)
11017                 return;
11018
11019         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11020         {
11021                 R_DecalSystem_Reset(decalsystem);
11022                 return;
11023         }
11024
11025         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11026         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11027
11028         if (decalsystem->lastupdatetime)
11029                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11030         else
11031                 frametime = 0;
11032         decalsystem->lastupdatetime = r_refdef.scene.time;
11033         decal = decalsystem->decals;
11034         numdecals = decalsystem->numdecals;
11035
11036         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11037         {
11038                 if (decal->color4f[0][3])
11039                 {
11040                         decal->lived += frametime;
11041                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11042                         {
11043                                 memset(decal, 0, sizeof(*decal));
11044                                 if (decalsystem->freedecal > i)
11045                                         decalsystem->freedecal = i;
11046                         }
11047                 }
11048         }
11049         decal = decalsystem->decals;
11050         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11051                 numdecals--;
11052
11053         // collapse the array by shuffling the tail decals into the gaps
11054         for (;;)
11055         {
11056                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11057                         decalsystem->freedecal++;
11058                 if (decalsystem->freedecal == numdecals)
11059                         break;
11060                 decal[decalsystem->freedecal] = decal[--numdecals];
11061         }
11062
11063         decalsystem->numdecals = numdecals;
11064
11065         if (numdecals <= 0)
11066         {
11067                 // if there are no decals left, reset decalsystem
11068                 R_DecalSystem_Reset(decalsystem);
11069         }
11070 }
11071
11072 extern skinframe_t *decalskinframe;
11073 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11074 {
11075         int i;
11076         decalsystem_t *decalsystem = &ent->decalsystem;
11077         int numdecals;
11078         tridecal_t *decal;
11079         float faderate;
11080         float alpha;
11081         float *v3f;
11082         float *c4f;
11083         float *t2f;
11084         const int *e;
11085         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11086         int numtris = 0;
11087
11088         numdecals = decalsystem->numdecals;
11089         if (!numdecals)
11090                 return;
11091
11092         if (r_showsurfaces.integer)
11093                 return;
11094
11095         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11096         {
11097                 R_DecalSystem_Reset(decalsystem);
11098                 return;
11099         }
11100
11101         // if the model is static it doesn't matter what value we give for
11102         // wantnormals and wanttangents, so this logic uses only rules applicable
11103         // to a model, knowing that they are meaningless otherwise
11104         if (ent == r_refdef.scene.worldentity)
11105                 RSurf_ActiveWorldEntity();
11106         else
11107                 RSurf_ActiveModelEntity(ent, false, false, false);
11108
11109         decalsystem->lastupdatetime = r_refdef.scene.time;
11110         decal = decalsystem->decals;
11111
11112         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11113
11114         // update vertex positions for animated models
11115         v3f = decalsystem->vertex3f;
11116         c4f = decalsystem->color4f;
11117         t2f = decalsystem->texcoord2f;
11118         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11119         {
11120                 if (!decal->color4f[0][3])
11121                         continue;
11122
11123                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11124                         continue;
11125
11126                 // skip backfaces
11127                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11128                         continue;
11129
11130                 // update color values for fading decals
11131                 if (decal->lived >= cl_decals_time.value)
11132                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11133                 else
11134                         alpha = 1.0f;
11135
11136                 c4f[ 0] = decal->color4f[0][0] * alpha;
11137                 c4f[ 1] = decal->color4f[0][1] * alpha;
11138                 c4f[ 2] = decal->color4f[0][2] * alpha;
11139                 c4f[ 3] = 1;
11140                 c4f[ 4] = decal->color4f[1][0] * alpha;
11141                 c4f[ 5] = decal->color4f[1][1] * alpha;
11142                 c4f[ 6] = decal->color4f[1][2] * alpha;
11143                 c4f[ 7] = 1;
11144                 c4f[ 8] = decal->color4f[2][0] * alpha;
11145                 c4f[ 9] = decal->color4f[2][1] * alpha;
11146                 c4f[10] = decal->color4f[2][2] * alpha;
11147                 c4f[11] = 1;
11148
11149                 t2f[0] = decal->texcoord2f[0][0];
11150                 t2f[1] = decal->texcoord2f[0][1];
11151                 t2f[2] = decal->texcoord2f[1][0];
11152                 t2f[3] = decal->texcoord2f[1][1];
11153                 t2f[4] = decal->texcoord2f[2][0];
11154                 t2f[5] = decal->texcoord2f[2][1];
11155
11156                 // update vertex positions for animated models
11157                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11158                 {
11159                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11160                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11161                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11162                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11163                 }
11164                 else
11165                 {
11166                         VectorCopy(decal->vertex3f[0], v3f);
11167                         VectorCopy(decal->vertex3f[1], v3f + 3);
11168                         VectorCopy(decal->vertex3f[2], v3f + 6);
11169                 }
11170
11171                 if (r_refdef.fogenabled)
11172                 {
11173                         alpha = RSurf_FogVertex(v3f);
11174                         VectorScale(c4f, alpha, c4f);
11175                         alpha = RSurf_FogVertex(v3f + 3);
11176                         VectorScale(c4f + 4, alpha, c4f + 4);
11177                         alpha = RSurf_FogVertex(v3f + 6);
11178                         VectorScale(c4f + 8, alpha, c4f + 8);
11179                 }
11180
11181                 v3f += 9;
11182                 c4f += 12;
11183                 t2f += 6;
11184                 numtris++;
11185         }
11186
11187         if (numtris > 0)
11188         {
11189                 r_refdef.stats.drawndecals += numtris;
11190
11191                 // now render the decals all at once
11192                 // (this assumes they all use one particle font texture!)
11193                 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);
11194 //              R_Mesh_ResetTextureState();
11195                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11196                 GL_DepthMask(false);
11197                 GL_DepthRange(0, 1);
11198                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11199                 GL_DepthTest(true);
11200                 GL_CullFace(GL_NONE);
11201                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11202                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11203                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11204         }
11205 }
11206
11207 static void R_DrawModelDecals(void)
11208 {
11209         int i, numdecals;
11210
11211         // fade faster when there are too many decals
11212         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11213         for (i = 0;i < r_refdef.scene.numentities;i++)
11214                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11215
11216         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11217         for (i = 0;i < r_refdef.scene.numentities;i++)
11218                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11219                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11220
11221         R_DecalSystem_ApplySplatEntitiesQueue();
11222
11223         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11224         for (i = 0;i < r_refdef.scene.numentities;i++)
11225                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11226
11227         r_refdef.stats.totaldecals += numdecals;
11228
11229         if (r_showsurfaces.integer)
11230                 return;
11231
11232         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11233
11234         for (i = 0;i < r_refdef.scene.numentities;i++)
11235         {
11236                 if (!r_refdef.viewcache.entityvisible[i])
11237                         continue;
11238                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11239                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11240         }
11241 }
11242
11243 extern cvar_t mod_collision_bih;
11244 void R_DrawDebugModel(void)
11245 {
11246         entity_render_t *ent = rsurface.entity;
11247         int i, j, k, l, flagsmask;
11248         const msurface_t *surface;
11249         dp_model_t *model = ent->model;
11250         vec3_t v;
11251
11252         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11253                 return;
11254
11255         if (r_showoverdraw.value > 0)
11256         {
11257                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11258                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11259                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11260                 GL_DepthTest(false);
11261                 GL_DepthMask(false);
11262                 GL_DepthRange(0, 1);
11263                 GL_BlendFunc(GL_ONE, GL_ONE);
11264                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11265                 {
11266                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11267                                 continue;
11268                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11269                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11270                         {
11271                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11272                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11273                                 if (!rsurface.texture->currentlayers->depthmask)
11274                                         GL_Color(c, 0, 0, 1.0f);
11275                                 else if (ent == r_refdef.scene.worldentity)
11276                                         GL_Color(c, c, c, 1.0f);
11277                                 else
11278                                         GL_Color(0, c, 0, 1.0f);
11279                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11280                                 RSurf_DrawBatch();
11281                         }
11282                 }
11283                 rsurface.texture = NULL;
11284         }
11285
11286         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11287
11288 //      R_Mesh_ResetTextureState();
11289         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11290         GL_DepthRange(0, 1);
11291         GL_DepthTest(!r_showdisabledepthtest.integer);
11292         GL_DepthMask(false);
11293         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11294
11295         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11296         {
11297                 int triangleindex;
11298                 int bihleafindex;
11299                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11300                 const q3mbrush_t *brush;
11301                 const bih_t *bih = &model->collision_bih;
11302                 const bih_leaf_t *bihleaf;
11303                 float vertex3f[3][3];
11304                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11305                 cullbox = false;
11306                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11307                 {
11308                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11309                                 continue;
11310                         switch (bihleaf->type)
11311                         {
11312                         case BIH_BRUSH:
11313                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11314                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11315                                 {
11316                                         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);
11317                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11318                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11319                                 }
11320                                 break;
11321                         case BIH_COLLISIONTRIANGLE:
11322                                 triangleindex = bihleaf->itemindex;
11323                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11324                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11325                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11326                                 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);
11327                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11328                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11329                                 break;
11330                         case BIH_RENDERTRIANGLE:
11331                                 triangleindex = bihleaf->itemindex;
11332                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11333                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11334                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11335                                 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);
11336                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11337                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11338                                 break;
11339                         }
11340                 }
11341         }
11342
11343         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11344
11345         if (r_showtris.integer && qglPolygonMode)
11346         {
11347                 if (r_showdisabledepthtest.integer)
11348                 {
11349                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11350                         GL_DepthMask(false);
11351                 }
11352                 else
11353                 {
11354                         GL_BlendFunc(GL_ONE, GL_ZERO);
11355                         GL_DepthMask(true);
11356                 }
11357                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11358                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11359                 {
11360                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11361                                 continue;
11362                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11363                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11364                         {
11365                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11366                                 if (!rsurface.texture->currentlayers->depthmask)
11367                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11368                                 else if (ent == r_refdef.scene.worldentity)
11369                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11370                                 else
11371                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11372                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11373                                 RSurf_DrawBatch();
11374                         }
11375                 }
11376                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11377                 rsurface.texture = NULL;
11378         }
11379
11380         if (r_shownormals.value != 0 && qglBegin)
11381         {
11382                 if (r_showdisabledepthtest.integer)
11383                 {
11384                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11385                         GL_DepthMask(false);
11386                 }
11387                 else
11388                 {
11389                         GL_BlendFunc(GL_ONE, GL_ZERO);
11390                         GL_DepthMask(true);
11391                 }
11392                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11393                 {
11394                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11395                                 continue;
11396                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11397                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11398                         {
11399                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11400                                 qglBegin(GL_LINES);
11401                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11402                                 {
11403                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11404                                         {
11405                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11406                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11407                                                 qglVertex3f(v[0], v[1], v[2]);
11408                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11409                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11410                                                 qglVertex3f(v[0], v[1], v[2]);
11411                                         }
11412                                 }
11413                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11414                                 {
11415                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11416                                         {
11417                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11418                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11419                                                 qglVertex3f(v[0], v[1], v[2]);
11420                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11421                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11422                                                 qglVertex3f(v[0], v[1], v[2]);
11423                                         }
11424                                 }
11425                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11426                                 {
11427                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11428                                         {
11429                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11430                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11431                                                 qglVertex3f(v[0], v[1], v[2]);
11432                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11433                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11434                                                 qglVertex3f(v[0], v[1], v[2]);
11435                                         }
11436                                 }
11437                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11438                                 {
11439                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11440                                         {
11441                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11442                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11443                                                 qglVertex3f(v[0], v[1], v[2]);
11444                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11445                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11446                                                 qglVertex3f(v[0], v[1], v[2]);
11447                                         }
11448                                 }
11449                                 qglEnd();
11450                                 CHECKGLERROR
11451                         }
11452                 }
11453                 rsurface.texture = NULL;
11454         }
11455 }
11456
11457 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11458 int r_maxsurfacelist = 0;
11459 const msurface_t **r_surfacelist = NULL;
11460 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11461 {
11462         int i, j, endj, flagsmask;
11463         dp_model_t *model = r_refdef.scene.worldmodel;
11464         msurface_t *surfaces;
11465         unsigned char *update;
11466         int numsurfacelist = 0;
11467         if (model == NULL)
11468                 return;
11469
11470         if (r_maxsurfacelist < model->num_surfaces)
11471         {
11472                 r_maxsurfacelist = model->num_surfaces;
11473                 if (r_surfacelist)
11474                         Mem_Free((msurface_t**)r_surfacelist);
11475                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11476         }
11477
11478         RSurf_ActiveWorldEntity();
11479
11480         surfaces = model->data_surfaces;
11481         update = model->brushq1.lightmapupdateflags;
11482
11483         // update light styles on this submodel
11484         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11485         {
11486                 model_brush_lightstyleinfo_t *style;
11487                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11488                 {
11489                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11490                         {
11491                                 int *list = style->surfacelist;
11492                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11493                                 for (j = 0;j < style->numsurfaces;j++)
11494                                         update[list[j]] = true;
11495                         }
11496                 }
11497         }
11498
11499         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11500
11501         if (debug)
11502         {
11503                 R_DrawDebugModel();
11504                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11505                 return;
11506         }
11507
11508         rsurface.lightmaptexture = NULL;
11509         rsurface.deluxemaptexture = NULL;
11510         rsurface.uselightmaptexture = false;
11511         rsurface.texture = NULL;
11512         rsurface.rtlight = NULL;
11513         numsurfacelist = 0;
11514         // add visible surfaces to draw list
11515         for (i = 0;i < model->nummodelsurfaces;i++)
11516         {
11517                 j = model->sortedmodelsurfaces[i];
11518                 if (r_refdef.viewcache.world_surfacevisible[j])
11519                         r_surfacelist[numsurfacelist++] = surfaces + j;
11520         }
11521         // update lightmaps if needed
11522         if (model->brushq1.firstrender)
11523         {
11524                 model->brushq1.firstrender = false;
11525                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11526                         if (update[j])
11527                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11528         }
11529         else if (update)
11530         {
11531                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11532                         if (r_refdef.viewcache.world_surfacevisible[j])
11533                                 if (update[j])
11534                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11535         }
11536         // don't do anything if there were no surfaces
11537         if (!numsurfacelist)
11538         {
11539                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11540                 return;
11541         }
11542         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11543
11544         // add to stats if desired
11545         if (r_speeds.integer && !skysurfaces && !depthonly)
11546         {
11547                 r_refdef.stats.world_surfaces += numsurfacelist;
11548                 for (j = 0;j < numsurfacelist;j++)
11549                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11550         }
11551
11552         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11553 }
11554
11555 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11556 {
11557         int i, j, endj, flagsmask;
11558         dp_model_t *model = ent->model;
11559         msurface_t *surfaces;
11560         unsigned char *update;
11561         int numsurfacelist = 0;
11562         if (model == NULL)
11563                 return;
11564
11565         if (r_maxsurfacelist < model->num_surfaces)
11566         {
11567                 r_maxsurfacelist = model->num_surfaces;
11568                 if (r_surfacelist)
11569                         Mem_Free((msurface_t **)r_surfacelist);
11570                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11571         }
11572
11573         // if the model is static it doesn't matter what value we give for
11574         // wantnormals and wanttangents, so this logic uses only rules applicable
11575         // to a model, knowing that they are meaningless otherwise
11576         if (ent == r_refdef.scene.worldentity)
11577                 RSurf_ActiveWorldEntity();
11578         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11579                 RSurf_ActiveModelEntity(ent, false, false, false);
11580         else if (prepass)
11581                 RSurf_ActiveModelEntity(ent, true, true, true);
11582         else if (depthonly)
11583         {
11584                 switch (vid.renderpath)
11585                 {
11586                 case RENDERPATH_GL20:
11587                 case RENDERPATH_D3D9:
11588                 case RENDERPATH_D3D10:
11589                 case RENDERPATH_D3D11:
11590                 case RENDERPATH_SOFT:
11591                 case RENDERPATH_GLES2:
11592                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11593                         break;
11594                 case RENDERPATH_GL11:
11595                 case RENDERPATH_GL13:
11596                 case RENDERPATH_GLES1:
11597                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11598                         break;
11599                 }
11600         }
11601         else
11602         {
11603                 switch (vid.renderpath)
11604                 {
11605                 case RENDERPATH_GL20:
11606                 case RENDERPATH_D3D9:
11607                 case RENDERPATH_D3D10:
11608                 case RENDERPATH_D3D11:
11609                 case RENDERPATH_SOFT:
11610                 case RENDERPATH_GLES2:
11611                         RSurf_ActiveModelEntity(ent, true, true, false);
11612                         break;
11613                 case RENDERPATH_GL11:
11614                 case RENDERPATH_GL13:
11615                 case RENDERPATH_GLES1:
11616                         RSurf_ActiveModelEntity(ent, true, false, false);
11617                         break;
11618                 }
11619         }
11620
11621         surfaces = model->data_surfaces;
11622         update = model->brushq1.lightmapupdateflags;
11623
11624         // update light styles
11625         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11626         {
11627                 model_brush_lightstyleinfo_t *style;
11628                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11629                 {
11630                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11631                         {
11632                                 int *list = style->surfacelist;
11633                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11634                                 for (j = 0;j < style->numsurfaces;j++)
11635                                         update[list[j]] = true;
11636                         }
11637                 }
11638         }
11639
11640         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11641
11642         if (debug)
11643         {
11644                 R_DrawDebugModel();
11645                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11646                 return;
11647         }
11648
11649         rsurface.lightmaptexture = NULL;
11650         rsurface.deluxemaptexture = NULL;
11651         rsurface.uselightmaptexture = false;
11652         rsurface.texture = NULL;
11653         rsurface.rtlight = NULL;
11654         numsurfacelist = 0;
11655         // add visible surfaces to draw list
11656         for (i = 0;i < model->nummodelsurfaces;i++)
11657                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11658         // don't do anything if there were no surfaces
11659         if (!numsurfacelist)
11660         {
11661                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11662                 return;
11663         }
11664         // update lightmaps if needed
11665         if (update)
11666         {
11667                 int updated = 0;
11668                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11669                 {
11670                         if (update[j])
11671                         {
11672                                 updated++;
11673                                 R_BuildLightMap(ent, surfaces + j);
11674                         }
11675                 }
11676         }
11677         if (update)
11678                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11679                         if (update[j])
11680                                 R_BuildLightMap(ent, surfaces + j);
11681         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11682
11683         // add to stats if desired
11684         if (r_speeds.integer && !skysurfaces && !depthonly)
11685         {
11686                 r_refdef.stats.entities_surfaces += numsurfacelist;
11687                 for (j = 0;j < numsurfacelist;j++)
11688                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11689         }
11690
11691         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11692 }
11693
11694 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11695 {
11696         static texture_t texture;
11697         static msurface_t surface;
11698         const msurface_t *surfacelist = &surface;
11699
11700         // fake enough texture and surface state to render this geometry
11701
11702         texture.update_lastrenderframe = -1; // regenerate this texture
11703         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11704         texture.currentskinframe = skinframe;
11705         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11706         texture.offsetmapping = OFFSETMAPPING_OFF;
11707         texture.offsetscale = 1;
11708         texture.specularscalemod = 1;
11709         texture.specularpowermod = 1;
11710
11711         surface.texture = &texture;
11712         surface.num_triangles = numtriangles;
11713         surface.num_firsttriangle = firsttriangle;
11714         surface.num_vertices = numvertices;
11715         surface.num_firstvertex = firstvertex;
11716
11717         // now render it
11718         rsurface.texture = R_GetCurrentTexture(surface.texture);
11719         rsurface.lightmaptexture = NULL;
11720         rsurface.deluxemaptexture = NULL;
11721         rsurface.uselightmaptexture = false;
11722         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11723 }
11724
11725 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)
11726 {
11727         static msurface_t surface;
11728         const msurface_t *surfacelist = &surface;
11729
11730         // fake enough texture and surface state to render this geometry
11731         surface.texture = texture;
11732         surface.num_triangles = numtriangles;
11733         surface.num_firsttriangle = firsttriangle;
11734         surface.num_vertices = numvertices;
11735         surface.num_firstvertex = firstvertex;
11736
11737         // now render it
11738         rsurface.texture = R_GetCurrentTexture(surface.texture);
11739         rsurface.lightmaptexture = NULL;
11740         rsurface.deluxemaptexture = NULL;
11741         rsurface.uselightmaptexture = false;
11742         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11743 }