]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Add/update cvars and such... Almost done now basically. Just a bit of testing left.
[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.88", "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", "1", "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", "10", "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", "100", "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 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         else if (texturemode == GL_ADD)
1914                 permutation |= SHADERPERMUTATION_GLOW;
1915         else if (texturemode == GL_DECAL)
1916                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1917         if (!second)
1918                 texturemode = GL_MODULATE;
1919         if (vid.allowalphatocoverage)
1920                 GL_AlphaToCoverage(false);
1921         switch (vid.renderpath)
1922         {
1923         case RENDERPATH_D3D9:
1924 #ifdef SUPPORTD3D
1925                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1926                 R_Mesh_TexBind(GL20TU_FIRST , first );
1927                 R_Mesh_TexBind(GL20TU_SECOND, second);
1928 #endif
1929                 break;
1930         case RENDERPATH_D3D10:
1931                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1932                 break;
1933         case RENDERPATH_D3D11:
1934                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1935                 break;
1936         case RENDERPATH_GL20:
1937         case RENDERPATH_GLES2:
1938                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1939                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1940                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1941                 break;
1942         case RENDERPATH_GL13:
1943         case RENDERPATH_GLES1:
1944                 R_Mesh_TexBind(0, first );
1945                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1946                 R_Mesh_TexBind(1, second);
1947                 if (second)
1948                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1949                 break;
1950         case RENDERPATH_GL11:
1951                 R_Mesh_TexBind(0, first );
1952                 break;
1953         case RENDERPATH_SOFT:
1954                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1955                 R_Mesh_TexBind(GL20TU_FIRST , first );
1956                 R_Mesh_TexBind(GL20TU_SECOND, second);
1957                 break;
1958         }
1959 }
1960
1961 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1962 {
1963         unsigned int permutation = 0;
1964         if (r_trippy.integer && !notrippy)
1965                 permutation |= SHADERPERMUTATION_TRIPPY;
1966         if (vid.allowalphatocoverage)
1967                 GL_AlphaToCoverage(false);
1968         switch (vid.renderpath)
1969         {
1970         case RENDERPATH_D3D9:
1971 #ifdef SUPPORTD3D
1972                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1973 #endif
1974                 break;
1975         case RENDERPATH_D3D10:
1976                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1977                 break;
1978         case RENDERPATH_D3D11:
1979                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1980                 break;
1981         case RENDERPATH_GL20:
1982         case RENDERPATH_GLES2:
1983                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1984                 break;
1985         case RENDERPATH_GL13:
1986         case RENDERPATH_GLES1:
1987                 R_Mesh_TexBind(0, 0);
1988                 R_Mesh_TexBind(1, 0);
1989                 break;
1990         case RENDERPATH_GL11:
1991                 R_Mesh_TexBind(0, 0);
1992                 break;
1993         case RENDERPATH_SOFT:
1994                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1995                 break;
1996         }
1997 }
1998
1999 void R_SetupShader_ShowDepth(qboolean notrippy)
2000 {
2001         int permutation = 0;
2002         if (r_trippy.integer && !notrippy)
2003                 permutation |= SHADERPERMUTATION_TRIPPY;
2004         if (r_trippy.integer)
2005                 permutation |= SHADERPERMUTATION_TRIPPY;
2006         if (vid.allowalphatocoverage)
2007                 GL_AlphaToCoverage(false);
2008         switch (vid.renderpath)
2009         {
2010         case RENDERPATH_D3D9:
2011 #ifdef SUPPORTHLSL
2012                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2013 #endif
2014                 break;
2015         case RENDERPATH_D3D10:
2016                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2017                 break;
2018         case RENDERPATH_D3D11:
2019                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2020                 break;
2021         case RENDERPATH_GL20:
2022         case RENDERPATH_GLES2:
2023                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2024                 break;
2025         case RENDERPATH_GL13:
2026         case RENDERPATH_GLES1:
2027                 break;
2028         case RENDERPATH_GL11:
2029                 break;
2030         case RENDERPATH_SOFT:
2031                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2032                 break;
2033         }
2034 }
2035
2036 extern qboolean r_shadow_usingdeferredprepass;
2037 extern cvar_t r_shadow_deferred_8bitrange;
2038 extern rtexture_t *r_shadow_attenuationgradienttexture;
2039 extern rtexture_t *r_shadow_attenuation2dtexture;
2040 extern rtexture_t *r_shadow_attenuation3dtexture;
2041 extern qboolean r_shadow_usingshadowmap2d;
2042 extern qboolean r_shadow_usingshadowmaportho;
2043 extern float r_shadow_shadowmap_texturescale[2];
2044 extern float r_shadow_shadowmap_parameters[4];
2045 extern qboolean r_shadow_shadowmapvsdct;
2046 extern qboolean r_shadow_shadowmapsampler;
2047 extern int r_shadow_shadowmappcf;
2048 extern rtexture_t *r_shadow_shadowmap2dtexture;
2049 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2050 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2051 extern matrix4x4_t r_shadow_shadowmapmatrix;
2052 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2053 extern int r_shadow_prepass_width;
2054 extern int r_shadow_prepass_height;
2055 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2056 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2057 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2058 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2059 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2060
2061 #define BLENDFUNC_ALLOWS_COLORMOD      1
2062 #define BLENDFUNC_ALLOWS_FOG           2
2063 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2064 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2065 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2066 static int R_BlendFuncFlags(int src, int dst)
2067 {
2068         int r = 0;
2069
2070         // a blendfunc allows colormod if:
2071         // a) it can never keep the destination pixel invariant, or
2072         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2073         // this is to prevent unintended side effects from colormod
2074
2075         // a blendfunc allows fog if:
2076         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2077         // this is to prevent unintended side effects from fog
2078
2079         // these checks are the output of fogeval.pl
2080
2081         r |= BLENDFUNC_ALLOWS_COLORMOD;
2082         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2083         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2084         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2085         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2086         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2088         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2089         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2090         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2091         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2092         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2094         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2096         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2097         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2100         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2101         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2103
2104         return r;
2105 }
2106
2107 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)
2108 {
2109         // select a permutation of the lighting shader appropriate to this
2110         // combination of texture, entity, light source, and fogging, only use the
2111         // minimum features necessary to avoid wasting rendering time in the
2112         // fragment shader on features that are not being used
2113         unsigned int permutation = 0;
2114         unsigned int mode = 0;
2115         int blendfuncflags;
2116         static float dummy_colormod[3] = {1, 1, 1};
2117         float *colormod = rsurface.colormod;
2118         float m16f[16];
2119         matrix4x4_t tempmatrix;
2120         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2121         if (r_trippy.integer && !notrippy)
2122                 permutation |= SHADERPERMUTATION_TRIPPY;
2123         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2124                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2125         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2126                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2127         if (rsurfacepass == RSURFPASS_BACKGROUND)
2128         {
2129                 // distorted background
2130                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2131                 {
2132                         mode = SHADERMODE_WATER;
2133                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2134                         {
2135                                 // this is the right thing to do for wateralpha
2136                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2137                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2138                         }
2139                         else
2140                         {
2141                                 // this is the right thing to do for entity alpha
2142                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2143                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2144                         }
2145                 }
2146                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2147                 {
2148                         mode = SHADERMODE_REFRACTION;
2149                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2150                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2151                 }
2152                 else
2153                 {
2154                         mode = SHADERMODE_GENERIC;
2155                         permutation |= SHADERPERMUTATION_DIFFUSE;
2156                         GL_BlendFunc(GL_ONE, GL_ZERO);
2157                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2158                 }
2159                 if (vid.allowalphatocoverage)
2160                         GL_AlphaToCoverage(false);
2161         }
2162         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2163         {
2164                 if (r_glsl_offsetmapping.integer)
2165                 {
2166                         switch(rsurface.texture->offsetmapping)
2167                         {
2168                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2169                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2170                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2171                         case OFFSETMAPPING_OFF: break;
2172                         }
2173                 }
2174                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2175                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2176                 // normalmap (deferred prepass), may use alpha test on diffuse
2177                 mode = SHADERMODE_DEFERREDGEOMETRY;
2178                 GL_BlendFunc(GL_ONE, GL_ZERO);
2179                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2180                 if (vid.allowalphatocoverage)
2181                         GL_AlphaToCoverage(false);
2182         }
2183         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2184         {
2185                 if (r_glsl_offsetmapping.integer)
2186                 {
2187                         switch(rsurface.texture->offsetmapping)
2188                         {
2189                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2190                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2191                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2192                         case OFFSETMAPPING_OFF: break;
2193                         }
2194                 }
2195                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2196                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2197                 // light source
2198                 mode = SHADERMODE_LIGHTSOURCE;
2199                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2200                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2201                 if (diffusescale > 0)
2202                         permutation |= SHADERPERMUTATION_DIFFUSE;
2203                 if (specularscale > 0)
2204                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2205                 if (r_refdef.fogenabled)
2206                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2207                 if (rsurface.texture->colormapping)
2208                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2209                 if (r_shadow_usingshadowmap2d)
2210                 {
2211                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2212                         if(r_shadow_shadowmapvsdct)
2213                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2214
2215                         if (r_shadow_shadowmapsampler)
2216                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2217                         if (r_shadow_shadowmappcf > 1)
2218                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2219                         else if (r_shadow_shadowmappcf)
2220                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2221                 }
2222                 if (rsurface.texture->reflectmasktexture)
2223                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2224                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2225                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2226                 if (vid.allowalphatocoverage)
2227                         GL_AlphaToCoverage(false);
2228         }
2229         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2230         {
2231                 if (r_glsl_offsetmapping.integer)
2232                 {
2233                         switch(rsurface.texture->offsetmapping)
2234                         {
2235                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2236                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2237                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2238                         case OFFSETMAPPING_OFF: break;
2239                         }
2240                 }
2241                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2242                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2243                 // unshaded geometry (fullbright or ambient model lighting)
2244                 mode = SHADERMODE_FLATCOLOR;
2245                 ambientscale = diffusescale = specularscale = 0;
2246                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2247                         permutation |= SHADERPERMUTATION_GLOW;
2248                 if (r_refdef.fogenabled)
2249                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2250                 if (rsurface.texture->colormapping)
2251                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2252                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2253                 {
2254                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2255                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2256
2257                         if (r_shadow_shadowmapsampler)
2258                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2259                         if (r_shadow_shadowmappcf > 1)
2260                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2261                         else if (r_shadow_shadowmappcf)
2262                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2263                 }
2264                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2265                         permutation |= SHADERPERMUTATION_REFLECTION;
2266                 if (rsurface.texture->reflectmasktexture)
2267                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2268                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2269                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2270                 // when using alphatocoverage, we don't need alphakill
2271                 if (vid.allowalphatocoverage)
2272                 {
2273                         if (r_transparent_alphatocoverage.integer)
2274                         {
2275                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2276                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2277                         }
2278                         else
2279                                 GL_AlphaToCoverage(false);
2280                 }
2281         }
2282         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2283         {
2284                 if (r_glsl_offsetmapping.integer)
2285                 {
2286                         switch(rsurface.texture->offsetmapping)
2287                         {
2288                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2289                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2291                         case OFFSETMAPPING_OFF: break;
2292                         }
2293                 }
2294                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2295                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2296                 // directional model lighting
2297                 mode = SHADERMODE_LIGHTDIRECTION;
2298                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2299                         permutation |= SHADERPERMUTATION_GLOW;
2300                 permutation |= SHADERPERMUTATION_DIFFUSE;
2301                 if (specularscale > 0)
2302                         permutation |= SHADERPERMUTATION_SPECULAR;
2303                 if (r_refdef.fogenabled)
2304                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2305                 if (rsurface.texture->colormapping)
2306                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2307                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2308                 {
2309                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2310                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2311
2312                         if (r_shadow_shadowmapsampler)
2313                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2314                         if (r_shadow_shadowmappcf > 1)
2315                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2316                         else if (r_shadow_shadowmappcf)
2317                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2318                 }
2319                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2320                         permutation |= SHADERPERMUTATION_REFLECTION;
2321                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2322                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2323                 if (rsurface.texture->reflectmasktexture)
2324                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2325                 if (r_shadow_bouncegridtexture)
2326                 {
2327                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2328                         if (r_shadow_bouncegriddirectional)
2329                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2330                 }
2331                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2332                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2333                 // when using alphatocoverage, we don't need alphakill
2334                 if (vid.allowalphatocoverage)
2335                 {
2336                         if (r_transparent_alphatocoverage.integer)
2337                         {
2338                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2339                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2340                         }
2341                         else
2342                                 GL_AlphaToCoverage(false);
2343                 }
2344         }
2345         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2346         {
2347                 if (r_glsl_offsetmapping.integer)
2348                 {
2349                         switch(rsurface.texture->offsetmapping)
2350                         {
2351                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2352                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2353                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2354                         case OFFSETMAPPING_OFF: break;
2355                         }
2356                 }
2357                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2358                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2359                 // ambient model lighting
2360                 mode = SHADERMODE_LIGHTDIRECTION;
2361                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2362                         permutation |= SHADERPERMUTATION_GLOW;
2363                 if (r_refdef.fogenabled)
2364                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2365                 if (rsurface.texture->colormapping)
2366                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2367                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2368                 {
2369                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2370                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2371
2372                         if (r_shadow_shadowmapsampler)
2373                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2374                         if (r_shadow_shadowmappcf > 1)
2375                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2376                         else if (r_shadow_shadowmappcf)
2377                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2378                 }
2379                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2380                         permutation |= SHADERPERMUTATION_REFLECTION;
2381                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2382                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2383                 if (rsurface.texture->reflectmasktexture)
2384                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2385                 if (r_shadow_bouncegridtexture)
2386                 {
2387                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2388                         if (r_shadow_bouncegriddirectional)
2389                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2390                 }
2391                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2392                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2393                 // when using alphatocoverage, we don't need alphakill
2394                 if (vid.allowalphatocoverage)
2395                 {
2396                         if (r_transparent_alphatocoverage.integer)
2397                         {
2398                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2399                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2400                         }
2401                         else
2402                                 GL_AlphaToCoverage(false);
2403                 }
2404         }
2405         else
2406         {
2407                 if (r_glsl_offsetmapping.integer)
2408                 {
2409                         switch(rsurface.texture->offsetmapping)
2410                         {
2411                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2412                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2413                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2414                         case OFFSETMAPPING_OFF: break;
2415                         }
2416                 }
2417                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2418                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2419                 // lightmapped wall
2420                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2421                         permutation |= SHADERPERMUTATION_GLOW;
2422                 if (r_refdef.fogenabled)
2423                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2424                 if (rsurface.texture->colormapping)
2425                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2426                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2427                 {
2428                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2429                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2430
2431                         if (r_shadow_shadowmapsampler)
2432                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2433                         if (r_shadow_shadowmappcf > 1)
2434                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2435                         else if (r_shadow_shadowmappcf)
2436                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2437                 }
2438                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2439                         permutation |= SHADERPERMUTATION_REFLECTION;
2440                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2441                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2442                 if (rsurface.texture->reflectmasktexture)
2443                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2444                 if (FAKELIGHT_ENABLED)
2445                 {
2446                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2447                         mode = SHADERMODE_FAKELIGHT;
2448                         permutation |= SHADERPERMUTATION_DIFFUSE;
2449                         if (specularscale > 0)
2450                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2451                 }
2452                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2453                 {
2454                         // deluxemapping (light direction texture)
2455                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2456                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2457                         else
2458                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2459                         permutation |= SHADERPERMUTATION_DIFFUSE;
2460                         if (specularscale > 0)
2461                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2462                 }
2463                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2464                 {
2465                         // fake deluxemapping (uniform light direction in tangentspace)
2466                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2467                         permutation |= SHADERPERMUTATION_DIFFUSE;
2468                         if (specularscale > 0)
2469                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2470                 }
2471                 else if (rsurface.uselightmaptexture)
2472                 {
2473                         // ordinary lightmapping (q1bsp, q3bsp)
2474                         mode = SHADERMODE_LIGHTMAP;
2475                 }
2476                 else
2477                 {
2478                         // ordinary vertex coloring (q3bsp)
2479                         mode = SHADERMODE_VERTEXCOLOR;
2480                 }
2481                 if (r_shadow_bouncegridtexture)
2482                 {
2483                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2484                         if (r_shadow_bouncegriddirectional)
2485                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2486                 }
2487                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2488                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2489                 // when using alphatocoverage, we don't need alphakill
2490                 if (vid.allowalphatocoverage)
2491                 {
2492                         if (r_transparent_alphatocoverage.integer)
2493                         {
2494                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2495                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2496                         }
2497                         else
2498                                 GL_AlphaToCoverage(false);
2499                 }
2500         }
2501         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2502                 colormod = dummy_colormod;
2503         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2504                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2505         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2506                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2507         switch(vid.renderpath)
2508         {
2509         case RENDERPATH_D3D9:
2510 #ifdef SUPPORTD3D
2511                 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);
2512                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2513                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2514                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2515                 if (mode == SHADERMODE_LIGHTSOURCE)
2516                 {
2517                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2518                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2519                 }
2520                 else
2521                 {
2522                         if (mode == SHADERMODE_LIGHTDIRECTION)
2523                         {
2524                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2525                         }
2526                 }
2527                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2528                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2529                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2530                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2531                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2532
2533                 if (mode == SHADERMODE_LIGHTSOURCE)
2534                 {
2535                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2536                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2537                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2538                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2539                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2540
2541                         // additive passes are only darkened by fog, not tinted
2542                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2543                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2544                 }
2545                 else
2546                 {
2547                         if (mode == SHADERMODE_FLATCOLOR)
2548                         {
2549                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2550                         }
2551                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2552                         {
2553                                 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]);
2554                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2555                                 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);
2556                                 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);
2557                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2558                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2559                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2560                         }
2561                         else
2562                         {
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2564                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2565                                 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);
2566                                 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);
2567                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2568                         }
2569                         // additive passes are only darkened by fog, not tinted
2570                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2572                         else
2573                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2574                         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);
2575                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2576                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2577                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2578                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2579                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2580                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2581                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2582                         if (mode == SHADERMODE_WATER)
2583                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2584                 }
2585                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2586                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2587                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2588                 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));
2589                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2590                 if (rsurface.texture->pantstexture)
2591                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2592                 else
2593                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2594                 if (rsurface.texture->shirttexture)
2595                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2596                 else
2597                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2598                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2599                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2600                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2601                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2602                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2603                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2604                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2605                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2606                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2607                         );
2608                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2609                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2610
2611                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2612                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2613                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2614                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2615                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2616                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2617                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2618                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2619                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2620                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2621                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2622                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2623                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2624                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2625                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2626                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2627                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2628                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2629                 {
2630                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2631                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2632                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2633                 }
2634                 else
2635                 {
2636                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2637                 }
2638 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2639 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2640                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2641                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2642                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2643                 {
2644                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2645                         if (rsurface.rtlight)
2646                         {
2647                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2648                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2649                         }
2650                 }
2651 #endif
2652                 break;
2653         case RENDERPATH_D3D10:
2654                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2655                 break;
2656         case RENDERPATH_D3D11:
2657                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2658                 break;
2659         case RENDERPATH_GL20:
2660         case RENDERPATH_GLES2:
2661                 if (!vid.useinterleavedarrays)
2662                 {
2663                         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);
2664                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2665                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2666                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2667                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2668                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2669                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2670                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2671                 }
2672                 else
2673                 {
2674                         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);
2675                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2676                 }
2677                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2678                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2679                 if (mode == SHADERMODE_LIGHTSOURCE)
2680                 {
2681                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2682                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2683                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2684                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2685                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2686                         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);
2687         
2688                         // additive passes are only darkened by fog, not tinted
2689                         if (r_glsl_permutation->loc_FogColor >= 0)
2690                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2691                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2692                 }
2693                 else
2694                 {
2695                         if (mode == SHADERMODE_FLATCOLOR)
2696                         {
2697                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2698                         }
2699                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2700                         {
2701                                 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]);
2702                                 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]);
2703                                 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);
2704                                 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);
2705                                 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);
2706                                 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]);
2707                                 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]);
2708                         }
2709                         else
2710                         {
2711                                 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]);
2712                                 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]);
2713                                 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);
2714                                 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);
2715                                 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);
2716                         }
2717                         // additive passes are only darkened by fog, not tinted
2718                         if (r_glsl_permutation->loc_FogColor >= 0)
2719                         {
2720                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2721                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2722                                 else
2723                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2724                         }
2725                         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);
2726                         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]);
2727                         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]);
2728                         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]);
2729                         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]);
2730                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2731                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2732                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2733                         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]);
2734                 }
2735                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2736                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2737                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2738                 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]);
2739                 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]);
2740
2741                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2742                 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));
2743                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2744                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2745                 {
2746                         if (rsurface.texture->pantstexture)
2747                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2748                         else
2749                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2750                 }
2751                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2752                 {
2753                         if (rsurface.texture->shirttexture)
2754                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2755                         else
2756                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2757                 }
2758                 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]);
2759                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2760                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2761                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2762                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2763                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2764                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2765                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2766                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2767                         );
2768                 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]);
2769                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2770                 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);}
2771                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2772
2773                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2774                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2775                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2776                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2777                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2778                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2779                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2780                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2781                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2782                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2783                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2784                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2785                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2786                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2787                 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);
2788                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2789                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2790                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2791                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2792                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2793                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2794                 {
2795                         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);
2796                         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);
2797                         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);
2798                 }
2799                 else
2800                 {
2801                         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);
2802                 }
2803                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2804                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2805                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2806                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2807                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2808                 {
2809                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2810                         if (rsurface.rtlight)
2811                         {
2812                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2813                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2814                         }
2815                 }
2816                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2817                 CHECKGLERROR
2818                 break;
2819         case RENDERPATH_GL11:
2820         case RENDERPATH_GL13:
2821         case RENDERPATH_GLES1:
2822                 break;
2823         case RENDERPATH_SOFT:
2824                 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);
2825                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2826                 R_SetupShader_SetPermutationSoft(mode, permutation);
2827                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2828                 if (mode == SHADERMODE_LIGHTSOURCE)
2829                 {
2830                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2831                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2832                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2833                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2834                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2835                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2836         
2837                         // additive passes are only darkened by fog, not tinted
2838                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2839                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2840                 }
2841                 else
2842                 {
2843                         if (mode == SHADERMODE_FLATCOLOR)
2844                         {
2845                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2846                         }
2847                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2848                         {
2849                                 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]);
2850                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2851                                 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);
2852                                 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);
2853                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2854                                 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]);
2855                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2856                         }
2857                         else
2858                         {
2859                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2860                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2861                                 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);
2862                                 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);
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2864                         }
2865                         // additive passes are only darkened by fog, not tinted
2866                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2868                         else
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2870                         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);
2871                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2872                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2873                         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]);
2874                         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]);
2875                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2876                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2877                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2878                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2879                 }
2880                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2881                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2882                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2883                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2884                 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]);
2885
2886                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2887                 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));
2888                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2889                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2890                 {
2891                         if (rsurface.texture->pantstexture)
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2893                         else
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2895                 }
2896                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2897                 {
2898                         if (rsurface.texture->shirttexture)
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2900                         else
2901                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2902                 }
2903                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2904                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2905                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2906                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2907                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2908                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2909                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2910                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2911                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2912                         );
2913                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2914                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2915
2916                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2917                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2918                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2919                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2920                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2921                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2922                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2923                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2924                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2925                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2926                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2927                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2928                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2929                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2930                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2931                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2932                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2933                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2934                 {
2935                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2936                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2937                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2938                 }
2939                 else
2940                 {
2941                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2942                 }
2943 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2944 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2945                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2946                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2947                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2948                 {
2949                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2950                         if (rsurface.rtlight)
2951                         {
2952                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2953                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2954                         }
2955                 }
2956                 break;
2957         }
2958 }
2959
2960 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2961 {
2962         // select a permutation of the lighting shader appropriate to this
2963         // combination of texture, entity, light source, and fogging, only use the
2964         // minimum features necessary to avoid wasting rendering time in the
2965         // fragment shader on features that are not being used
2966         unsigned int permutation = 0;
2967         unsigned int mode = 0;
2968         const float *lightcolorbase = rtlight->currentcolor;
2969         float ambientscale = rtlight->ambientscale;
2970         float diffusescale = rtlight->diffusescale;
2971         float specularscale = rtlight->specularscale;
2972         // this is the location of the light in view space
2973         vec3_t viewlightorigin;
2974         // this transforms from view space (camera) to light space (cubemap)
2975         matrix4x4_t viewtolight;
2976         matrix4x4_t lighttoview;
2977         float viewtolight16f[16];
2978         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2979         // light source
2980         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2981         if (rtlight->currentcubemap != r_texture_whitecube)
2982                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2983         if (diffusescale > 0)
2984                 permutation |= SHADERPERMUTATION_DIFFUSE;
2985         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2986                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2987         if (r_shadow_usingshadowmap2d)
2988         {
2989                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2990                 if (r_shadow_shadowmapvsdct)
2991                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2992
2993                 if (r_shadow_shadowmapsampler)
2994                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2995                 if (r_shadow_shadowmappcf > 1)
2996                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2997                 else if (r_shadow_shadowmappcf)
2998                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2999         }
3000         if (vid.allowalphatocoverage)
3001                 GL_AlphaToCoverage(false);
3002         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3003         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3004         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3005         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3006         switch(vid.renderpath)
3007         {
3008         case RENDERPATH_D3D9:
3009 #ifdef SUPPORTD3D
3010                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3011                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3012                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3013                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3014                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3015                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3016                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3017                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3018                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3019                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3020                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3021
3022                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3023                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3024                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3025                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3026                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3027                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3028 #endif
3029                 break;
3030         case RENDERPATH_D3D10:
3031                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3032                 break;
3033         case RENDERPATH_D3D11:
3034                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3035                 break;
3036         case RENDERPATH_GL20:
3037         case RENDERPATH_GLES2:
3038                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3039                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3040                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3041                 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);
3042                 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);
3043                 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);
3044                 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]);
3045                 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]);
3046                 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));
3047                 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]);
3048                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3049
3050                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3051                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3052                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3053                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3054                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3055                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3056                 break;
3057         case RENDERPATH_GL11:
3058         case RENDERPATH_GL13:
3059         case RENDERPATH_GLES1:
3060                 break;
3061         case RENDERPATH_SOFT:
3062                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3063                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3064                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3065                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3066                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3067                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3068                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3069                 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]);
3070                 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));
3071                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3072                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3073
3074                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3075                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3076                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3077                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3078                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3079                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3080                 break;
3081         }
3082 }
3083
3084 #define SKINFRAME_HASH 1024
3085
3086 typedef struct
3087 {
3088         int loadsequence; // incremented each level change
3089         memexpandablearray_t array;
3090         skinframe_t *hash[SKINFRAME_HASH];
3091 }
3092 r_skinframe_t;
3093 r_skinframe_t r_skinframe;
3094
3095 void R_SkinFrame_PrepareForPurge(void)
3096 {
3097         r_skinframe.loadsequence++;
3098         // wrap it without hitting zero
3099         if (r_skinframe.loadsequence >= 200)
3100                 r_skinframe.loadsequence = 1;
3101 }
3102
3103 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3104 {
3105         if (!skinframe)
3106                 return;
3107         // mark the skinframe as used for the purging code
3108         skinframe->loadsequence = r_skinframe.loadsequence;
3109 }
3110
3111 void R_SkinFrame_Purge(void)
3112 {
3113         int i;
3114         skinframe_t *s;
3115         for (i = 0;i < SKINFRAME_HASH;i++)
3116         {
3117                 for (s = r_skinframe.hash[i];s;s = s->next)
3118                 {
3119                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3120                         {
3121                                 if (s->merged == s->base)
3122                                         s->merged = NULL;
3123                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3124                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3125                                 R_PurgeTexture(s->merged);s->merged = NULL;
3126                                 R_PurgeTexture(s->base  );s->base   = NULL;
3127                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3128                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3129                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3130                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3131                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3132                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3133                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3134                                 s->loadsequence = 0;
3135                         }
3136                 }
3137         }
3138 }
3139
3140 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3141         skinframe_t *item;
3142         char basename[MAX_QPATH];
3143
3144         Image_StripImageExtension(name, basename, sizeof(basename));
3145
3146         if( last == NULL ) {
3147                 int hashindex;
3148                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3149                 item = r_skinframe.hash[hashindex];
3150         } else {
3151                 item = last->next;
3152         }
3153
3154         // linearly search through the hash bucket
3155         for( ; item ; item = item->next ) {
3156                 if( !strcmp( item->basename, basename ) ) {
3157                         return item;
3158                 }
3159         }
3160         return NULL;
3161 }
3162
3163 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3164 {
3165         skinframe_t *item;
3166         int hashindex;
3167         char basename[MAX_QPATH];
3168
3169         Image_StripImageExtension(name, basename, sizeof(basename));
3170
3171         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3172         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3173                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3174                         break;
3175
3176         if (!item) {
3177                 rtexture_t *dyntexture;
3178                 // check whether its a dynamic texture
3179                 dyntexture = CL_GetDynTexture( basename );
3180                 if (!add && !dyntexture)
3181                         return NULL;
3182                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3183                 memset(item, 0, sizeof(*item));
3184                 strlcpy(item->basename, basename, sizeof(item->basename));
3185                 item->base = dyntexture; // either NULL or dyntexture handle
3186                 item->textureflags = textureflags;
3187                 item->comparewidth = comparewidth;
3188                 item->compareheight = compareheight;
3189                 item->comparecrc = comparecrc;
3190                 item->next = r_skinframe.hash[hashindex];
3191                 r_skinframe.hash[hashindex] = item;
3192         }
3193         else if( item->base == NULL )
3194         {
3195                 rtexture_t *dyntexture;
3196                 // check whether its a dynamic texture
3197                 // 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]
3198                 dyntexture = CL_GetDynTexture( basename );
3199                 item->base = dyntexture; // either NULL or dyntexture handle
3200         }
3201
3202         R_SkinFrame_MarkUsed(item);
3203         return item;
3204 }
3205
3206 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3207         { \
3208                 unsigned long long avgcolor[5], wsum; \
3209                 int pix, comp, w; \
3210                 avgcolor[0] = 0; \
3211                 avgcolor[1] = 0; \
3212                 avgcolor[2] = 0; \
3213                 avgcolor[3] = 0; \
3214                 avgcolor[4] = 0; \
3215                 wsum = 0; \
3216                 for(pix = 0; pix < cnt; ++pix) \
3217                 { \
3218                         w = 0; \
3219                         for(comp = 0; comp < 3; ++comp) \
3220                                 w += getpixel; \
3221                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3222                         { \
3223                                 ++wsum; \
3224                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3225                                 w = getpixel; \
3226                                 for(comp = 0; comp < 3; ++comp) \
3227                                         avgcolor[comp] += getpixel * w; \
3228                                 avgcolor[3] += w; \
3229                         } \
3230                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3231                         avgcolor[4] += getpixel; \
3232                 } \
3233                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3234                         avgcolor[3] = 1; \
3235                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3236                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3237                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3238                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3239         }
3240
3241 extern cvar_t gl_picmip;
3242 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3243 {
3244         int j;
3245         unsigned char *pixels;
3246         unsigned char *bumppixels;
3247         unsigned char *basepixels = NULL;
3248         int basepixels_width = 0;
3249         int basepixels_height = 0;
3250         skinframe_t *skinframe;
3251         rtexture_t *ddsbase = NULL;
3252         qboolean ddshasalpha = false;
3253         float ddsavgcolor[4];
3254         char basename[MAX_QPATH];
3255         int miplevel = R_PicmipForFlags(textureflags);
3256         int savemiplevel = miplevel;
3257         int mymiplevel;
3258
3259         if (cls.state == ca_dedicated)
3260                 return NULL;
3261
3262         // return an existing skinframe if already loaded
3263         // if loading of the first image fails, don't make a new skinframe as it
3264         // would cause all future lookups of this to be missing
3265         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3266         if (skinframe && skinframe->base)
3267                 return skinframe;
3268
3269         Image_StripImageExtension(name, basename, sizeof(basename));
3270
3271         // check for DDS texture file first
3272         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3273         {
3274                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3275                 if (basepixels == NULL)
3276                         return NULL;
3277         }
3278
3279         // FIXME handle miplevel
3280
3281         if (developer_loading.integer)
3282                 Con_Printf("loading skin \"%s\"\n", name);
3283
3284         // we've got some pixels to store, so really allocate this new texture now
3285         if (!skinframe)
3286                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3287         skinframe->stain = NULL;
3288         skinframe->merged = NULL;
3289         skinframe->base = NULL;
3290         skinframe->pants = NULL;
3291         skinframe->shirt = NULL;
3292         skinframe->nmap = NULL;
3293         skinframe->gloss = NULL;
3294         skinframe->glow = NULL;
3295         skinframe->fog = NULL;
3296         skinframe->reflect = NULL;
3297         skinframe->hasalpha = false;
3298
3299         if (ddsbase)
3300         {
3301                 skinframe->base = ddsbase;
3302                 skinframe->hasalpha = ddshasalpha;
3303                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3304                 if (r_loadfog && skinframe->hasalpha)
3305                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3306                 //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]);
3307         }
3308         else
3309         {
3310                 basepixels_width = image_width;
3311                 basepixels_height = image_height;
3312                 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);
3313                 if (textureflags & TEXF_ALPHA)
3314                 {
3315                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3316                         {
3317                                 if (basepixels[j] < 255)
3318                                 {
3319                                         skinframe->hasalpha = true;
3320                                         break;
3321                                 }
3322                         }
3323                         if (r_loadfog && skinframe->hasalpha)
3324                         {
3325                                 // has transparent pixels
3326                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3327                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3328                                 {
3329                                         pixels[j+0] = 255;
3330                                         pixels[j+1] = 255;
3331                                         pixels[j+2] = 255;
3332                                         pixels[j+3] = basepixels[j+3];
3333                                 }
3334                                 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);
3335                                 Mem_Free(pixels);
3336                         }
3337                 }
3338                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3339                 //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]);
3340                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3341                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3342                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3343                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3344         }
3345
3346         if (r_loaddds)
3347         {
3348                 mymiplevel = savemiplevel;
3349                 if (r_loadnormalmap)
3350                         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);
3351                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3352                 if (r_loadgloss)
3353                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3354                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3355                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3356                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3357         }
3358
3359         // _norm is the name used by tenebrae and has been adopted as standard
3360         if (r_loadnormalmap && skinframe->nmap == NULL)
3361         {
3362                 mymiplevel = savemiplevel;
3363                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3364                 {
3365                         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);
3366                         Mem_Free(pixels);
3367                         pixels = NULL;
3368                 }
3369                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3370                 {
3371                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3372                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3373                         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);
3374                         Mem_Free(pixels);
3375                         Mem_Free(bumppixels);
3376                 }
3377                 else if (r_shadow_bumpscale_basetexture.value > 0)
3378                 {
3379                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3380                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3381                         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);
3382                         Mem_Free(pixels);
3383                 }
3384                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3385                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3386         }
3387
3388         // _luma is supported only for tenebrae compatibility
3389         // _glow is the preferred name
3390         mymiplevel = savemiplevel;
3391         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))))
3392         {
3393                 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);
3394                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3395                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3396                 Mem_Free(pixels);pixels = NULL;
3397         }
3398
3399         mymiplevel = savemiplevel;
3400         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3401         {
3402                 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);
3403                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3404                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3405                 Mem_Free(pixels);
3406                 pixels = NULL;
3407         }
3408
3409         mymiplevel = savemiplevel;
3410         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3411         {
3412                 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);
3413                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3414                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3415                 Mem_Free(pixels);
3416                 pixels = NULL;
3417         }
3418
3419         mymiplevel = savemiplevel;
3420         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3421         {
3422                 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);
3423                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3424                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3425                 Mem_Free(pixels);
3426                 pixels = NULL;
3427         }
3428
3429         mymiplevel = savemiplevel;
3430         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3431         {
3432                 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);
3433                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3434                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3435                 Mem_Free(pixels);
3436                 pixels = NULL;
3437         }
3438
3439         if (basepixels)
3440                 Mem_Free(basepixels);
3441
3442         return skinframe;
3443 }
3444
3445 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3446 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3447 {
3448         int i;
3449         unsigned char *temp1, *temp2;
3450         skinframe_t *skinframe;
3451
3452         if (cls.state == ca_dedicated)
3453                 return NULL;
3454
3455         // if already loaded just return it, otherwise make a new skinframe
3456         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3457         if (skinframe && skinframe->base)
3458                 return skinframe;
3459
3460         skinframe->stain = NULL;
3461         skinframe->merged = NULL;
3462         skinframe->base = NULL;
3463         skinframe->pants = NULL;
3464         skinframe->shirt = NULL;
3465         skinframe->nmap = NULL;
3466         skinframe->gloss = NULL;
3467         skinframe->glow = NULL;
3468         skinframe->fog = NULL;
3469         skinframe->reflect = NULL;
3470         skinframe->hasalpha = false;
3471
3472         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3473         if (!skindata)
3474                 return NULL;
3475
3476         if (developer_loading.integer)
3477                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3478
3479         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3480         {
3481                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3482                 temp2 = temp1 + width * height * 4;
3483                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3484                 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);
3485                 Mem_Free(temp1);
3486         }
3487         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3488         if (textureflags & TEXF_ALPHA)
3489         {
3490                 for (i = 3;i < width * height * 4;i += 4)
3491                 {
3492                         if (skindata[i] < 255)
3493                         {
3494                                 skinframe->hasalpha = true;
3495                                 break;
3496                         }
3497                 }
3498                 if (r_loadfog && skinframe->hasalpha)
3499                 {
3500                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3501                         memcpy(fogpixels, skindata, width * height * 4);
3502                         for (i = 0;i < width * height * 4;i += 4)
3503                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3504                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3505                         Mem_Free(fogpixels);
3506                 }
3507         }
3508
3509         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3510         //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]);
3511
3512         return skinframe;
3513 }
3514
3515 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3516 {
3517         int i;
3518         int featuresmask;
3519         skinframe_t *skinframe;
3520
3521         if (cls.state == ca_dedicated)
3522                 return NULL;
3523
3524         // if already loaded just return it, otherwise make a new skinframe
3525         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3526         if (skinframe && skinframe->base)
3527                 return skinframe;
3528
3529         skinframe->stain = NULL;
3530         skinframe->merged = NULL;
3531         skinframe->base = NULL;
3532         skinframe->pants = NULL;
3533         skinframe->shirt = NULL;
3534         skinframe->nmap = NULL;
3535         skinframe->gloss = NULL;
3536         skinframe->glow = NULL;
3537         skinframe->fog = NULL;
3538         skinframe->reflect = NULL;
3539         skinframe->hasalpha = false;
3540
3541         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3542         if (!skindata)
3543                 return NULL;
3544
3545         if (developer_loading.integer)
3546                 Con_Printf("loading quake skin \"%s\"\n", name);
3547
3548         // 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)
3549         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3550         memcpy(skinframe->qpixels, skindata, width*height);
3551         skinframe->qwidth = width;
3552         skinframe->qheight = height;
3553
3554         featuresmask = 0;
3555         for (i = 0;i < width * height;i++)
3556                 featuresmask |= palette_featureflags[skindata[i]];
3557
3558         skinframe->hasalpha = false;
3559         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3560         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3561         skinframe->qgeneratemerged = true;
3562         skinframe->qgeneratebase = skinframe->qhascolormapping;
3563         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3564
3565         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3566         //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]);
3567
3568         return skinframe;
3569 }
3570
3571 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3572 {
3573         int width;
3574         int height;
3575         unsigned char *skindata;
3576
3577         if (!skinframe->qpixels)
3578                 return;
3579
3580         if (!skinframe->qhascolormapping)
3581                 colormapped = false;
3582
3583         if (colormapped)
3584         {
3585                 if (!skinframe->qgeneratebase)
3586                         return;
3587         }
3588         else
3589         {
3590                 if (!skinframe->qgeneratemerged)
3591                         return;
3592         }
3593
3594         width = skinframe->qwidth;
3595         height = skinframe->qheight;
3596         skindata = skinframe->qpixels;
3597
3598         if (skinframe->qgeneratenmap)
3599         {
3600                 unsigned char *temp1, *temp2;
3601                 skinframe->qgeneratenmap = false;
3602                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3603                 temp2 = temp1 + width * height * 4;
3604                 // use either a custom palette or the quake palette
3605                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3606                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3607                 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);
3608                 Mem_Free(temp1);
3609         }
3610
3611         if (skinframe->qgenerateglow)
3612         {
3613                 skinframe->qgenerateglow = false;
3614                 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
3615         }
3616
3617         if (colormapped)
3618         {
3619                 skinframe->qgeneratebase = false;
3620                 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);
3621                 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);
3622                 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);
3623         }
3624         else
3625         {
3626                 skinframe->qgeneratemerged = false;
3627                 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);
3628         }
3629
3630         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3631         {
3632                 Mem_Free(skinframe->qpixels);
3633                 skinframe->qpixels = NULL;
3634         }
3635 }
3636
3637 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)
3638 {
3639         int i;
3640         skinframe_t *skinframe;
3641
3642         if (cls.state == ca_dedicated)
3643                 return NULL;
3644
3645         // if already loaded just return it, otherwise make a new skinframe
3646         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3647         if (skinframe && skinframe->base)
3648                 return skinframe;
3649
3650         skinframe->stain = NULL;
3651         skinframe->merged = NULL;
3652         skinframe->base = NULL;
3653         skinframe->pants = NULL;
3654         skinframe->shirt = NULL;
3655         skinframe->nmap = NULL;
3656         skinframe->gloss = NULL;
3657         skinframe->glow = NULL;
3658         skinframe->fog = NULL;
3659         skinframe->reflect = NULL;
3660         skinframe->hasalpha = false;
3661
3662         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3663         if (!skindata)
3664                 return NULL;
3665
3666         if (developer_loading.integer)
3667                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3668
3669         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3670         if (textureflags & TEXF_ALPHA)
3671         {
3672                 for (i = 0;i < width * height;i++)
3673                 {
3674                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3675                         {
3676                                 skinframe->hasalpha = true;
3677                                 break;
3678                         }
3679                 }
3680                 if (r_loadfog && skinframe->hasalpha)
3681                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3682         }
3683
3684         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3685         //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]);
3686
3687         return skinframe;
3688 }
3689
3690 skinframe_t *R_SkinFrame_LoadMissing(void)
3691 {
3692         skinframe_t *skinframe;
3693
3694         if (cls.state == ca_dedicated)
3695                 return NULL;
3696
3697         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3698         skinframe->stain = NULL;
3699         skinframe->merged = NULL;
3700         skinframe->base = NULL;
3701         skinframe->pants = NULL;
3702         skinframe->shirt = NULL;
3703         skinframe->nmap = NULL;
3704         skinframe->gloss = NULL;
3705         skinframe->glow = NULL;
3706         skinframe->fog = NULL;
3707         skinframe->reflect = NULL;
3708         skinframe->hasalpha = false;
3709
3710         skinframe->avgcolor[0] = rand() / RAND_MAX;
3711         skinframe->avgcolor[1] = rand() / RAND_MAX;
3712         skinframe->avgcolor[2] = rand() / RAND_MAX;
3713         skinframe->avgcolor[3] = 1;
3714
3715         return skinframe;
3716 }
3717
3718 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3719 typedef struct suffixinfo_s
3720 {
3721         const char *suffix;
3722         qboolean flipx, flipy, flipdiagonal;
3723 }
3724 suffixinfo_t;
3725 static suffixinfo_t suffix[3][6] =
3726 {
3727         {
3728                 {"px",   false, false, false},
3729                 {"nx",   false, false, false},
3730                 {"py",   false, false, false},
3731                 {"ny",   false, false, false},
3732                 {"pz",   false, false, false},
3733                 {"nz",   false, false, false}
3734         },
3735         {
3736                 {"posx", false, false, false},
3737                 {"negx", false, false, false},
3738                 {"posy", false, false, false},
3739                 {"negy", false, false, false},
3740                 {"posz", false, false, false},
3741                 {"negz", false, false, false}
3742         },
3743         {
3744                 {"rt",    true, false,  true},
3745                 {"lf",   false,  true,  true},
3746                 {"ft",    true,  true, false},
3747                 {"bk",   false, false, false},
3748                 {"up",    true, false,  true},
3749                 {"dn",    true, false,  true}
3750         }
3751 };
3752
3753 static int componentorder[4] = {0, 1, 2, 3};
3754
3755 rtexture_t *R_LoadCubemap(const char *basename)
3756 {
3757         int i, j, cubemapsize;
3758         unsigned char *cubemappixels, *image_buffer;
3759         rtexture_t *cubemaptexture;
3760         char name[256];
3761         // must start 0 so the first loadimagepixels has no requested width/height
3762         cubemapsize = 0;
3763         cubemappixels = NULL;
3764         cubemaptexture = NULL;
3765         // keep trying different suffix groups (posx, px, rt) until one loads
3766         for (j = 0;j < 3 && !cubemappixels;j++)
3767         {
3768                 // load the 6 images in the suffix group
3769                 for (i = 0;i < 6;i++)
3770                 {
3771                         // generate an image name based on the base and and suffix
3772                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3773                         // load it
3774                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3775                         {
3776                                 // an image loaded, make sure width and height are equal
3777                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3778                                 {
3779                                         // if this is the first image to load successfully, allocate the cubemap memory
3780                                         if (!cubemappixels && image_width >= 1)
3781                                         {
3782                                                 cubemapsize = image_width;
3783                                                 // note this clears to black, so unavailable sides are black
3784                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3785                                         }
3786                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3787                                         if (cubemappixels)
3788                                                 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);
3789                                 }
3790                                 else
3791                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3792                                 // free the image
3793                                 Mem_Free(image_buffer);
3794                         }
3795                 }
3796         }
3797         // if a cubemap loaded, upload it
3798         if (cubemappixels)
3799         {
3800                 if (developer_loading.integer)
3801                         Con_Printf("loading cubemap \"%s\"\n", basename);
3802
3803                 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);
3804                 Mem_Free(cubemappixels);
3805         }
3806         else
3807         {
3808                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3809                 if (developer_loading.integer)
3810                 {
3811                         Con_Printf("(tried tried images ");
3812                         for (j = 0;j < 3;j++)
3813                                 for (i = 0;i < 6;i++)
3814                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3815                         Con_Print(" and was unable to find any of them).\n");
3816                 }
3817         }
3818         return cubemaptexture;
3819 }
3820
3821 rtexture_t *R_GetCubemap(const char *basename)
3822 {
3823         int i;
3824         for (i = 0;i < r_texture_numcubemaps;i++)
3825                 if (r_texture_cubemaps[i] != NULL)
3826                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3827                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3828         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3829                 return r_texture_whitecube;
3830         r_texture_numcubemaps++;
3831         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3832         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3833         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3834         return r_texture_cubemaps[i]->texture;
3835 }
3836
3837 void R_FreeCubemap(const char *basename)
3838 {
3839         int i;
3840
3841         for (i = 0;i < r_texture_numcubemaps;i++)
3842         {
3843                 if (r_texture_cubemaps[i] != NULL)
3844                 {
3845                         if (r_texture_cubemaps[i]->texture)
3846                         {
3847                                 if (developer_loading.integer)
3848                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3849                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3850                                 Mem_Free(r_texture_cubemaps[i]);
3851                                 r_texture_cubemaps[i] = NULL;
3852                         }
3853                 }
3854         }
3855 }
3856
3857 void R_FreeCubemaps(void)
3858 {
3859         int i;
3860         for (i = 0;i < r_texture_numcubemaps;i++)
3861         {
3862                 if (developer_loading.integer)
3863                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3864                 if (r_texture_cubemaps[i] != NULL)
3865                 {
3866                         if (r_texture_cubemaps[i]->texture)
3867                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3868                         Mem_Free(r_texture_cubemaps[i]);
3869                 }
3870         }
3871         r_texture_numcubemaps = 0;
3872 }
3873
3874 void R_Main_FreeViewCache(void)
3875 {
3876         if (r_refdef.viewcache.entityvisible)
3877                 Mem_Free(r_refdef.viewcache.entityvisible);
3878         if (r_refdef.viewcache.world_pvsbits)
3879                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3880         if (r_refdef.viewcache.world_leafvisible)
3881                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3882         if (r_refdef.viewcache.world_surfacevisible)
3883                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3884         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3885 }
3886
3887 void R_Main_ResizeViewCache(void)
3888 {
3889         int numentities = r_refdef.scene.numentities;
3890         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3891         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3892         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3893         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3894         if (r_refdef.viewcache.maxentities < numentities)
3895         {
3896                 r_refdef.viewcache.maxentities = numentities;
3897                 if (r_refdef.viewcache.entityvisible)
3898                         Mem_Free(r_refdef.viewcache.entityvisible);
3899                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3900         }
3901         if (r_refdef.viewcache.world_numclusters != numclusters)
3902         {
3903                 r_refdef.viewcache.world_numclusters = numclusters;
3904                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3905                 if (r_refdef.viewcache.world_pvsbits)
3906                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3907                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3908         }
3909         if (r_refdef.viewcache.world_numleafs != numleafs)
3910         {
3911                 r_refdef.viewcache.world_numleafs = numleafs;
3912                 if (r_refdef.viewcache.world_leafvisible)
3913                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3914                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3915         }
3916         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3917         {
3918                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3919                 if (r_refdef.viewcache.world_surfacevisible)
3920                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3921                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3922         }
3923 }
3924
3925 extern rtexture_t *loadingscreentexture;
3926 void gl_main_start(void)
3927 {
3928         loadingscreentexture = NULL;
3929         r_texture_blanknormalmap = NULL;
3930         r_texture_white = NULL;
3931         r_texture_grey128 = NULL;
3932         r_texture_black = NULL;
3933         r_texture_whitecube = NULL;
3934         r_texture_normalizationcube = NULL;
3935         r_texture_fogattenuation = NULL;
3936         r_texture_fogheighttexture = NULL;
3937         r_texture_gammaramps = NULL;
3938         r_texture_numcubemaps = 0;
3939
3940         r_loaddds = r_texture_dds_load.integer != 0;
3941         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3942
3943         switch(vid.renderpath)
3944         {
3945         case RENDERPATH_GL20:
3946         case RENDERPATH_D3D9:
3947         case RENDERPATH_D3D10:
3948         case RENDERPATH_D3D11:
3949         case RENDERPATH_SOFT:
3950         case RENDERPATH_GLES2:
3951                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3952                 Cvar_SetValueQuick(&gl_combine, 1);
3953                 Cvar_SetValueQuick(&r_glsl, 1);
3954                 r_loadnormalmap = true;
3955                 r_loadgloss = true;
3956                 r_loadfog = false;
3957                 break;
3958         case RENDERPATH_GL13:
3959         case RENDERPATH_GLES1:
3960                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3961                 Cvar_SetValueQuick(&gl_combine, 1);
3962                 Cvar_SetValueQuick(&r_glsl, 0);
3963                 r_loadnormalmap = false;
3964                 r_loadgloss = false;
3965                 r_loadfog = true;
3966                 break;
3967         case RENDERPATH_GL11:
3968                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3969                 Cvar_SetValueQuick(&gl_combine, 0);
3970                 Cvar_SetValueQuick(&r_glsl, 0);
3971                 r_loadnormalmap = false;
3972                 r_loadgloss = false;
3973                 r_loadfog = true;
3974                 break;
3975         }
3976
3977         R_AnimCache_Free();
3978         R_FrameData_Reset();
3979
3980         r_numqueries = 0;
3981         r_maxqueries = 0;
3982         memset(r_queries, 0, sizeof(r_queries));
3983
3984         r_qwskincache = NULL;
3985         r_qwskincache_size = 0;
3986
3987         // due to caching of texture_t references, the collision cache must be reset
3988         Collision_Cache_Reset(true);
3989
3990         // set up r_skinframe loading system for textures
3991         memset(&r_skinframe, 0, sizeof(r_skinframe));
3992         r_skinframe.loadsequence = 1;
3993         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3994
3995         r_main_texturepool = R_AllocTexturePool();
3996         R_BuildBlankTextures();
3997         R_BuildNoTexture();
3998         if (vid.support.arb_texture_cube_map)
3999         {
4000                 R_BuildWhiteCube();
4001                 R_BuildNormalizationCube();
4002         }
4003         r_texture_fogattenuation = NULL;
4004         r_texture_fogheighttexture = NULL;
4005         r_texture_gammaramps = NULL;
4006         //r_texture_fogintensity = NULL;
4007         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4008         memset(&r_waterstate, 0, sizeof(r_waterstate));
4009         r_glsl_permutation = NULL;
4010         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4011         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4012         glslshaderstring = NULL;
4013 #ifdef SUPPORTD3D
4014         r_hlsl_permutation = NULL;
4015         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4016         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4017 #endif
4018         hlslshaderstring = NULL;
4019         memset(&r_svbsp, 0, sizeof (r_svbsp));
4020
4021         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4022         r_texture_numcubemaps = 0;
4023
4024         r_refdef.fogmasktable_density = 0;
4025 }
4026
4027 void gl_main_shutdown(void)
4028 {
4029         R_AnimCache_Free();
4030         R_FrameData_Reset();
4031
4032         R_Main_FreeViewCache();
4033
4034         switch(vid.renderpath)
4035         {
4036         case RENDERPATH_GL11:
4037         case RENDERPATH_GL13:
4038         case RENDERPATH_GL20:
4039         case RENDERPATH_GLES1:
4040         case RENDERPATH_GLES2:
4041                 if (r_maxqueries)
4042                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4043                 break;
4044         case RENDERPATH_D3D9:
4045                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4046                 break;
4047         case RENDERPATH_D3D10:
4048                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4049                 break;
4050         case RENDERPATH_D3D11:
4051                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4052                 break;
4053         case RENDERPATH_SOFT:
4054                 break;
4055         }
4056
4057         r_numqueries = 0;
4058         r_maxqueries = 0;
4059         memset(r_queries, 0, sizeof(r_queries));
4060
4061         r_qwskincache = NULL;
4062         r_qwskincache_size = 0;
4063
4064         // clear out the r_skinframe state
4065         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4066         memset(&r_skinframe, 0, sizeof(r_skinframe));
4067
4068         if (r_svbsp.nodes)
4069                 Mem_Free(r_svbsp.nodes);
4070         memset(&r_svbsp, 0, sizeof (r_svbsp));
4071         R_FreeTexturePool(&r_main_texturepool);
4072         loadingscreentexture = NULL;
4073         r_texture_blanknormalmap = NULL;
4074         r_texture_white = NULL;
4075         r_texture_grey128 = NULL;
4076         r_texture_black = NULL;
4077         r_texture_whitecube = NULL;
4078         r_texture_normalizationcube = NULL;
4079         r_texture_fogattenuation = NULL;
4080         r_texture_fogheighttexture = NULL;
4081         r_texture_gammaramps = NULL;
4082         r_texture_numcubemaps = 0;
4083         //r_texture_fogintensity = NULL;
4084         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4085         memset(&r_waterstate, 0, sizeof(r_waterstate));
4086         R_GLSL_Restart_f();
4087
4088         r_glsl_permutation = NULL;
4089         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4090         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4091         glslshaderstring = NULL;
4092 #ifdef SUPPORTD3D
4093         r_hlsl_permutation = NULL;
4094         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4095         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4096 #endif
4097         hlslshaderstring = NULL;
4098 }
4099
4100 extern void CL_ParseEntityLump(char *entitystring);
4101 void gl_main_newmap(void)
4102 {
4103         // FIXME: move this code to client
4104         char *entities, entname[MAX_QPATH];
4105         if (r_qwskincache)
4106                 Mem_Free(r_qwskincache);
4107         r_qwskincache = NULL;
4108         r_qwskincache_size = 0;
4109         if (cl.worldmodel)
4110         {
4111                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4112                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4113                 {
4114                         CL_ParseEntityLump(entities);
4115                         Mem_Free(entities);
4116                         return;
4117                 }
4118                 if (cl.worldmodel->brush.entities)
4119                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4120         }
4121         R_Main_FreeViewCache();
4122
4123         R_FrameData_Reset();
4124 }
4125
4126 void GL_Main_Init(void)
4127 {
4128         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4129
4130         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4131         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4132         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4133         if (gamemode == GAME_NEHAHRA)
4134         {
4135                 Cvar_RegisterVariable (&gl_fogenable);
4136                 Cvar_RegisterVariable (&gl_fogdensity);
4137                 Cvar_RegisterVariable (&gl_fogred);
4138                 Cvar_RegisterVariable (&gl_foggreen);
4139                 Cvar_RegisterVariable (&gl_fogblue);
4140                 Cvar_RegisterVariable (&gl_fogstart);
4141                 Cvar_RegisterVariable (&gl_fogend);
4142                 Cvar_RegisterVariable (&gl_skyclip);
4143         }
4144         Cvar_RegisterVariable(&r_motionblur);
4145         Cvar_RegisterVariable(&r_damageblur);
4146         Cvar_RegisterVariable(&r_motionblur_averaging);
4147         Cvar_RegisterVariable(&r_motionblur_randomize);
4148         Cvar_RegisterVariable(&r_motionblur_minblur);
4149         Cvar_RegisterVariable(&r_motionblur_maxblur);
4150         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4151         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4152         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4153         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4154         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4155         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4156         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4157         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4158         Cvar_RegisterVariable(&r_equalize_entities_by);
4159         Cvar_RegisterVariable(&r_equalize_entities_to);
4160         Cvar_RegisterVariable(&r_depthfirst);
4161         Cvar_RegisterVariable(&r_useinfinitefarclip);
4162         Cvar_RegisterVariable(&r_farclip_base);
4163         Cvar_RegisterVariable(&r_farclip_world);
4164         Cvar_RegisterVariable(&r_nearclip);
4165         Cvar_RegisterVariable(&r_deformvertexes);
4166         Cvar_RegisterVariable(&r_transparent);
4167         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4168         Cvar_RegisterVariable(&r_showoverdraw);
4169         Cvar_RegisterVariable(&r_showbboxes);
4170         Cvar_RegisterVariable(&r_showsurfaces);
4171         Cvar_RegisterVariable(&r_showtris);
4172         Cvar_RegisterVariable(&r_shownormals);
4173         Cvar_RegisterVariable(&r_showlighting);
4174         Cvar_RegisterVariable(&r_showshadowvolumes);
4175         Cvar_RegisterVariable(&r_showcollisionbrushes);
4176         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4177         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4178         Cvar_RegisterVariable(&r_showdisabledepthtest);
4179         Cvar_RegisterVariable(&r_drawportals);
4180         Cvar_RegisterVariable(&r_drawentities);
4181         Cvar_RegisterVariable(&r_draw2d);
4182         Cvar_RegisterVariable(&r_drawworld);
4183         Cvar_RegisterVariable(&r_cullentities_trace);
4184         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4185         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4186         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4187         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4188         Cvar_RegisterVariable(&r_drawviewmodel);
4189         Cvar_RegisterVariable(&r_drawexteriormodel);
4190         Cvar_RegisterVariable(&r_speeds);
4191         Cvar_RegisterVariable(&r_fullbrights);
4192         Cvar_RegisterVariable(&r_wateralpha);
4193         Cvar_RegisterVariable(&r_dynamic);
4194         Cvar_RegisterVariable(&r_fakelight);
4195         Cvar_RegisterVariable(&r_fakelight_intensity);
4196         Cvar_RegisterVariable(&r_fullbright);
4197         Cvar_RegisterVariable(&r_shadows);
4198         Cvar_RegisterVariable(&r_shadows_darken);
4199         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4200         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4201         Cvar_RegisterVariable(&r_shadows_throwdistance);
4202         Cvar_RegisterVariable(&r_shadows_throwdirection);
4203         Cvar_RegisterVariable(&r_shadows_focus);
4204         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4205         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4206         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4207         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4208         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4209         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4210         Cvar_RegisterVariable(&r_fog_exp2);
4211         Cvar_RegisterVariable(&r_fog_clear);
4212         Cvar_RegisterVariable(&r_drawfog);
4213         Cvar_RegisterVariable(&r_transparentdepthmasking);
4214         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4215         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4216         Cvar_RegisterVariable(&r_texture_dds_load);
4217         Cvar_RegisterVariable(&r_texture_dds_save);
4218         Cvar_RegisterVariable(&r_textureunits);
4219         Cvar_RegisterVariable(&gl_combine);
4220         Cvar_RegisterVariable(&r_viewfbo);
4221         Cvar_RegisterVariable(&r_viewscale);
4222         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4223         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4224         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4225         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4226         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4227         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4228         Cvar_RegisterVariable(&r_glsl);
4229         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4230         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4231         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4232         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4233         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4234         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4235         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4236         Cvar_RegisterVariable(&r_glsl_postprocess);
4237         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4238         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4239         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4240         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4241         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4242         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4243         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4244         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4245
4246         Cvar_RegisterVariable(&r_water);
4247         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4248         Cvar_RegisterVariable(&r_water_clippingplanebias);
4249         Cvar_RegisterVariable(&r_water_refractdistort);
4250         Cvar_RegisterVariable(&r_water_reflectdistort);
4251         Cvar_RegisterVariable(&r_water_scissormode);
4252         Cvar_RegisterVariable(&r_water_lowquality);
4253
4254         Cvar_RegisterVariable(&r_lerpsprites);
4255         Cvar_RegisterVariable(&r_lerpmodels);
4256         Cvar_RegisterVariable(&r_lerplightstyles);
4257         Cvar_RegisterVariable(&r_waterscroll);
4258         Cvar_RegisterVariable(&r_bloom);
4259         Cvar_RegisterVariable(&r_bloom_colorscale);
4260         Cvar_RegisterVariable(&r_bloom_brighten);
4261         Cvar_RegisterVariable(&r_bloom_blur);
4262         Cvar_RegisterVariable(&r_bloom_resolution);
4263         Cvar_RegisterVariable(&r_bloom_colorexponent);
4264         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4265         Cvar_RegisterVariable(&r_hdr);
4266         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4267         Cvar_RegisterVariable(&r_hdr_glowintensity);
4268         Cvar_RegisterVariable(&r_hdr_range);
4269         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4270         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4271         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4272         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4273         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4274         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4275         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4276         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4277         Cvar_RegisterVariable(&developer_texturelogging);
4278         Cvar_RegisterVariable(&gl_lightmaps);
4279         Cvar_RegisterVariable(&r_test);
4280         Cvar_RegisterVariable(&r_glsl_saturation);
4281         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4282         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4283         Cvar_RegisterVariable(&r_framedatasize);
4284         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4285                 Cvar_SetValue("r_fullbrights", 0);
4286         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4287 }
4288
4289 extern void R_Textures_Init(void);
4290 extern void GL_Draw_Init(void);
4291 extern void GL_Main_Init(void);
4292 extern void R_Shadow_Init(void);
4293 extern void R_Sky_Init(void);
4294 extern void GL_Surf_Init(void);
4295 extern void R_Particles_Init(void);
4296 extern void R_Explosion_Init(void);
4297 extern void gl_backend_init(void);
4298 extern void Sbar_Init(void);
4299 extern void R_LightningBeams_Init(void);
4300 extern void Mod_RenderInit(void);
4301 extern void Font_Init(void);
4302
4303 void Render_Init(void)
4304 {
4305         gl_backend_init();
4306         R_Textures_Init();
4307         GL_Main_Init();
4308         Font_Init();
4309         GL_Draw_Init();
4310         R_Shadow_Init();
4311         R_Sky_Init();
4312         GL_Surf_Init();
4313         Sbar_Init();
4314         R_Particles_Init();
4315         R_Explosion_Init();
4316         R_LightningBeams_Init();
4317         Mod_RenderInit();
4318 }
4319
4320 /*
4321 ===============
4322 GL_Init
4323 ===============
4324 */
4325 extern char *ENGINE_EXTENSIONS;
4326 void GL_Init (void)
4327 {
4328         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4329         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4330         gl_version = (const char *)qglGetString(GL_VERSION);
4331         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4332
4333         if (!gl_extensions)
4334                 gl_extensions = "";
4335         if (!gl_platformextensions)
4336                 gl_platformextensions = "";
4337
4338         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4339         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4340         Con_Printf("GL_VERSION: %s\n", gl_version);
4341         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4342         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4343
4344         VID_CheckExtensions();
4345
4346         // LordHavoc: report supported extensions
4347         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4348
4349         // clear to black (loading plaque will be seen over this)
4350         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4351 }
4352
4353 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4354 {
4355         int i;
4356         mplane_t *p;
4357         if (r_trippy.integer)
4358                 return false;
4359         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4360         {
4361                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4362                 if (i == 4)
4363                         continue;
4364                 p = r_refdef.view.frustum + i;
4365                 switch(p->signbits)
4366                 {
4367                 default:
4368                 case 0:
4369                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4370                                 return true;
4371                         break;
4372                 case 1:
4373                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4374                                 return true;
4375                         break;
4376                 case 2:
4377                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4378                                 return true;
4379                         break;
4380                 case 3:
4381                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4382                                 return true;
4383                         break;
4384                 case 4:
4385                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4386                                 return true;
4387                         break;
4388                 case 5:
4389                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4390                                 return true;
4391                         break;
4392                 case 6:
4393                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4394                                 return true;
4395                         break;
4396                 case 7:
4397                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4398                                 return true;
4399                         break;
4400                 }
4401         }
4402         return false;
4403 }
4404
4405 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4406 {
4407         int i;
4408         const mplane_t *p;
4409         if (r_trippy.integer)
4410                 return false;
4411         for (i = 0;i < numplanes;i++)
4412         {
4413                 p = planes + i;
4414                 switch(p->signbits)
4415                 {
4416                 default:
4417                 case 0:
4418                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4419                                 return true;
4420                         break;
4421                 case 1:
4422                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4423                                 return true;
4424                         break;
4425                 case 2:
4426                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4427                                 return true;
4428                         break;
4429                 case 3:
4430                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4431                                 return true;
4432                         break;
4433                 case 4:
4434                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4435                                 return true;
4436                         break;
4437                 case 5:
4438                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4439                                 return true;
4440                         break;
4441                 case 6:
4442                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 7:
4446                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 }
4450         }
4451         return false;
4452 }
4453
4454 //==================================================================================
4455
4456 // LordHavoc: this stores temporary data used within the same frame
4457
4458 typedef struct r_framedata_mem_s
4459 {
4460         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4461         size_t size; // how much usable space
4462         size_t current; // how much space in use
4463         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4464         size_t wantedsize; // how much space was allocated
4465         unsigned char *data; // start of real data (16byte aligned)
4466 }
4467 r_framedata_mem_t;
4468
4469 static r_framedata_mem_t *r_framedata_mem;
4470
4471 void R_FrameData_Reset(void)
4472 {
4473         while (r_framedata_mem)
4474         {
4475                 r_framedata_mem_t *next = r_framedata_mem->purge;
4476                 Mem_Free(r_framedata_mem);
4477                 r_framedata_mem = next;
4478         }
4479 }
4480
4481 void R_FrameData_Resize(void)
4482 {
4483         size_t wantedsize;
4484         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4485         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4486         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4487         {
4488                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4489                 newmem->wantedsize = wantedsize;
4490                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4491                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4492                 newmem->current = 0;
4493                 newmem->mark = 0;
4494                 newmem->purge = r_framedata_mem;
4495                 r_framedata_mem = newmem;
4496         }
4497 }
4498
4499 void R_FrameData_NewFrame(void)
4500 {
4501         R_FrameData_Resize();
4502         if (!r_framedata_mem)
4503                 return;
4504         // if we ran out of space on the last frame, free the old memory now
4505         while (r_framedata_mem->purge)
4506         {
4507                 // repeatedly remove the second item in the list, leaving only head
4508                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4509                 Mem_Free(r_framedata_mem->purge);
4510                 r_framedata_mem->purge = next;
4511         }
4512         // reset the current mem pointer
4513         r_framedata_mem->current = 0;
4514         r_framedata_mem->mark = 0;
4515 }
4516
4517 void *R_FrameData_Alloc(size_t size)
4518 {
4519         void *data;
4520
4521         // align to 16 byte boundary - the data pointer is already aligned, so we
4522         // only need to ensure the size of every allocation is also aligned
4523         size = (size + 15) & ~15;
4524
4525         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4526         {
4527                 // emergency - we ran out of space, allocate more memory
4528                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4529                 R_FrameData_Resize();
4530         }
4531
4532         data = r_framedata_mem->data + r_framedata_mem->current;
4533         r_framedata_mem->current += size;
4534
4535         // count the usage for stats
4536         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4537         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4538
4539         return (void *)data;
4540 }
4541
4542 void *R_FrameData_Store(size_t size, void *data)
4543 {
4544         void *d = R_FrameData_Alloc(size);
4545         if (d && data)
4546                 memcpy(d, data, size);
4547         return d;
4548 }
4549
4550 void R_FrameData_SetMark(void)
4551 {
4552         if (!r_framedata_mem)
4553                 return;
4554         r_framedata_mem->mark = r_framedata_mem->current;
4555 }
4556
4557 void R_FrameData_ReturnToMark(void)
4558 {
4559         if (!r_framedata_mem)
4560                 return;
4561         r_framedata_mem->current = r_framedata_mem->mark;
4562 }
4563
4564 //==================================================================================
4565
4566 // LordHavoc: animcache originally written by Echon, rewritten since then
4567
4568 /**
4569  * Animation cache prevents re-generating mesh data for an animated model
4570  * multiple times in one frame for lighting, shadowing, reflections, etc.
4571  */
4572
4573 void R_AnimCache_Free(void)
4574 {
4575 }
4576
4577 void R_AnimCache_ClearCache(void)
4578 {
4579         int i;
4580         entity_render_t *ent;
4581
4582         for (i = 0;i < r_refdef.scene.numentities;i++)
4583         {
4584                 ent = r_refdef.scene.entities[i];
4585                 ent->animcache_vertex3f = NULL;
4586                 ent->animcache_normal3f = NULL;
4587                 ent->animcache_svector3f = NULL;
4588                 ent->animcache_tvector3f = NULL;
4589                 ent->animcache_vertexmesh = NULL;
4590                 ent->animcache_vertex3fbuffer = NULL;
4591                 ent->animcache_vertexmeshbuffer = NULL;
4592         }
4593 }
4594
4595 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4596 {
4597         int i;
4598
4599         // check if we need the meshbuffers
4600         if (!vid.useinterleavedarrays)
4601                 return;
4602
4603         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4604                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4605         // TODO: upload vertex3f buffer?
4606         if (ent->animcache_vertexmesh)
4607         {
4608                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4609                 for (i = 0;i < numvertices;i++)
4610                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4611                 if (ent->animcache_svector3f)
4612                         for (i = 0;i < numvertices;i++)
4613                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4614                 if (ent->animcache_tvector3f)
4615                         for (i = 0;i < numvertices;i++)
4616                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4617                 if (ent->animcache_normal3f)
4618                         for (i = 0;i < numvertices;i++)
4619                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4620                 // TODO: upload vertexmeshbuffer?
4621         }
4622 }
4623
4624 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4625 {
4626         dp_model_t *model = ent->model;
4627         int numvertices;
4628         // see if it's already cached this frame
4629         if (ent->animcache_vertex3f)
4630         {
4631                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4632                 if (wantnormals || wanttangents)
4633                 {
4634                         if (ent->animcache_normal3f)
4635                                 wantnormals = false;
4636                         if (ent->animcache_svector3f)
4637                                 wanttangents = false;
4638                         if (wantnormals || wanttangents)
4639                         {
4640                                 numvertices = model->surfmesh.num_vertices;
4641                                 if (wantnormals)
4642                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4643                                 if (wanttangents)
4644                                 {
4645                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4646                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4647                                 }
4648                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4649                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4650                         }
4651                 }
4652         }
4653         else
4654         {
4655                 // see if this ent is worth caching
4656                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4657                         return false;
4658                 // get some memory for this entity and generate mesh data
4659                 numvertices = model->surfmesh.num_vertices;
4660                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4661                 if (wantnormals)
4662                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4663                 if (wanttangents)
4664                 {
4665                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4666                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4667                 }
4668                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4669                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4670         }
4671         return true;
4672 }
4673
4674 void R_AnimCache_CacheVisibleEntities(void)
4675 {
4676         int i;
4677         qboolean wantnormals = true;
4678         qboolean wanttangents = !r_showsurfaces.integer;
4679
4680         switch(vid.renderpath)
4681         {
4682         case RENDERPATH_GL20:
4683         case RENDERPATH_D3D9:
4684         case RENDERPATH_D3D10:
4685         case RENDERPATH_D3D11:
4686         case RENDERPATH_GLES2:
4687                 break;
4688         case RENDERPATH_GL11:
4689         case RENDERPATH_GL13:
4690         case RENDERPATH_GLES1:
4691                 wanttangents = false;
4692                 break;
4693         case RENDERPATH_SOFT:
4694                 break;
4695         }
4696
4697         if (r_shownormals.integer)
4698                 wanttangents = wantnormals = true;
4699
4700         // TODO: thread this
4701         // NOTE: R_PrepareRTLights() also caches entities
4702
4703         for (i = 0;i < r_refdef.scene.numentities;i++)
4704                 if (r_refdef.viewcache.entityvisible[i])
4705                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4706 }
4707
4708 //==================================================================================
4709
4710 extern cvar_t r_overheadsprites_pushback;
4711
4712 static void R_View_UpdateEntityLighting (void)
4713 {
4714         int i;
4715         entity_render_t *ent;
4716         vec3_t tempdiffusenormal, avg;
4717         vec_t f, fa, fd, fdd;
4718         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4719
4720         for (i = 0;i < r_refdef.scene.numentities;i++)
4721         {
4722                 ent = r_refdef.scene.entities[i];
4723
4724                 // skip unseen models
4725                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4726                         continue;
4727
4728                 // skip bsp models
4729                 if (ent->model && ent->model->brush.num_leafs)
4730                 {
4731                         // TODO: use modellight for r_ambient settings on world?
4732                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4733                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4734                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4735                         continue;
4736                 }
4737
4738                 // fetch the lighting from the worldmodel data
4739                 VectorClear(ent->modellight_ambient);
4740                 VectorClear(ent->modellight_diffuse);
4741                 VectorClear(tempdiffusenormal);
4742                 if (ent->flags & RENDER_LIGHT)
4743                 {
4744                         vec3_t org;
4745                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4746
4747                         // complete lightning for lit sprites
4748                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4749                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4750                         {
4751                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4752                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4753                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4754                         }
4755                         else
4756                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4757
4758                         if(ent->flags & RENDER_EQUALIZE)
4759                         {
4760                                 // first fix up ambient lighting...
4761                                 if(r_equalize_entities_minambient.value > 0)
4762                                 {
4763                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4764                                         if(fd > 0)
4765                                         {
4766                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4767                                                 if(fa < r_equalize_entities_minambient.value * fd)
4768                                                 {
4769                                                         // solve:
4770                                                         //   fa'/fd' = minambient
4771                                                         //   fa'+0.25*fd' = fa+0.25*fd
4772                                                         //   ...
4773                                                         //   fa' = fd' * minambient
4774                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4775                                                         //   ...
4776                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4777                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4778                                                         //   ...
4779                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4780                                                         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
4781                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4782                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4783                                                 }
4784                                         }
4785                                 }
4786
4787                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4788                                 {
4789                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4790                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4791                                         f = fa + 0.25 * fd;
4792                                         if(f > 0)
4793                                         {
4794                                                 // adjust brightness and saturation to target
4795                                                 avg[0] = avg[1] = avg[2] = fa / f;
4796                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4797                                                 avg[0] = avg[1] = avg[2] = fd / f;
4798                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4799                                         }
4800                                 }
4801                         }
4802                 }
4803                 else // highly rare
4804                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4805
4806                 // move the light direction into modelspace coordinates for lighting code
4807                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4808                 if(VectorLength2(ent->modellight_lightdir) == 0)
4809                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4810                 VectorNormalize(ent->modellight_lightdir);
4811         }
4812 }
4813
4814 #define MAX_LINEOFSIGHTTRACES 64
4815
4816 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4817 {
4818         int i;
4819         vec3_t boxmins, boxmaxs;
4820         vec3_t start;
4821         vec3_t end;
4822         dp_model_t *model = r_refdef.scene.worldmodel;
4823
4824         if (!model || !model->brush.TraceLineOfSight)
4825                 return true;
4826
4827         // expand the box a little
4828         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4829         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4830         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4831         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4832         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4833         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4834
4835         // return true if eye is inside enlarged box
4836         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4837                 return true;
4838
4839         // try center
4840         VectorCopy(eye, start);
4841         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4842         if (model->brush.TraceLineOfSight(model, start, end))
4843                 return true;
4844
4845         // try various random positions
4846         for (i = 0;i < numsamples;i++)
4847         {
4848                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4849                 if (model->brush.TraceLineOfSight(model, start, end))
4850                         return true;
4851         }
4852
4853         return false;
4854 }
4855
4856
4857 static void R_View_UpdateEntityVisible (void)
4858 {
4859         int i;
4860         int renderimask;
4861         int samples;
4862         entity_render_t *ent;
4863
4864         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4865                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4866                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4867                 :                                                          RENDER_EXTERIORMODEL;
4868         if (!r_drawviewmodel.integer)
4869                 renderimask |= RENDER_VIEWMODEL;
4870         if (!r_drawexteriormodel.integer)
4871                 renderimask |= RENDER_EXTERIORMODEL;
4872         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4873         {
4874                 // worldmodel can check visibility
4875                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4876                 for (i = 0;i < r_refdef.scene.numentities;i++)
4877                 {
4878                         ent = r_refdef.scene.entities[i];
4879                         if (!(ent->flags & renderimask))
4880                         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)))
4881                         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))
4882                                 r_refdef.viewcache.entityvisible[i] = true;
4883                 }
4884         }
4885         else
4886         {
4887                 // no worldmodel or it can't check visibility
4888                 for (i = 0;i < r_refdef.scene.numentities;i++)
4889                 {
4890                         ent = r_refdef.scene.entities[i];
4891                         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));
4892                 }
4893         }
4894         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4895                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4896         {
4897                 for (i = 0;i < r_refdef.scene.numentities;i++)
4898                 {
4899                         if (!r_refdef.viewcache.entityvisible[i])
4900                                 continue;
4901                         ent = r_refdef.scene.entities[i];
4902                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4903                         {
4904                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4905                                 if (samples < 0)
4906                                         continue; // temp entities do pvs only
4907                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4908                                         ent->last_trace_visibility = realtime;
4909                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4910                                         r_refdef.viewcache.entityvisible[i] = 0;
4911                         }
4912                 }
4913         }
4914 }
4915
4916 /// only used if skyrendermasked, and normally returns false
4917 int R_DrawBrushModelsSky (void)
4918 {
4919         int i, sky;
4920         entity_render_t *ent;
4921
4922         sky = false;
4923         for (i = 0;i < r_refdef.scene.numentities;i++)
4924         {
4925                 if (!r_refdef.viewcache.entityvisible[i])
4926                         continue;
4927                 ent = r_refdef.scene.entities[i];
4928                 if (!ent->model || !ent->model->DrawSky)
4929                         continue;
4930                 ent->model->DrawSky(ent);
4931                 sky = true;
4932         }
4933         return sky;
4934 }
4935
4936 static void R_DrawNoModel(entity_render_t *ent);
4937 static void R_DrawModels(void)
4938 {
4939         int i;
4940         entity_render_t *ent;
4941
4942         for (i = 0;i < r_refdef.scene.numentities;i++)
4943         {
4944                 if (!r_refdef.viewcache.entityvisible[i])
4945                         continue;
4946                 ent = r_refdef.scene.entities[i];
4947                 r_refdef.stats.entities++;
4948                 /*
4949                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4950                 {
4951                         vec3_t f, l, u, o;
4952                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4953                         Con_Printf("R_DrawModels\n");
4954                         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]);
4955                         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);
4956                         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);
4957                 }
4958                 */
4959                 if (ent->model && ent->model->Draw != NULL)
4960                         ent->model->Draw(ent);
4961                 else
4962                         R_DrawNoModel(ent);
4963         }
4964 }
4965
4966 static void R_DrawModelsDepth(void)
4967 {
4968         int i;
4969         entity_render_t *ent;
4970
4971         for (i = 0;i < r_refdef.scene.numentities;i++)
4972         {
4973                 if (!r_refdef.viewcache.entityvisible[i])
4974                         continue;
4975                 ent = r_refdef.scene.entities[i];
4976                 if (ent->model && ent->model->DrawDepth != NULL)
4977                         ent->model->DrawDepth(ent);
4978         }
4979 }
4980
4981 static void R_DrawModelsDebug(void)
4982 {
4983         int i;
4984         entity_render_t *ent;
4985
4986         for (i = 0;i < r_refdef.scene.numentities;i++)
4987         {
4988                 if (!r_refdef.viewcache.entityvisible[i])
4989                         continue;
4990                 ent = r_refdef.scene.entities[i];
4991                 if (ent->model && ent->model->DrawDebug != NULL)
4992                         ent->model->DrawDebug(ent);
4993         }
4994 }
4995
4996 static void R_DrawModelsAddWaterPlanes(void)
4997 {
4998         int i;
4999         entity_render_t *ent;
5000
5001         for (i = 0;i < r_refdef.scene.numentities;i++)
5002         {
5003                 if (!r_refdef.viewcache.entityvisible[i])
5004                         continue;
5005                 ent = r_refdef.scene.entities[i];
5006                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5007                         ent->model->DrawAddWaterPlanes(ent);
5008         }
5009 }
5010
5011 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5012 {
5013         if (r_hdr_irisadaptation.integer)
5014         {
5015                 vec3_t ambient;
5016                 vec3_t diffuse;
5017                 vec3_t diffusenormal;
5018                 vec_t brightness;
5019                 vec_t goal;
5020                 vec_t current;
5021                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5022                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5023                 brightness = max(0.0000001f, brightness);
5024                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5025                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5026                 current = r_hdr_irisadaptation_value.value;
5027                 if (current < goal)
5028                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5029                 else if (current > goal)
5030                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5031                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5032                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5033         }
5034         else if (r_hdr_irisadaptation_value.value != 1.0f)
5035                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5036 }
5037
5038 static void R_View_SetFrustum(const int *scissor)
5039 {
5040         int i;
5041         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5042         vec3_t forward, left, up, origin, v;
5043
5044         if(scissor)
5045         {
5046                 // flipped x coordinates (because x points left here)
5047                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5048                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5049
5050                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5051                 switch(vid.renderpath)
5052                 {
5053                         case RENDERPATH_D3D9:
5054                         case RENDERPATH_D3D10:
5055                         case RENDERPATH_D3D11:
5056                                 // non-flipped y coordinates
5057                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5058                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5059                                 break;
5060                         case RENDERPATH_SOFT:
5061                         case RENDERPATH_GL11:
5062                         case RENDERPATH_GL13:
5063                         case RENDERPATH_GL20:
5064                         case RENDERPATH_GLES1:
5065                         case RENDERPATH_GLES2:
5066                                 // non-flipped y coordinates
5067                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5068                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5069                                 break;
5070                 }
5071         }
5072
5073         // we can't trust r_refdef.view.forward and friends in reflected scenes
5074         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5075
5076 #if 0
5077         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5078         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5079         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5080         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5081         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5082         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5083         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5084         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5085         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5086         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5087         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5088         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5089 #endif
5090
5091 #if 0
5092         zNear = r_refdef.nearclip;
5093         nudge = 1.0 - 1.0 / (1<<23);
5094         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5095         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5096         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5097         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5098         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5099         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5100         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5101         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5102 #endif
5103
5104
5105
5106 #if 0
5107         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5108         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5109         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5110         r_refdef.view.frustum[0].dist = m[15] - m[12];
5111
5112         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5113         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5114         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5115         r_refdef.view.frustum[1].dist = m[15] + m[12];
5116
5117         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5118         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5119         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5120         r_refdef.view.frustum[2].dist = m[15] - m[13];
5121
5122         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5123         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5124         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5125         r_refdef.view.frustum[3].dist = m[15] + m[13];
5126
5127         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5128         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5129         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5130         r_refdef.view.frustum[4].dist = m[15] - m[14];
5131
5132         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5133         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5134         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5135         r_refdef.view.frustum[5].dist = m[15] + m[14];
5136 #endif
5137
5138         if (r_refdef.view.useperspective)
5139         {
5140                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5141                 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]);
5142                 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]);
5143                 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]);
5144                 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]);
5145
5146                 // then the normals from the corners relative to origin
5147                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5148                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5149                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5150                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5151
5152                 // in a NORMAL view, forward cross left == up
5153                 // in a REFLECTED view, forward cross left == down
5154                 // so our cross products above need to be adjusted for a left handed coordinate system
5155                 CrossProduct(forward, left, v);
5156                 if(DotProduct(v, up) < 0)
5157                 {
5158                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5159                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5160                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5161                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5162                 }
5163
5164                 // Leaving those out was a mistake, those were in the old code, and they
5165                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5166                 // I couldn't reproduce it after adding those normalizations. --blub
5167                 VectorNormalize(r_refdef.view.frustum[0].normal);
5168                 VectorNormalize(r_refdef.view.frustum[1].normal);
5169                 VectorNormalize(r_refdef.view.frustum[2].normal);
5170                 VectorNormalize(r_refdef.view.frustum[3].normal);
5171
5172                 // make the corners absolute
5173                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5174                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5175                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5176                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5177
5178                 // one more normal
5179                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5180
5181                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5182                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5183                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5184                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5185                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5186         }
5187         else
5188         {
5189                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5190                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5191                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5192                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5193                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5194                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5195                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5196                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5197                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5198                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5199         }
5200         r_refdef.view.numfrustumplanes = 5;
5201
5202         if (r_refdef.view.useclipplane)
5203         {
5204                 r_refdef.view.numfrustumplanes = 6;
5205                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5206         }
5207
5208         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5209                 PlaneClassify(r_refdef.view.frustum + i);
5210
5211         // LordHavoc: note to all quake engine coders, Quake had a special case
5212         // for 90 degrees which assumed a square view (wrong), so I removed it,
5213         // Quake2 has it disabled as well.
5214
5215         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5216         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5217         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5218         //PlaneClassify(&frustum[0]);
5219
5220         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5221         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5222         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5223         //PlaneClassify(&frustum[1]);
5224
5225         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5226         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5227         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5228         //PlaneClassify(&frustum[2]);
5229
5230         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5231         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5232         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5233         //PlaneClassify(&frustum[3]);
5234
5235         // nearclip plane
5236         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5237         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5238         //PlaneClassify(&frustum[4]);
5239 }
5240
5241 void R_View_UpdateWithScissor(const int *myscissor)
5242 {
5243         R_Main_ResizeViewCache();
5244         R_View_SetFrustum(myscissor);
5245         R_View_WorldVisibility(r_refdef.view.useclipplane);
5246         R_View_UpdateEntityVisible();
5247         R_View_UpdateEntityLighting();
5248 }
5249
5250 void R_View_Update(void)
5251 {
5252         R_Main_ResizeViewCache();
5253         R_View_SetFrustum(NULL);
5254         R_View_WorldVisibility(r_refdef.view.useclipplane);
5255         R_View_UpdateEntityVisible();
5256         R_View_UpdateEntityLighting();
5257 }
5258
5259 float viewscalefpsadjusted = 1.0f;
5260
5261 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5262 {
5263         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5264         scale = bound(0.03125f, scale, 1.0f);
5265         *outwidth = (int)ceil(width * scale);
5266         *outheight = (int)ceil(height * scale);
5267 }
5268
5269 void R_Mesh_SetMainRenderTargets(void)
5270 {
5271         if (r_bloomstate.fbo_framebuffer)
5272                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5273         else
5274                 R_Mesh_ResetRenderTargets();
5275 }
5276
5277 void R_SetupView(qboolean allowwaterclippingplane)
5278 {
5279         const float *customclipplane = NULL;
5280         float plane[4];
5281         int scaledwidth, scaledheight;
5282         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5283         {
5284                 // LordHavoc: couldn't figure out how to make this approach the
5285                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5286                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5287                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5288                         dist = r_refdef.view.clipplane.dist;
5289                 plane[0] = r_refdef.view.clipplane.normal[0];
5290                 plane[1] = r_refdef.view.clipplane.normal[1];
5291                 plane[2] = r_refdef.view.clipplane.normal[2];
5292                 plane[3] = -dist;
5293                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5294         }
5295
5296         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5297         if (!r_refdef.view.useperspective)
5298                 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);
5299         else if (vid.stencil && r_useinfinitefarclip.integer)
5300                 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);
5301         else
5302                 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);
5303         R_Mesh_SetMainRenderTargets();
5304         R_SetViewport(&r_refdef.view.viewport);
5305         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5306         {
5307                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5308                 float screenplane[4];
5309                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5310                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5311                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5312                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5313                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5314         }
5315 }
5316
5317 void R_EntityMatrix(const matrix4x4_t *matrix)
5318 {
5319         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5320         {
5321                 gl_modelmatrixchanged = false;
5322                 gl_modelmatrix = *matrix;
5323                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5324                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5325                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5326                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5327                 CHECKGLERROR
5328                 switch(vid.renderpath)
5329                 {
5330                 case RENDERPATH_D3D9:
5331 #ifdef SUPPORTD3D
5332                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5333                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5334 #endif
5335                         break;
5336                 case RENDERPATH_D3D10:
5337                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5338                         break;
5339                 case RENDERPATH_D3D11:
5340                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5341                         break;
5342                 case RENDERPATH_GL11:
5343                 case RENDERPATH_GL13:
5344                 case RENDERPATH_GLES1:
5345                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5346                         break;
5347                 case RENDERPATH_SOFT:
5348                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5349                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5350                         break;
5351                 case RENDERPATH_GL20:
5352                 case RENDERPATH_GLES2:
5353                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5354                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5355                         break;
5356                 }
5357         }
5358 }
5359
5360 void R_ResetViewRendering2D(void)
5361 {
5362         r_viewport_t viewport;
5363         DrawQ_Finish();
5364
5365         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5366         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);
5367         R_Mesh_ResetRenderTargets();
5368         R_SetViewport(&viewport);
5369         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5370         GL_Color(1, 1, 1, 1);
5371         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5372         GL_BlendFunc(GL_ONE, GL_ZERO);
5373         GL_ScissorTest(false);
5374         GL_DepthMask(false);
5375         GL_DepthRange(0, 1);
5376         GL_DepthTest(false);
5377         GL_DepthFunc(GL_LEQUAL);
5378         R_EntityMatrix(&identitymatrix);
5379         R_Mesh_ResetTextureState();
5380         GL_PolygonOffset(0, 0);
5381         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5382         switch(vid.renderpath)
5383         {
5384         case RENDERPATH_GL11:
5385         case RENDERPATH_GL13:
5386         case RENDERPATH_GL20:
5387         case RENDERPATH_GLES1:
5388         case RENDERPATH_GLES2:
5389                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5390                 break;
5391         case RENDERPATH_D3D9:
5392         case RENDERPATH_D3D10:
5393         case RENDERPATH_D3D11:
5394         case RENDERPATH_SOFT:
5395                 break;
5396         }
5397         GL_CullFace(GL_NONE);
5398 }
5399
5400 void R_ResetViewRendering3D(void)
5401 {
5402         DrawQ_Finish();
5403
5404         R_SetupView(true);
5405         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5406         GL_Color(1, 1, 1, 1);
5407         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5408         GL_BlendFunc(GL_ONE, GL_ZERO);
5409         GL_ScissorTest(true);
5410         GL_DepthMask(true);
5411         GL_DepthRange(0, 1);
5412         GL_DepthTest(true);
5413         GL_DepthFunc(GL_LEQUAL);
5414         R_EntityMatrix(&identitymatrix);
5415         R_Mesh_ResetTextureState();
5416         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5417         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5418         switch(vid.renderpath)
5419         {
5420         case RENDERPATH_GL11:
5421         case RENDERPATH_GL13:
5422         case RENDERPATH_GL20:
5423         case RENDERPATH_GLES1:
5424         case RENDERPATH_GLES2:
5425                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5426                 break;
5427         case RENDERPATH_D3D9:
5428         case RENDERPATH_D3D10:
5429         case RENDERPATH_D3D11:
5430         case RENDERPATH_SOFT:
5431                 break;
5432         }
5433         GL_CullFace(r_refdef.view.cullface_back);
5434 }
5435
5436 /*
5437 ================
5438 R_RenderView_UpdateViewVectors
5439 ================
5440 */
5441 static void R_RenderView_UpdateViewVectors(void)
5442 {
5443         // break apart the view matrix into vectors for various purposes
5444         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5445         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5446         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5447         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5448         // make an inverted copy of the view matrix for tracking sprites
5449         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5450 }
5451
5452 void R_RenderScene(void);
5453 void R_RenderWaterPlanes(void);
5454
5455 static void R_Water_StartFrame(void)
5456 {
5457         int i;
5458         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5459         r_waterstate_waterplane_t *p;
5460
5461         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5462                 return;
5463
5464         switch(vid.renderpath)
5465         {
5466         case RENDERPATH_GL20:
5467         case RENDERPATH_D3D9:
5468         case RENDERPATH_D3D10:
5469         case RENDERPATH_D3D11:
5470         case RENDERPATH_SOFT:
5471         case RENDERPATH_GLES2:
5472                 break;
5473         case RENDERPATH_GL11:
5474         case RENDERPATH_GL13:
5475         case RENDERPATH_GLES1:
5476                 return;
5477         }
5478
5479         // set waterwidth and waterheight to the water resolution that will be
5480         // used (often less than the screen resolution for faster rendering)
5481         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5482
5483         // calculate desired texture sizes
5484         // can't use water if the card does not support the texture size
5485         if (!r_water.integer || r_showsurfaces.integer)
5486                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5487         else if (vid.support.arb_texture_non_power_of_two)
5488         {
5489                 texturewidth = waterwidth;
5490                 textureheight = waterheight;
5491                 camerawidth = waterwidth;
5492                 cameraheight = waterheight;
5493         }
5494         else
5495         {
5496                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5497                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5498                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5499                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5500         }
5501
5502         // allocate textures as needed
5503         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5504         {
5505                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5506                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5507                 {
5508                         if (p->texture_refraction)
5509                                 R_FreeTexture(p->texture_refraction);
5510                         p->texture_refraction = NULL;
5511                         if (p->texture_reflection)
5512                                 R_FreeTexture(p->texture_reflection);
5513                         p->texture_reflection = NULL;
5514                         if (p->texture_camera)
5515                                 R_FreeTexture(p->texture_camera);
5516                         p->texture_camera = NULL;
5517                 }
5518                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5519                 r_waterstate.texturewidth = texturewidth;
5520                 r_waterstate.textureheight = textureheight;
5521                 r_waterstate.camerawidth = camerawidth;
5522                 r_waterstate.cameraheight = cameraheight;
5523         }
5524
5525         if (r_waterstate.texturewidth)
5526         {
5527                 int scaledwidth, scaledheight;
5528
5529                 r_waterstate.enabled = true;
5530
5531                 // when doing a reduced render (HDR) we want to use a smaller area
5532                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5533                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5534                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5535
5536                 // set up variables that will be used in shader setup
5537                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5538                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5539                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5540                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5541         }
5542
5543         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5544         r_waterstate.numwaterplanes = 0;
5545 }
5546
5547 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5548 {
5549         int triangleindex, planeindex;
5550         const int *e;
5551         vec3_t vert[3];
5552         vec3_t normal;
5553         vec3_t center;
5554         mplane_t plane;
5555         r_waterstate_waterplane_t *p;
5556         texture_t *t = R_GetCurrentTexture(surface->texture);
5557
5558         // just use the first triangle with a valid normal for any decisions
5559         VectorClear(normal);
5560         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5561         {
5562                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5563                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5564                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5565                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5566                 if (VectorLength2(normal) >= 0.001)
5567                         break;
5568         }
5569
5570         VectorCopy(normal, plane.normal);
5571         VectorNormalize(plane.normal);
5572         plane.dist = DotProduct(vert[0], plane.normal);
5573         PlaneClassify(&plane);
5574         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5575         {
5576                 // skip backfaces (except if nocullface is set)
5577                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5578                         return;
5579                 VectorNegate(plane.normal, plane.normal);
5580                 plane.dist *= -1;
5581                 PlaneClassify(&plane);
5582         }
5583
5584
5585         // find a matching plane if there is one
5586         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5587                 if(p->camera_entity == t->camera_entity)
5588                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5589                                 break;
5590         if (planeindex >= r_waterstate.maxwaterplanes)
5591                 return; // nothing we can do, out of planes
5592
5593         // if this triangle does not fit any known plane rendered this frame, add one
5594         if (planeindex >= r_waterstate.numwaterplanes)
5595         {
5596                 // store the new plane
5597                 r_waterstate.numwaterplanes++;
5598                 p->plane = plane;
5599                 // clear materialflags and pvs
5600                 p->materialflags = 0;
5601                 p->pvsvalid = false;
5602                 p->camera_entity = t->camera_entity;
5603                 VectorCopy(surface->mins, p->mins);
5604                 VectorCopy(surface->maxs, p->maxs);
5605         }
5606         else
5607         {
5608                 // merge mins/maxs
5609                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5610                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5611                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5612                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5613                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5614                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5615         }
5616         // merge this surface's materialflags into the waterplane
5617         p->materialflags |= t->currentmaterialflags;
5618         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5619         {
5620                 // merge this surface's PVS into the waterplane
5621                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5622                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5623                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5624                 {
5625                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5626                         p->pvsvalid = true;
5627                 }
5628         }
5629 }
5630
5631 extern cvar_t r_drawparticles;
5632 extern cvar_t r_drawdecals;
5633
5634 static void R_Water_ProcessPlanes(void)
5635 {
5636         int myscissor[4];
5637         r_refdef_view_t originalview;
5638         r_refdef_view_t myview;
5639         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;
5640         r_waterstate_waterplane_t *p;
5641         vec3_t visorigin;
5642
5643         originalview = r_refdef.view;
5644
5645         // lowquality hack, temporarily shut down some cvars and restore afterwards
5646         qualityreduction = r_water_lowquality.integer;
5647         if (qualityreduction > 0)
5648         {
5649                 if (qualityreduction >= 1)
5650                 {
5651                         old_r_shadows = r_shadows.integer;
5652                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5653                         old_r_dlight = r_shadow_realtime_dlight.integer;
5654                         Cvar_SetValueQuick(&r_shadows, 0);
5655                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5656                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5657                 }
5658                 if (qualityreduction >= 2)
5659                 {
5660                         old_r_dynamic = r_dynamic.integer;
5661                         old_r_particles = r_drawparticles.integer;
5662                         old_r_decals = r_drawdecals.integer;
5663                         Cvar_SetValueQuick(&r_dynamic, 0);
5664                         Cvar_SetValueQuick(&r_drawparticles, 0);
5665                         Cvar_SetValueQuick(&r_drawdecals, 0);
5666                 }
5667         }
5668
5669         // make sure enough textures are allocated
5670         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5671         {
5672                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5673                 {
5674                         if (!p->texture_refraction)
5675                                 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);
5676                         if (!p->texture_refraction)
5677                                 goto error;
5678                 }
5679                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5680                 {
5681                         if (!p->texture_camera)
5682                                 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);
5683                         if (!p->texture_camera)
5684                                 goto error;
5685                 }
5686
5687                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5688                 {
5689                         if (!p->texture_reflection)
5690                                 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);
5691                         if (!p->texture_reflection)
5692                                 goto error;
5693                 }
5694         }
5695
5696         // render views
5697         r_refdef.view = originalview;
5698         r_refdef.view.showdebug = false;
5699         r_refdef.view.width = r_waterstate.waterwidth;
5700         r_refdef.view.height = r_waterstate.waterheight;
5701         r_refdef.view.useclipplane = true;
5702         myview = r_refdef.view;
5703         r_waterstate.renderingscene = true;
5704         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5705         {
5706                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5707                 {
5708                         r_refdef.view = myview;
5709                         if(r_water_scissormode.integer)
5710                         {
5711                                 R_SetupView(true);
5712                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5713                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5714                         }
5715
5716                         // render reflected scene and copy into texture
5717                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5718                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5719                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5720                         r_refdef.view.clipplane = p->plane;
5721                         // reverse the cullface settings for this render
5722                         r_refdef.view.cullface_front = GL_FRONT;
5723                         r_refdef.view.cullface_back = GL_BACK;
5724                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5725                         {
5726                                 r_refdef.view.usecustompvs = true;
5727                                 if (p->pvsvalid)
5728                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5729                                 else
5730                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5731                         }
5732
5733                         R_ResetViewRendering3D();
5734                         R_ClearScreen(r_refdef.fogenabled);
5735                         if(r_water_scissormode.integer & 2)
5736                                 R_View_UpdateWithScissor(myscissor);
5737                         else
5738                                 R_View_Update();
5739                         if(r_water_scissormode.integer & 1)
5740                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5741                         R_RenderScene();
5742
5743                         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);
5744                 }
5745
5746                 // render the normal view scene and copy into texture
5747                 // (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)
5748                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5749                 {
5750                         r_refdef.view = myview;
5751                         if(r_water_scissormode.integer)
5752                         {
5753                                 R_SetupView(true);
5754                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5755                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5756                         }
5757
5758                         r_waterstate.renderingrefraction = true;
5759
5760                         r_refdef.view.clipplane = p->plane;
5761                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5762                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5763
5764                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5765                         {
5766                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5767                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5768                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5769                                 R_RenderView_UpdateViewVectors();
5770                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5771                                 {
5772                                         r_refdef.view.usecustompvs = true;
5773                                         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);
5774                                 }
5775                         }
5776
5777                         PlaneClassify(&r_refdef.view.clipplane);
5778
5779                         R_ResetViewRendering3D();
5780                         R_ClearScreen(r_refdef.fogenabled);
5781                         if(r_water_scissormode.integer & 2)
5782                                 R_View_UpdateWithScissor(myscissor);
5783                         else
5784                                 R_View_Update();
5785                         if(r_water_scissormode.integer & 1)
5786                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5787                         R_RenderScene();
5788
5789                         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);
5790                         r_waterstate.renderingrefraction = false;
5791                 }
5792                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5793                 {
5794                         r_refdef.view = myview;
5795
5796                         r_refdef.view.clipplane = p->plane;
5797                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5798                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5799
5800                         r_refdef.view.width = r_waterstate.camerawidth;
5801                         r_refdef.view.height = r_waterstate.cameraheight;
5802                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5803                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5804
5805                         if(p->camera_entity)
5806                         {
5807                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5808                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5809                         }
5810
5811                         // note: all of the view is used for displaying... so
5812                         // there is no use in scissoring
5813
5814                         // reverse the cullface settings for this render
5815                         r_refdef.view.cullface_front = GL_FRONT;
5816                         r_refdef.view.cullface_back = GL_BACK;
5817                         // also reverse the view matrix
5818                         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
5819                         R_RenderView_UpdateViewVectors();
5820                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5821                         {
5822                                 r_refdef.view.usecustompvs = true;
5823                                 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);
5824                         }
5825                         
5826                         // camera needs no clipplane
5827                         r_refdef.view.useclipplane = false;
5828
5829                         PlaneClassify(&r_refdef.view.clipplane);
5830
5831                         R_ResetViewRendering3D();
5832                         R_ClearScreen(r_refdef.fogenabled);
5833                         R_View_Update();
5834                         R_RenderScene();
5835
5836                         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);
5837                         r_waterstate.renderingrefraction = false;
5838                 }
5839
5840         }
5841         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5842         r_waterstate.renderingscene = false;
5843         r_refdef.view = originalview;
5844         R_ResetViewRendering3D();
5845         R_ClearScreen(r_refdef.fogenabled);
5846         R_View_Update();
5847         goto finish;
5848 error:
5849         r_refdef.view = originalview;
5850         r_waterstate.renderingscene = false;
5851         Cvar_SetValueQuick(&r_water, 0);
5852         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5853 finish:
5854         // lowquality hack, restore cvars
5855         if (qualityreduction > 0)
5856         {
5857                 if (qualityreduction >= 1)
5858                 {
5859                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5860                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5861                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5862                 }
5863                 if (qualityreduction >= 2)
5864                 {
5865                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5866                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5867                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5868                 }
5869         }
5870 }
5871
5872 void R_Bloom_StartFrame(void)
5873 {
5874         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5875         int viewwidth, viewheight;
5876         textype_t textype;
5877
5878         if (r_viewscale_fpsscaling.integer)
5879         {
5880                 double actualframetime;
5881                 double targetframetime;
5882                 double adjust;
5883                 actualframetime = r_refdef.lastdrawscreentime;
5884                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5885                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5886                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5887                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5888                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5889                 viewscalefpsadjusted += adjust;
5890                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5891         }
5892         else
5893                 viewscalefpsadjusted = 1.0f;
5894
5895         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5896
5897         switch(vid.renderpath)
5898         {
5899         case RENDERPATH_GL20:
5900         case RENDERPATH_D3D9:
5901         case RENDERPATH_D3D10:
5902         case RENDERPATH_D3D11:
5903         case RENDERPATH_SOFT:
5904         case RENDERPATH_GLES2:
5905                 break;
5906         case RENDERPATH_GL11:
5907         case RENDERPATH_GL13:
5908         case RENDERPATH_GLES1:
5909                 return;
5910         }
5911
5912         // set bloomwidth and bloomheight to the bloom resolution that will be
5913         // used (often less than the screen resolution for faster rendering)
5914         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5915         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5916         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5917         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5918         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5919
5920         // calculate desired texture sizes
5921         if (vid.support.arb_texture_non_power_of_two)
5922         {
5923                 screentexturewidth = vid.width;
5924                 screentextureheight = vid.height;
5925                 bloomtexturewidth = r_bloomstate.bloomwidth;
5926                 bloomtextureheight = r_bloomstate.bloomheight;
5927         }
5928         else
5929         {
5930                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5931                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5932                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5933                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5934         }
5935
5936         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))
5937         {
5938                 Cvar_SetValueQuick(&r_hdr, 0);
5939                 Cvar_SetValueQuick(&r_bloom, 0);
5940                 Cvar_SetValueQuick(&r_motionblur, 0);
5941                 Cvar_SetValueQuick(&r_damageblur, 0);
5942         }
5943
5944         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)
5945                 screentexturewidth = screentextureheight = 0;
5946         if (!r_hdr.integer && !r_bloom.integer)
5947                 bloomtexturewidth = bloomtextureheight = 0;
5948
5949         textype = TEXTYPE_COLORBUFFER;
5950         switch (vid.renderpath)
5951         {
5952         case RENDERPATH_GL20:
5953         case RENDERPATH_GLES2:
5954                 if (vid.support.ext_framebuffer_object)
5955                 {
5956                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5957                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5958                 }
5959                 break;
5960         case RENDERPATH_GL11:
5961         case RENDERPATH_GL13:
5962         case RENDERPATH_GLES1:
5963         case RENDERPATH_D3D9:
5964         case RENDERPATH_D3D10:
5965         case RENDERPATH_D3D11:
5966         case RENDERPATH_SOFT:
5967                 break;
5968         }
5969
5970         // allocate textures as needed
5971         if (r_bloomstate.screentexturewidth != screentexturewidth
5972          || r_bloomstate.screentextureheight != screentextureheight
5973          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5974          || r_bloomstate.bloomtextureheight != bloomtextureheight
5975          || r_bloomstate.texturetype != textype
5976          || r_bloomstate.viewfbo != r_viewfbo.integer)
5977         {
5978                 if (r_bloomstate.texture_bloom)
5979                         R_FreeTexture(r_bloomstate.texture_bloom);
5980                 r_bloomstate.texture_bloom = NULL;
5981                 if (r_bloomstate.texture_screen)
5982                         R_FreeTexture(r_bloomstate.texture_screen);
5983                 r_bloomstate.texture_screen = NULL;
5984                 if (r_bloomstate.fbo_framebuffer)
5985                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5986                 r_bloomstate.fbo_framebuffer = 0;
5987                 if (r_bloomstate.texture_framebuffercolor)
5988                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5989                 r_bloomstate.texture_framebuffercolor = NULL;
5990                 if (r_bloomstate.texture_framebufferdepth)
5991                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5992                 r_bloomstate.texture_framebufferdepth = NULL;
5993                 r_bloomstate.screentexturewidth = screentexturewidth;
5994                 r_bloomstate.screentextureheight = screentextureheight;
5995                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5996                         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);
5997                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5998                 {
5999                         // FIXME: choose depth bits based on a cvar
6000                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6001                         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);
6002                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6003                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6004                         // render depth into one texture and normalmap into the other
6005                         if (qglDrawBuffer)
6006                         {
6007                                 int status;
6008                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6009                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6010                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
6011                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
6012                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6013                         }
6014                 }
6015                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6016                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6017                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6018                         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);
6019                 r_bloomstate.viewfbo = r_viewfbo.integer;
6020                 r_bloomstate.texturetype = textype;
6021         }
6022
6023         // when doing a reduced render (HDR) we want to use a smaller area
6024         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6025         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6026         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6027         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6028         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6029
6030         // set up a texcoord array for the full resolution screen image
6031         // (we have to keep this around to copy back during final render)
6032         r_bloomstate.screentexcoord2f[0] = 0;
6033         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6034         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6035         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6036         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6037         r_bloomstate.screentexcoord2f[5] = 0;
6038         r_bloomstate.screentexcoord2f[6] = 0;
6039         r_bloomstate.screentexcoord2f[7] = 0;
6040
6041         // set up a texcoord array for the reduced resolution bloom image
6042         // (which will be additive blended over the screen image)
6043         r_bloomstate.bloomtexcoord2f[0] = 0;
6044         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6045         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6046         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6047         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6048         r_bloomstate.bloomtexcoord2f[5] = 0;
6049         r_bloomstate.bloomtexcoord2f[6] = 0;
6050         r_bloomstate.bloomtexcoord2f[7] = 0;
6051
6052         switch(vid.renderpath)
6053         {
6054         case RENDERPATH_GL11:
6055         case RENDERPATH_GL13:
6056         case RENDERPATH_GL20:
6057         case RENDERPATH_SOFT:
6058         case RENDERPATH_GLES1:
6059         case RENDERPATH_GLES2:
6060                 break;
6061         case RENDERPATH_D3D9:
6062         case RENDERPATH_D3D10:
6063         case RENDERPATH_D3D11:
6064                 {
6065                         int i;
6066                         for (i = 0;i < 4;i++)
6067                         {
6068                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6069                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6070                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6071                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6072                         }
6073                 }
6074                 break;
6075         }
6076
6077         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6078         {
6079                 r_bloomstate.enabled = true;
6080                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6081         }
6082
6083         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);
6084
6085         if (r_bloomstate.fbo_framebuffer)
6086                 r_refdef.view.clear = true;
6087 }
6088
6089 void R_Bloom_CopyBloomTexture(float colorscale)
6090 {
6091         r_refdef.stats.bloom++;
6092
6093         // scale down screen texture to the bloom texture size
6094         CHECKGLERROR
6095         R_Mesh_SetMainRenderTargets();
6096         R_SetViewport(&r_bloomstate.viewport);
6097         GL_BlendFunc(GL_ONE, GL_ZERO);
6098         GL_Color(colorscale, colorscale, colorscale, 1);
6099         // 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...
6100         switch(vid.renderpath)
6101         {
6102         case RENDERPATH_GL11:
6103         case RENDERPATH_GL13:
6104         case RENDERPATH_GL20:
6105         case RENDERPATH_GLES1:
6106         case RENDERPATH_GLES2:
6107         case RENDERPATH_SOFT:
6108                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6109                 break;
6110         case RENDERPATH_D3D9:
6111         case RENDERPATH_D3D10:
6112         case RENDERPATH_D3D11:
6113                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6114                 break;
6115         }
6116         // TODO: do boxfilter scale-down in shader?
6117         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6118         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6119         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6120
6121         // we now have a bloom image in the framebuffer
6122         // copy it into the bloom image texture for later processing
6123         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);
6124         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6125 }
6126
6127 void R_Bloom_CopyHDRTexture(void)
6128 {
6129         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);
6130         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6131 }
6132
6133 void R_Bloom_MakeTexture(void)
6134 {
6135         int x, range, dir;
6136         float xoffset, yoffset, r, brighten;
6137
6138         r_refdef.stats.bloom++;
6139
6140         R_ResetViewRendering2D();
6141
6142         // we have a bloom image in the framebuffer
6143         CHECKGLERROR
6144         R_SetViewport(&r_bloomstate.viewport);
6145
6146         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6147         {
6148                 x *= 2;
6149                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6150                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6151                 GL_Color(r,r,r,1);
6152                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6153                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6154                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6155                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6156
6157                 // copy the vertically blurred bloom view to a texture
6158                 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);
6159                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6160         }
6161
6162         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6163         brighten = r_bloom_brighten.value;
6164         if (r_bloomstate.hdr)
6165                 brighten *= r_hdr_range.value;
6166         brighten = sqrt(brighten);
6167         if(range >= 1)
6168                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6169         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6170
6171         for (dir = 0;dir < 2;dir++)
6172         {
6173                 // blend on at multiple vertical offsets to achieve a vertical blur
6174                 // TODO: do offset blends using GLSL
6175                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6176                 GL_BlendFunc(GL_ONE, GL_ZERO);
6177                 for (x = -range;x <= range;x++)
6178                 {
6179                         if (!dir){xoffset = 0;yoffset = x;}
6180                         else {xoffset = x;yoffset = 0;}
6181                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6182                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6183                         // compute a texcoord array with the specified x and y offset
6184                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6185                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6186                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6187                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6188                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6189                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6190                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6191                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6192                         // this r value looks like a 'dot' particle, fading sharply to
6193                         // black at the edges
6194                         // (probably not realistic but looks good enough)
6195                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6196                         //r = brighten/(range*2+1);
6197                         r = brighten / (range * 2 + 1);
6198                         if(range >= 1)
6199                                 r *= (1 - x*x/(float)(range*range));
6200                         GL_Color(r, r, r, 1);
6201                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6202                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6203                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6204                         GL_BlendFunc(GL_ONE, GL_ONE);
6205                 }
6206
6207                 // copy the vertically blurred bloom view to a texture
6208                 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);
6209                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6210         }
6211 }
6212
6213 void R_HDR_RenderBloomTexture(void)
6214 {
6215         int oldwidth, oldheight;
6216         float oldcolorscale;
6217         qboolean oldwaterstate;
6218
6219         oldwaterstate = r_waterstate.enabled;
6220         oldcolorscale = r_refdef.view.colorscale;
6221         oldwidth = r_refdef.view.width;
6222         oldheight = r_refdef.view.height;
6223         r_refdef.view.width = r_bloomstate.bloomwidth;
6224         r_refdef.view.height = r_bloomstate.bloomheight;
6225
6226         if(r_hdr.integer < 2)
6227                 r_waterstate.enabled = false;
6228
6229         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6230         // TODO: add exposure compensation features
6231         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6232
6233         r_refdef.view.showdebug = false;
6234         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6235
6236         R_ResetViewRendering3D();
6237
6238         R_ClearScreen(r_refdef.fogenabled);
6239         if (r_timereport_active)
6240                 R_TimeReport("HDRclear");
6241
6242         R_View_Update();
6243         if (r_timereport_active)
6244                 R_TimeReport("visibility");
6245
6246         // only do secondary renders with HDR if r_hdr is 2 or higher
6247         r_waterstate.numwaterplanes = 0;
6248         if (r_waterstate.enabled)
6249                 R_RenderWaterPlanes();
6250
6251         r_refdef.view.showdebug = true;
6252         R_RenderScene();
6253         r_waterstate.numwaterplanes = 0;
6254
6255         R_ResetViewRendering2D();
6256
6257         R_Bloom_CopyHDRTexture();
6258         R_Bloom_MakeTexture();
6259
6260         // restore the view settings
6261         r_waterstate.enabled = oldwaterstate;
6262         r_refdef.view.width = oldwidth;
6263         r_refdef.view.height = oldheight;
6264         r_refdef.view.colorscale = oldcolorscale;
6265
6266         R_ResetViewRendering3D();
6267
6268         R_ClearScreen(r_refdef.fogenabled);
6269         if (r_timereport_active)
6270                 R_TimeReport("viewclear");
6271 }
6272
6273 static void R_BlendView(void)
6274 {
6275         unsigned int permutation;
6276         float uservecs[4][4];
6277
6278         switch (vid.renderpath)
6279         {
6280         case RENDERPATH_GL20:
6281         case RENDERPATH_D3D9:
6282         case RENDERPATH_D3D10:
6283         case RENDERPATH_D3D11:
6284         case RENDERPATH_SOFT:
6285         case RENDERPATH_GLES2:
6286                 permutation =
6287                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6288                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6289                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6290                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6291                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6292
6293                 if (r_bloomstate.texture_screen)
6294                 {
6295                         // make sure the buffer is available
6296                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6297
6298                         R_ResetViewRendering2D();
6299                         R_Mesh_SetMainRenderTargets();
6300
6301                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6302                         {
6303                                 // declare variables
6304                                 float blur_factor, blur_mouseaccel, blur_velocity;
6305                                 static float blur_average; 
6306                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6307
6308                                 // set a goal for the factoring
6309                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6310                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6311                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6312                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6313                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6314                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6315
6316                                 // from the goal, pick an averaged value between goal and last value
6317                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6318                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6319                                 
6320                                 // enforce minimum amount of blur 
6321                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6322                                 
6323                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6324
6325                                 // calculate values into a standard alpha
6326                                 cl.motionbluralpha = 1 - exp(-
6327                                                 (
6328                                                  (r_motionblur.value * blur_factor / 80)
6329                                                  +
6330                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6331                                                 )
6332                                                 /
6333                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6334                                           );
6335                                 
6336                                 // randomization for the blur value to combat persistent ghosting
6337                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6338                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6339                                 
6340                                 // apply the blur
6341                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6342                                 {
6343                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6344                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6345                                         switch(vid.renderpath)
6346                                         {
6347                                         case RENDERPATH_GL11:
6348                                         case RENDERPATH_GL13:
6349                                         case RENDERPATH_GL20:
6350                                         case RENDERPATH_GLES1:
6351                                         case RENDERPATH_GLES2:
6352                                         case RENDERPATH_SOFT:
6353                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6354                                                 break;
6355                                         case RENDERPATH_D3D9:
6356                                         case RENDERPATH_D3D10:
6357                                         case RENDERPATH_D3D11:
6358                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6359                                                 break;
6360                                         }
6361                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6362                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6363                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6364                                 }
6365                                 
6366                                 // updates old view angles for next pass 
6367                                 VectorCopy(cl.viewangles, blur_oldangles);
6368                         }
6369
6370                         // copy view into the screen texture
6371                         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);
6372                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6373                 }
6374                 else if (!r_bloomstate.texture_bloom)
6375                 {
6376                         // we may still have to do view tint...
6377                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6378                         {
6379                                 // apply a color tint to the whole view
6380                                 R_ResetViewRendering2D();
6381                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6382                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6383                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6384                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6385                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6386                         }
6387                         break; // no screen processing, no bloom, skip it
6388                 }
6389
6390                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6391                 {
6392                         // render simple bloom effect
6393                         // copy the screen and shrink it and darken it for the bloom process
6394                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6395                         // make the bloom texture
6396                         R_Bloom_MakeTexture();
6397                 }
6398
6399 #if _MSC_VER >= 1400
6400 #define sscanf sscanf_s
6401 #endif
6402                 memset(uservecs, 0, sizeof(uservecs));
6403                 if (r_glsl_postprocess_uservec1_enable.integer)
6404                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6405                 if (r_glsl_postprocess_uservec2_enable.integer)
6406                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6407                 if (r_glsl_postprocess_uservec3_enable.integer)
6408                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6409                 if (r_glsl_postprocess_uservec4_enable.integer)
6410                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6411
6412                 R_ResetViewRendering2D();
6413                 GL_Color(1, 1, 1, 1);
6414                 GL_BlendFunc(GL_ONE, GL_ZERO);
6415
6416                 switch(vid.renderpath)
6417                 {
6418                 case RENDERPATH_GL20:
6419                 case RENDERPATH_GLES2:
6420                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6421                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6422                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6423                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6424                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6425                         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]);
6426                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6427                         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]);
6428                         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]);
6429                         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]);
6430                         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]);
6431                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6432                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6433                         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);
6434                         break;
6435                 case RENDERPATH_D3D9:
6436 #ifdef SUPPORTD3D
6437                         // 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...
6438                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6439                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6440                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6441                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6442                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6443                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6444                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6445                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6446                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6447                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6448                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6449                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6450                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6451                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6452 #endif
6453                         break;
6454                 case RENDERPATH_D3D10:
6455                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6456                         break;
6457                 case RENDERPATH_D3D11:
6458                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6459                         break;
6460                 case RENDERPATH_SOFT:
6461                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6462                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6463                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6464                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6465                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6466                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6467                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6468                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6469                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6470                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6471                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6472                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6473                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6474                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6475                         break;
6476                 default:
6477                         break;
6478                 }
6479                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6480                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6481                 break;
6482         case RENDERPATH_GL11:
6483         case RENDERPATH_GL13:
6484         case RENDERPATH_GLES1:
6485                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6486                 {
6487                         // apply a color tint to the whole view
6488                         R_ResetViewRendering2D();
6489                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6490                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6491                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6492                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6493                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6494                 }
6495                 break;
6496         }
6497 }
6498
6499 matrix4x4_t r_waterscrollmatrix;
6500
6501 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6502 {
6503         if (r_refdef.fog_density)
6504         {
6505                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6506                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6507                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6508
6509                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6510                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6511                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6512                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6513
6514                 {
6515                         vec3_t fogvec;
6516                         VectorCopy(r_refdef.fogcolor, fogvec);
6517                         //   color.rgb *= ContrastBoost * SceneBrightness;
6518                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6519                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6520                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6521                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6522                 }
6523         }
6524 }
6525
6526 void R_UpdateVariables(void)
6527 {
6528         R_Textures_Frame();
6529
6530         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6531
6532         r_refdef.farclip = r_farclip_base.value;
6533         if (r_refdef.scene.worldmodel)
6534                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6535         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6536
6537         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6538                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6539         r_refdef.polygonfactor = 0;
6540         r_refdef.polygonoffset = 0;
6541         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6542         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6543
6544         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6545         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6546         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6547         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6548         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6549         if (FAKELIGHT_ENABLED)
6550         {
6551                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6552         }
6553         if (r_showsurfaces.integer)
6554         {
6555                 r_refdef.scene.rtworld = false;
6556                 r_refdef.scene.rtworldshadows = false;
6557                 r_refdef.scene.rtdlight = false;
6558                 r_refdef.scene.rtdlightshadows = false;
6559                 r_refdef.lightmapintensity = 0;
6560         }
6561
6562         if (gamemode == GAME_NEHAHRA)
6563         {
6564                 if (gl_fogenable.integer)
6565                 {
6566                         r_refdef.oldgl_fogenable = true;
6567                         r_refdef.fog_density = gl_fogdensity.value;
6568                         r_refdef.fog_red = gl_fogred.value;
6569                         r_refdef.fog_green = gl_foggreen.value;
6570                         r_refdef.fog_blue = gl_fogblue.value;
6571                         r_refdef.fog_alpha = 1;
6572                         r_refdef.fog_start = 0;
6573                         r_refdef.fog_end = gl_skyclip.value;
6574                         r_refdef.fog_height = 1<<30;
6575                         r_refdef.fog_fadedepth = 128;
6576                 }
6577                 else if (r_refdef.oldgl_fogenable)
6578                 {
6579                         r_refdef.oldgl_fogenable = false;
6580                         r_refdef.fog_density = 0;
6581                         r_refdef.fog_red = 0;
6582                         r_refdef.fog_green = 0;
6583                         r_refdef.fog_blue = 0;
6584                         r_refdef.fog_alpha = 0;
6585                         r_refdef.fog_start = 0;
6586                         r_refdef.fog_end = 0;
6587                         r_refdef.fog_height = 1<<30;
6588                         r_refdef.fog_fadedepth = 128;
6589                 }
6590         }
6591
6592         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6593         r_refdef.fog_start = max(0, r_refdef.fog_start);
6594         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6595
6596         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6597
6598         if (r_refdef.fog_density && r_drawfog.integer)
6599         {
6600                 r_refdef.fogenabled = true;
6601                 // this is the point where the fog reaches 0.9986 alpha, which we
6602                 // consider a good enough cutoff point for the texture
6603                 // (0.9986 * 256 == 255.6)
6604                 if (r_fog_exp2.integer)
6605                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6606                 else
6607                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6608                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6609                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6610                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6611                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6612                         R_BuildFogHeightTexture();
6613                 // fog color was already set
6614                 // update the fog texture
6615                 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)
6616                         R_BuildFogTexture();
6617                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6618                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6619         }
6620         else
6621                 r_refdef.fogenabled = false;
6622
6623         switch(vid.renderpath)
6624         {
6625         case RENDERPATH_GL20:
6626         case RENDERPATH_D3D9:
6627         case RENDERPATH_D3D10:
6628         case RENDERPATH_D3D11:
6629         case RENDERPATH_SOFT:
6630         case RENDERPATH_GLES2:
6631                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6632                 {
6633                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6634                         {
6635                                 // build GLSL gamma texture
6636 #define RAMPWIDTH 256
6637                                 unsigned short ramp[RAMPWIDTH * 3];
6638                                 unsigned char rampbgr[RAMPWIDTH][4];
6639                                 int i;
6640
6641                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6642
6643                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6644                                 for(i = 0; i < RAMPWIDTH; ++i)
6645                                 {
6646                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6647                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6648                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6649                                         rampbgr[i][3] = 0;
6650                                 }
6651                                 if (r_texture_gammaramps)
6652                                 {
6653                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6654                                 }
6655                                 else
6656                                 {
6657                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6658                                 }
6659                         }
6660                 }
6661                 else
6662                 {
6663                         // remove GLSL gamma texture
6664                 }
6665                 break;
6666         case RENDERPATH_GL11:
6667         case RENDERPATH_GL13:
6668         case RENDERPATH_GLES1:
6669                 break;
6670         }
6671 }
6672
6673 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6674 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6675 /*
6676 ================
6677 R_SelectScene
6678 ================
6679 */
6680 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6681         if( scenetype != r_currentscenetype ) {
6682                 // store the old scenetype
6683                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6684                 r_currentscenetype = scenetype;
6685                 // move in the new scene
6686                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6687         }
6688 }
6689
6690 /*
6691 ================
6692 R_GetScenePointer
6693 ================
6694 */
6695 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6696 {
6697         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6698         if( scenetype == r_currentscenetype ) {
6699                 return &r_refdef.scene;
6700         } else {
6701                 return &r_scenes_store[ scenetype ];
6702         }
6703 }
6704
6705 /*
6706 ================
6707 R_RenderView
6708 ================
6709 */
6710 int dpsoftrast_test;
6711 extern void R_Shadow_UpdateBounceGridTexture(void);
6712 extern cvar_t r_shadow_bouncegrid;
6713 void R_RenderView(void)
6714 {
6715         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6716
6717         dpsoftrast_test = r_test.integer;
6718
6719         if (r_timereport_active)
6720                 R_TimeReport("start");
6721         r_textureframe++; // used only by R_GetCurrentTexture
6722         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6723
6724         if(R_CompileShader_CheckStaticParms())
6725                 R_GLSL_Restart_f();
6726
6727         if (!r_drawentities.integer)
6728                 r_refdef.scene.numentities = 0;
6729
6730         R_AnimCache_ClearCache();
6731         R_FrameData_NewFrame();
6732
6733         /* adjust for stereo display */
6734         if(R_Stereo_Active())
6735         {
6736                 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);
6737                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6738         }
6739
6740         if (r_refdef.view.isoverlay)
6741         {
6742                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6743                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6744                 R_TimeReport("depthclear");
6745
6746                 r_refdef.view.showdebug = false;
6747
6748                 r_waterstate.enabled = false;
6749                 r_waterstate.numwaterplanes = 0;
6750
6751                 R_RenderScene();
6752
6753                 r_refdef.view.matrix = originalmatrix;
6754
6755                 CHECKGLERROR
6756                 return;
6757         }
6758
6759         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6760         {
6761                 r_refdef.view.matrix = originalmatrix;
6762                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6763         }
6764
6765         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6766
6767         R_RenderView_UpdateViewVectors();
6768
6769         R_Shadow_UpdateWorldLightSelection();
6770
6771         R_Bloom_StartFrame();
6772         R_Water_StartFrame();
6773
6774         CHECKGLERROR
6775         if (r_timereport_active)
6776                 R_TimeReport("viewsetup");
6777
6778         R_ResetViewRendering3D();
6779
6780         if (r_refdef.view.clear || r_refdef.fogenabled)
6781         {
6782                 R_ClearScreen(r_refdef.fogenabled);
6783                 if (r_timereport_active)
6784                         R_TimeReport("viewclear");
6785         }
6786         r_refdef.view.clear = true;
6787
6788         // this produces a bloom texture to be used in R_BlendView() later
6789         if (r_bloomstate.hdr)
6790         {
6791                 R_HDR_RenderBloomTexture();
6792                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6793                 r_textureframe++; // used only by R_GetCurrentTexture
6794         }
6795
6796         r_refdef.view.showdebug = true;
6797
6798         R_View_Update();
6799         if (r_timereport_active)
6800                 R_TimeReport("visibility");
6801
6802         R_Shadow_UpdateBounceGridTexture();
6803         if (r_timereport_active && r_shadow_bouncegrid.integer)
6804                 R_TimeReport("bouncegrid");
6805
6806         r_waterstate.numwaterplanes = 0;
6807         if (r_waterstate.enabled)
6808                 R_RenderWaterPlanes();
6809
6810         R_RenderScene();
6811         r_waterstate.numwaterplanes = 0;
6812
6813         R_BlendView();
6814         if (r_timereport_active)
6815                 R_TimeReport("blendview");
6816
6817         GL_Scissor(0, 0, vid.width, vid.height);
6818         GL_ScissorTest(false);
6819
6820         r_refdef.view.matrix = originalmatrix;
6821
6822         CHECKGLERROR
6823 }
6824
6825 void R_RenderWaterPlanes(void)
6826 {
6827         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6828         {
6829                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6830                 if (r_timereport_active)
6831                         R_TimeReport("waterworld");
6832         }
6833
6834         // don't let sound skip if going slow
6835         if (r_refdef.scene.extraupdate)
6836                 S_ExtraUpdate ();
6837
6838         R_DrawModelsAddWaterPlanes();
6839         if (r_timereport_active)
6840                 R_TimeReport("watermodels");
6841
6842         if (r_waterstate.numwaterplanes)
6843         {
6844                 R_Water_ProcessPlanes();
6845                 if (r_timereport_active)
6846                         R_TimeReport("waterscenes");
6847         }
6848 }
6849
6850 extern void R_DrawLightningBeams (void);
6851 extern void VM_CL_AddPolygonsToMeshQueue (void);
6852 extern void R_DrawPortals (void);
6853 extern cvar_t cl_locs_show;
6854 static void R_DrawLocs(void);
6855 static void R_DrawEntityBBoxes(void);
6856 static void R_DrawModelDecals(void);
6857 extern void R_DrawModelShadows(void);
6858 extern void R_DrawModelShadowMaps(void);
6859 extern cvar_t cl_decals_newsystem;
6860 extern qboolean r_shadow_usingdeferredprepass;
6861 void R_RenderScene(void)
6862 {
6863         qboolean shadowmapping = false;
6864
6865         if (r_timereport_active)
6866                 R_TimeReport("beginscene");
6867
6868         r_refdef.stats.renders++;
6869
6870         R_UpdateFogColor();
6871
6872         // don't let sound skip if going slow
6873         if (r_refdef.scene.extraupdate)
6874                 S_ExtraUpdate ();
6875
6876         R_MeshQueue_BeginScene();
6877
6878         R_SkyStartFrame();
6879
6880         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);
6881
6882         if (r_timereport_active)
6883                 R_TimeReport("skystartframe");
6884
6885         if (cl.csqc_vidvars.drawworld)
6886         {
6887                 // don't let sound skip if going slow
6888                 if (r_refdef.scene.extraupdate)
6889                         S_ExtraUpdate ();
6890
6891                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6892                 {
6893                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6894                         if (r_timereport_active)
6895                                 R_TimeReport("worldsky");
6896                 }
6897
6898                 if (R_DrawBrushModelsSky() && r_timereport_active)
6899                         R_TimeReport("bmodelsky");
6900
6901                 if (skyrendermasked && skyrenderlater)
6902                 {
6903                         // we have to force off the water clipping plane while rendering sky
6904                         R_SetupView(false);
6905                         R_Sky();
6906                         R_SetupView(true);
6907                         if (r_timereport_active)
6908                                 R_TimeReport("sky");
6909                 }
6910         }
6911
6912         R_AnimCache_CacheVisibleEntities();
6913         if (r_timereport_active)
6914                 R_TimeReport("animation");
6915
6916         R_Shadow_PrepareLights();
6917         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6918                 R_Shadow_PrepareModelShadows();
6919         if (r_timereport_active)
6920                 R_TimeReport("preparelights");
6921
6922         if (R_Shadow_ShadowMappingEnabled())
6923                 shadowmapping = true;
6924
6925         if (r_shadow_usingdeferredprepass)
6926                 R_Shadow_DrawPrepass();
6927
6928         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6929         {
6930                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6931                 if (r_timereport_active)
6932                         R_TimeReport("worlddepth");
6933         }
6934         if (r_depthfirst.integer >= 2)
6935         {
6936                 R_DrawModelsDepth();
6937                 if (r_timereport_active)
6938                         R_TimeReport("modeldepth");
6939         }
6940
6941         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6942         {
6943                 R_DrawModelShadowMaps();
6944                 R_ResetViewRendering3D();
6945                 // don't let sound skip if going slow
6946                 if (r_refdef.scene.extraupdate)
6947                         S_ExtraUpdate ();
6948         }
6949
6950         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6951         {
6952                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6953                 if (r_timereport_active)
6954                         R_TimeReport("world");
6955         }
6956
6957         // don't let sound skip if going slow
6958         if (r_refdef.scene.extraupdate)
6959                 S_ExtraUpdate ();
6960
6961         R_DrawModels();
6962         if (r_timereport_active)
6963                 R_TimeReport("models");
6964
6965         // don't let sound skip if going slow
6966         if (r_refdef.scene.extraupdate)
6967                 S_ExtraUpdate ();
6968
6969         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6970         {
6971                 R_DrawModelShadows();
6972                 R_ResetViewRendering3D();
6973                 // don't let sound skip if going slow
6974                 if (r_refdef.scene.extraupdate)
6975                         S_ExtraUpdate ();
6976         }
6977
6978         if (!r_shadow_usingdeferredprepass)
6979         {
6980                 R_Shadow_DrawLights();
6981                 if (r_timereport_active)
6982                         R_TimeReport("rtlights");
6983         }
6984
6985         // don't let sound skip if going slow
6986         if (r_refdef.scene.extraupdate)
6987                 S_ExtraUpdate ();
6988
6989         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6990         {
6991                 R_DrawModelShadows();
6992                 R_ResetViewRendering3D();
6993                 // don't let sound skip if going slow
6994                 if (r_refdef.scene.extraupdate)
6995                         S_ExtraUpdate ();
6996         }
6997
6998         if (cl.csqc_vidvars.drawworld)
6999         {
7000                 if (cl_decals_newsystem.integer)
7001                 {
7002                         R_DrawModelDecals();
7003                         if (r_timereport_active)
7004                                 R_TimeReport("modeldecals");
7005                 }
7006                 else
7007                 {
7008                         R_DrawDecals();
7009                         if (r_timereport_active)
7010                                 R_TimeReport("decals");
7011                 }
7012
7013                 R_DrawParticles();
7014                 if (r_timereport_active)
7015                         R_TimeReport("particles");
7016
7017                 R_DrawExplosions();
7018                 if (r_timereport_active)
7019                         R_TimeReport("explosions");
7020
7021                 R_DrawLightningBeams();
7022                 if (r_timereport_active)
7023                         R_TimeReport("lightning");
7024         }
7025
7026         VM_CL_AddPolygonsToMeshQueue();
7027
7028         if (r_refdef.view.showdebug)
7029         {
7030                 if (cl_locs_show.integer)
7031                 {
7032                         R_DrawLocs();
7033                         if (r_timereport_active)
7034                                 R_TimeReport("showlocs");
7035                 }
7036
7037                 if (r_drawportals.integer)
7038                 {
7039                         R_DrawPortals();
7040                         if (r_timereport_active)
7041                                 R_TimeReport("portals");
7042                 }
7043
7044                 if (r_showbboxes.value > 0)
7045                 {
7046                         R_DrawEntityBBoxes();
7047                         if (r_timereport_active)
7048                                 R_TimeReport("bboxes");
7049                 }
7050         }
7051
7052         if (r_transparent.integer)
7053         {
7054                 R_MeshQueue_RenderTransparent();
7055                 if (r_timereport_active)
7056                         R_TimeReport("drawtrans");
7057         }
7058
7059         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))
7060         {
7061                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7062                 if (r_timereport_active)
7063                         R_TimeReport("worlddebug");
7064                 R_DrawModelsDebug();
7065                 if (r_timereport_active)
7066                         R_TimeReport("modeldebug");
7067         }
7068
7069         if (cl.csqc_vidvars.drawworld)
7070         {
7071                 R_Shadow_DrawCoronas();
7072                 if (r_timereport_active)
7073                         R_TimeReport("coronas");
7074         }
7075
7076 #if 0
7077         {
7078                 GL_DepthTest(false);
7079                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7080                 GL_Color(1, 1, 1, 1);
7081                 qglBegin(GL_POLYGON);
7082                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7083                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7084                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7085                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7086                 qglEnd();
7087                 qglBegin(GL_POLYGON);
7088                 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]);
7089                 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]);
7090                 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]);
7091                 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]);
7092                 qglEnd();
7093                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7094         }
7095 #endif
7096
7097         // don't let sound skip if going slow
7098         if (r_refdef.scene.extraupdate)
7099                 S_ExtraUpdate ();
7100
7101         R_ResetViewRendering2D();
7102 }
7103
7104 static const unsigned short bboxelements[36] =
7105 {
7106         5, 1, 3, 5, 3, 7,
7107         6, 2, 0, 6, 0, 4,
7108         7, 3, 2, 7, 2, 6,
7109         4, 0, 1, 4, 1, 5,
7110         4, 5, 7, 4, 7, 6,
7111         1, 0, 2, 1, 2, 3,
7112 };
7113
7114 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7115 {
7116         int i;
7117         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7118
7119         RSurf_ActiveWorldEntity();
7120
7121         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7122         GL_DepthMask(false);
7123         GL_DepthRange(0, 1);
7124         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7125 //      R_Mesh_ResetTextureState();
7126
7127         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7128         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7129         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7130         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7131         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7132         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7133         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7134         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7135         R_FillColors(color4f, 8, cr, cg, cb, ca);
7136         if (r_refdef.fogenabled)
7137         {
7138                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7139                 {
7140                         f1 = RSurf_FogVertex(v);
7141                         f2 = 1 - f1;
7142                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7143                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7144                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7145                 }
7146         }
7147         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7148         R_Mesh_ResetTextureState();
7149         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7150         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7151 }
7152
7153 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7154 {
7155         int i;
7156         float color[4];
7157         prvm_edict_t *edict;
7158         prvm_prog_t *prog_save = prog;
7159
7160         // this function draws bounding boxes of server entities
7161         if (!sv.active)
7162                 return;
7163
7164         GL_CullFace(GL_NONE);
7165         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7166
7167         prog = 0;
7168         SV_VM_Begin();
7169         for (i = 0;i < numsurfaces;i++)
7170         {
7171                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7172                 switch ((int)PRVM_serveredictfloat(edict, solid))
7173                 {
7174                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7175                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7176                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7177                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7178                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7179                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7180                 }
7181                 color[3] *= r_showbboxes.value;
7182                 color[3] = bound(0, color[3], 1);
7183                 GL_DepthTest(!r_showdisabledepthtest.integer);
7184                 GL_CullFace(r_refdef.view.cullface_front);
7185                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7186         }
7187         SV_VM_End();
7188         prog = prog_save;
7189 }
7190
7191 static void R_DrawEntityBBoxes(void)
7192 {
7193         int i;
7194         prvm_edict_t *edict;
7195         vec3_t center;
7196         prvm_prog_t *prog_save = prog;
7197
7198         // this function draws bounding boxes of server entities
7199         if (!sv.active)
7200                 return;
7201
7202         prog = 0;
7203         SV_VM_Begin();
7204         for (i = 0;i < prog->num_edicts;i++)
7205         {
7206                 edict = PRVM_EDICT_NUM(i);
7207                 if (edict->priv.server->free)
7208                         continue;
7209                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7210                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7211                         continue;
7212                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7213                         continue;
7214                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7215                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7216         }
7217         SV_VM_End();
7218         prog = prog_save;
7219 }
7220
7221 static const int nomodelelement3i[24] =
7222 {
7223         5, 2, 0,
7224         5, 1, 2,
7225         5, 0, 3,
7226         5, 3, 1,
7227         0, 2, 4,
7228         2, 1, 4,
7229         3, 0, 4,
7230         1, 3, 4
7231 };
7232
7233 static const unsigned short nomodelelement3s[24] =
7234 {
7235         5, 2, 0,
7236         5, 1, 2,
7237         5, 0, 3,
7238         5, 3, 1,
7239         0, 2, 4,
7240         2, 1, 4,
7241         3, 0, 4,
7242         1, 3, 4
7243 };
7244
7245 static const float nomodelvertex3f[6*3] =
7246 {
7247         -16,   0,   0,
7248          16,   0,   0,
7249           0, -16,   0,
7250           0,  16,   0,
7251           0,   0, -16,
7252           0,   0,  16
7253 };
7254
7255 static const float nomodelcolor4f[6*4] =
7256 {
7257         0.0f, 0.0f, 0.5f, 1.0f,
7258         0.0f, 0.0f, 0.5f, 1.0f,
7259         0.0f, 0.5f, 0.0f, 1.0f,
7260         0.0f, 0.5f, 0.0f, 1.0f,
7261         0.5f, 0.0f, 0.0f, 1.0f,
7262         0.5f, 0.0f, 0.0f, 1.0f
7263 };
7264
7265 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7266 {
7267         int i;
7268         float f1, f2, *c;
7269         float color4f[6*4];
7270
7271         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);
7272
7273         // this is only called once per entity so numsurfaces is always 1, and
7274         // surfacelist is always {0}, so this code does not handle batches
7275
7276         if (rsurface.ent_flags & RENDER_ADDITIVE)
7277         {
7278                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7279                 GL_DepthMask(false);
7280         }
7281         else if (rsurface.colormod[3] < 1)
7282         {
7283                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7284                 GL_DepthMask(false);
7285         }
7286         else
7287         {
7288                 GL_BlendFunc(GL_ONE, GL_ZERO);
7289                 GL_DepthMask(true);
7290         }
7291         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7292         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7293         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7294         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7295         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7296         for (i = 0, c = color4f;i < 6;i++, c += 4)
7297         {
7298                 c[0] *= rsurface.colormod[0];
7299                 c[1] *= rsurface.colormod[1];
7300                 c[2] *= rsurface.colormod[2];
7301                 c[3] *= rsurface.colormod[3];
7302         }
7303         if (r_refdef.fogenabled)
7304         {
7305                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7306                 {
7307                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7308                         f2 = 1 - f1;
7309                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7310                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7311                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7312                 }
7313         }
7314 //      R_Mesh_ResetTextureState();
7315         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7316         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7317         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7318 }
7319
7320 void R_DrawNoModel(entity_render_t *ent)
7321 {
7322         vec3_t org;
7323         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7324         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7325                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7326         else
7327                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7328 }
7329
7330 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7331 {
7332         vec3_t right1, right2, diff, normal;
7333
7334         VectorSubtract (org2, org1, normal);
7335
7336         // calculate 'right' vector for start
7337         VectorSubtract (r_refdef.view.origin, org1, diff);
7338         CrossProduct (normal, diff, right1);
7339         VectorNormalize (right1);
7340
7341         // calculate 'right' vector for end
7342         VectorSubtract (r_refdef.view.origin, org2, diff);
7343         CrossProduct (normal, diff, right2);
7344         VectorNormalize (right2);
7345
7346         vert[ 0] = org1[0] + width * right1[0];
7347         vert[ 1] = org1[1] + width * right1[1];
7348         vert[ 2] = org1[2] + width * right1[2];
7349         vert[ 3] = org1[0] - width * right1[0];
7350         vert[ 4] = org1[1] - width * right1[1];
7351         vert[ 5] = org1[2] - width * right1[2];
7352         vert[ 6] = org2[0] - width * right2[0];
7353         vert[ 7] = org2[1] - width * right2[1];
7354         vert[ 8] = org2[2] - width * right2[2];
7355         vert[ 9] = org2[0] + width * right2[0];
7356         vert[10] = org2[1] + width * right2[1];
7357         vert[11] = org2[2] + width * right2[2];
7358 }
7359
7360 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)
7361 {
7362         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7363         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7364         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7365         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7366         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7367         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7368         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7369         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7370         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7371         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7372         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7373         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7374 }
7375
7376 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7377 {
7378         int i;
7379         float *vertex3f;
7380         float v[3];
7381         VectorSet(v, x, y, z);
7382         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7383                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7384                         break;
7385         if (i == mesh->numvertices)
7386         {
7387                 if (mesh->numvertices < mesh->maxvertices)
7388                 {
7389                         VectorCopy(v, vertex3f);
7390                         mesh->numvertices++;
7391                 }
7392                 return mesh->numvertices;
7393         }
7394         else
7395                 return i;
7396 }
7397
7398 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7399 {
7400         int i;
7401         int *e, element[3];
7402         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7403         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7404         e = mesh->element3i + mesh->numtriangles * 3;
7405         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7406         {
7407                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7408                 if (mesh->numtriangles < mesh->maxtriangles)
7409                 {
7410                         *e++ = element[0];
7411                         *e++ = element[1];
7412                         *e++ = element[2];
7413                         mesh->numtriangles++;
7414                 }
7415                 element[1] = element[2];
7416         }
7417 }
7418
7419 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7420 {
7421         int i;
7422         int *e, element[3];
7423         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7424         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7425         e = mesh->element3i + mesh->numtriangles * 3;
7426         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7427         {
7428                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7429                 if (mesh->numtriangles < mesh->maxtriangles)
7430                 {
7431                         *e++ = element[0];
7432                         *e++ = element[1];
7433                         *e++ = element[2];
7434                         mesh->numtriangles++;
7435                 }
7436                 element[1] = element[2];
7437         }
7438 }
7439
7440 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7441 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7442 {
7443         int planenum, planenum2;
7444         int w;
7445         int tempnumpoints;
7446         mplane_t *plane, *plane2;
7447         double maxdist;
7448         double temppoints[2][256*3];
7449         // figure out how large a bounding box we need to properly compute this brush
7450         maxdist = 0;
7451         for (w = 0;w < numplanes;w++)
7452                 maxdist = max(maxdist, fabs(planes[w].dist));
7453         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7454         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7455         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7456         {
7457                 w = 0;
7458                 tempnumpoints = 4;
7459                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7460                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7461                 {
7462                         if (planenum2 == planenum)
7463                                 continue;
7464                         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);
7465                         w = !w;
7466                 }
7467                 if (tempnumpoints < 3)
7468                         continue;
7469                 // generate elements forming a triangle fan for this polygon
7470                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7471         }
7472 }
7473
7474 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)
7475 {
7476         texturelayer_t *layer;
7477         layer = t->currentlayers + t->currentnumlayers++;
7478         layer->type = type;
7479         layer->depthmask = depthmask;
7480         layer->blendfunc1 = blendfunc1;
7481         layer->blendfunc2 = blendfunc2;
7482         layer->texture = texture;
7483         layer->texmatrix = *matrix;
7484         layer->color[0] = r;
7485         layer->color[1] = g;
7486         layer->color[2] = b;
7487         layer->color[3] = a;
7488 }
7489
7490 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7491 {
7492         if(parms[0] == 0 && parms[1] == 0)
7493                 return false;
7494         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7495                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7496                         return false;
7497         return true;
7498 }
7499
7500 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7501 {
7502         double index, f;
7503         index = parms[2] + rsurface.shadertime * parms[3];
7504         index -= floor(index);
7505         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7506         {
7507         default:
7508         case Q3WAVEFUNC_NONE:
7509         case Q3WAVEFUNC_NOISE:
7510         case Q3WAVEFUNC_COUNT:
7511                 f = 0;
7512                 break;
7513         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7514         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7515         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7516         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7517         case Q3WAVEFUNC_TRIANGLE:
7518                 index *= 4;
7519                 f = index - floor(index);
7520                 if (index < 1)
7521                 {
7522                         // f = f;
7523                 }
7524                 else if (index < 2)
7525                         f = 1 - f;
7526                 else if (index < 3)
7527                         f = -f;
7528                 else
7529                         f = -(1 - f);
7530                 break;
7531         }
7532         f = parms[0] + parms[1] * f;
7533         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7534                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7535         return (float) f;
7536 }
7537
7538 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7539 {
7540         int w, h, idx;
7541         double f;
7542         double offsetd[2];
7543         float tcmat[12];
7544         matrix4x4_t matrix, temp;
7545         switch(tcmod->tcmod)
7546         {
7547                 case Q3TCMOD_COUNT:
7548                 case Q3TCMOD_NONE:
7549                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7550                                 matrix = r_waterscrollmatrix;
7551                         else
7552                                 matrix = identitymatrix;
7553                         break;
7554                 case Q3TCMOD_ENTITYTRANSLATE:
7555                         // this is used in Q3 to allow the gamecode to control texcoord
7556                         // scrolling on the entity, which is not supported in darkplaces yet.
7557                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7558                         break;
7559                 case Q3TCMOD_ROTATE:
7560                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7561                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7562                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7563                         break;
7564                 case Q3TCMOD_SCALE:
7565                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7566                         break;
7567                 case Q3TCMOD_SCROLL:
7568                         // extra care is needed because of precision breakdown with large values of time
7569                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7570                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7571                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7572                         break;
7573                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7574                         w = (int) tcmod->parms[0];
7575                         h = (int) tcmod->parms[1];
7576                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7577                         f = f - floor(f);
7578                         idx = (int) floor(f * w * h);
7579                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7580                         break;
7581                 case Q3TCMOD_STRETCH:
7582                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7583                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7584                         break;
7585                 case Q3TCMOD_TRANSFORM:
7586                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7587                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7588                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7589                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7590                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7591                         break;
7592                 case Q3TCMOD_TURBULENT:
7593                         // this is handled in the RSurf_PrepareVertices function
7594                         matrix = identitymatrix;
7595                         break;
7596         }
7597         temp = *texmatrix;
7598         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7599 }
7600
7601 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7602 {
7603         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7604         char name[MAX_QPATH];
7605         skinframe_t *skinframe;
7606         unsigned char pixels[296*194];
7607         strlcpy(cache->name, skinname, sizeof(cache->name));
7608         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7609         if (developer_loading.integer)
7610                 Con_Printf("loading %s\n", name);
7611         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7612         if (!skinframe || !skinframe->base)
7613         {
7614                 unsigned char *f;
7615                 fs_offset_t filesize;
7616                 skinframe = NULL;
7617                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7618                 if (f)
7619                 {
7620                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7621                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7622                         Mem_Free(f);
7623                 }
7624         }
7625         cache->skinframe = skinframe;
7626 }
7627
7628 texture_t *R_GetCurrentTexture(texture_t *t)
7629 {
7630         int i;
7631         const entity_render_t *ent = rsurface.entity;
7632         dp_model_t *model = ent->model;
7633         q3shaderinfo_layer_tcmod_t *tcmod;
7634
7635         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7636                 return t->currentframe;
7637         t->update_lastrenderframe = r_textureframe;
7638         t->update_lastrenderentity = (void *)ent;
7639
7640         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7641                 t->camera_entity = ent->entitynumber;
7642         else
7643                 t->camera_entity = 0;
7644
7645         // switch to an alternate material if this is a q1bsp animated material
7646         {
7647                 texture_t *texture = t;
7648                 int s = rsurface.ent_skinnum;
7649                 if ((unsigned int)s >= (unsigned int)model->numskins)
7650                         s = 0;
7651                 if (model->skinscenes)
7652                 {
7653                         if (model->skinscenes[s].framecount > 1)
7654                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7655                         else
7656                                 s = model->skinscenes[s].firstframe;
7657                 }
7658                 if (s > 0)
7659                         t = t + s * model->num_surfaces;
7660                 if (t->animated)
7661                 {
7662                         // use an alternate animation if the entity's frame is not 0,
7663                         // and only if the texture has an alternate animation
7664                         if (rsurface.ent_alttextures && t->anim_total[1])
7665                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7666                         else
7667                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7668                 }
7669                 texture->currentframe = t;
7670         }
7671
7672         // update currentskinframe to be a qw skin or animation frame
7673         if (rsurface.ent_qwskin >= 0)
7674         {
7675                 i = rsurface.ent_qwskin;
7676                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7677                 {
7678                         r_qwskincache_size = cl.maxclients;
7679                         if (r_qwskincache)
7680                                 Mem_Free(r_qwskincache);
7681                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7682                 }
7683                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7684                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7685                 t->currentskinframe = r_qwskincache[i].skinframe;
7686                 if (t->currentskinframe == NULL)
7687                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7688         }
7689         else if (t->numskinframes >= 2)
7690                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7691         if (t->backgroundnumskinframes >= 2)
7692                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7693
7694         t->currentmaterialflags = t->basematerialflags;
7695         t->currentalpha = rsurface.colormod[3];
7696         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7697                 t->currentalpha *= r_wateralpha.value;
7698         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7699                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7700         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7701                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7702         if (!(rsurface.ent_flags & RENDER_LIGHT))
7703                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7704         else if (FAKELIGHT_ENABLED)
7705         {
7706                 // no modellight if using fakelight for the map
7707         }
7708         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7709         {
7710                 // pick a model lighting mode
7711                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7712                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7713                 else
7714                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7715         }
7716         if (rsurface.ent_flags & RENDER_ADDITIVE)
7717                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7718         else if (t->currentalpha < 1)
7719                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7720         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7721                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7722         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7723                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7724         if (t->backgroundnumskinframes)
7725                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7726         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7727         {
7728                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7729                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7730         }
7731         else
7732                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7733         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7734         {
7735                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7736                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7737         }
7738         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7739                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7740
7741         // there is no tcmod
7742         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7743         {
7744                 t->currenttexmatrix = r_waterscrollmatrix;
7745                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7746         }
7747         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7748         {
7749                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7750                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7751         }
7752
7753         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7754                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7755         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7756                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7757
7758         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7759         if (t->currentskinframe->qpixels)
7760                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7761         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7762         if (!t->basetexture)
7763                 t->basetexture = r_texture_notexture;
7764         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7765         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7766         t->nmaptexture = t->currentskinframe->nmap;
7767         if (!t->nmaptexture)
7768                 t->nmaptexture = r_texture_blanknormalmap;
7769         t->glosstexture = r_texture_black;
7770         t->glowtexture = t->currentskinframe->glow;
7771         t->fogtexture = t->currentskinframe->fog;
7772         t->reflectmasktexture = t->currentskinframe->reflect;
7773         if (t->backgroundnumskinframes)
7774         {
7775                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7776                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7777                 t->backgroundglosstexture = r_texture_black;
7778                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7779                 if (!t->backgroundnmaptexture)
7780                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7781         }
7782         else
7783         {
7784                 t->backgroundbasetexture = r_texture_white;
7785                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7786                 t->backgroundglosstexture = r_texture_black;
7787                 t->backgroundglowtexture = NULL;
7788         }
7789         t->specularpower = r_shadow_glossexponent.value;
7790         // TODO: store reference values for these in the texture?
7791         t->specularscale = 0;
7792         if (r_shadow_gloss.integer > 0)
7793         {
7794                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7795                 {
7796                         if (r_shadow_glossintensity.value > 0)
7797                         {
7798                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7799                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7800                                 t->specularscale = r_shadow_glossintensity.value;
7801                         }
7802                 }
7803                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7804                 {
7805                         t->glosstexture = r_texture_white;
7806                         t->backgroundglosstexture = r_texture_white;
7807                         t->specularscale = r_shadow_gloss2intensity.value;
7808                         t->specularpower = r_shadow_gloss2exponent.value;
7809                 }
7810         }
7811         t->specularscale *= t->specularscalemod;
7812         t->specularpower *= t->specularpowermod;
7813
7814         // lightmaps mode looks bad with dlights using actual texturing, so turn
7815         // off the colormap and glossmap, but leave the normalmap on as it still
7816         // accurately represents the shading involved
7817         if (gl_lightmaps.integer)
7818         {
7819                 t->basetexture = r_texture_grey128;
7820                 t->pantstexture = r_texture_black;
7821                 t->shirttexture = r_texture_black;
7822                 t->nmaptexture = r_texture_blanknormalmap;
7823                 t->glosstexture = r_texture_black;
7824                 t->glowtexture = NULL;
7825                 t->fogtexture = NULL;
7826                 t->reflectmasktexture = NULL;
7827                 t->backgroundbasetexture = NULL;
7828                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7829                 t->backgroundglosstexture = r_texture_black;
7830                 t->backgroundglowtexture = NULL;
7831                 t->specularscale = 0;
7832                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7833         }
7834
7835         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7836         VectorClear(t->dlightcolor);
7837         t->currentnumlayers = 0;
7838         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7839         {
7840                 int blendfunc1, blendfunc2;
7841                 qboolean depthmask;
7842                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7843                 {
7844                         blendfunc1 = GL_SRC_ALPHA;
7845                         blendfunc2 = GL_ONE;
7846                 }
7847                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7848                 {
7849                         blendfunc1 = GL_SRC_ALPHA;
7850                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7851                 }
7852                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7853                 {
7854                         blendfunc1 = t->customblendfunc[0];
7855                         blendfunc2 = t->customblendfunc[1];
7856                 }
7857                 else
7858                 {
7859                         blendfunc1 = GL_ONE;
7860                         blendfunc2 = GL_ZERO;
7861                 }
7862                 // don't colormod evilblend textures
7863                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7864                         VectorSet(t->lightmapcolor, 1, 1, 1);
7865                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7866                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7867                 {
7868                         // fullbright is not affected by r_refdef.lightmapintensity
7869                         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]);
7870                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7871                                 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]);
7872                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7873                                 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]);
7874                 }
7875                 else
7876                 {
7877                         vec3_t ambientcolor;
7878                         float colorscale;
7879                         // set the color tint used for lights affecting this surface
7880                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7881                         colorscale = 2;
7882                         // q3bsp has no lightmap updates, so the lightstylevalue that
7883                         // would normally be baked into the lightmap must be
7884                         // applied to the color
7885                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7886                         if (model->type == mod_brushq3)
7887                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7888                         colorscale *= r_refdef.lightmapintensity;
7889                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7890                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7891                         // basic lit geometry
7892                         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]);
7893                         // add pants/shirt if needed
7894                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7895                                 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]);
7896                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7897                                 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]);
7898                         // now add ambient passes if needed
7899                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7900                         {
7901                                 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]);
7902                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7903                                         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]);
7904                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7905                                         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]);
7906                         }
7907                 }
7908                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7909                         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]);
7910                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7911                 {
7912                         // if this is opaque use alpha blend which will darken the earlier
7913                         // passes cheaply.
7914                         //
7915                         // if this is an alpha blended material, all the earlier passes
7916                         // were darkened by fog already, so we only need to add the fog
7917                         // color ontop through the fog mask texture
7918                         //
7919                         // if this is an additive blended material, all the earlier passes
7920                         // were darkened by fog already, and we should not add fog color
7921                         // (because the background was not darkened, there is no fog color
7922                         // that was lost behind it).
7923                         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]);
7924                 }
7925         }
7926
7927         return t->currentframe;
7928 }
7929
7930 rsurfacestate_t rsurface;
7931
7932 void RSurf_ActiveWorldEntity(void)
7933 {
7934         dp_model_t *model = r_refdef.scene.worldmodel;
7935         //if (rsurface.entity == r_refdef.scene.worldentity)
7936         //      return;
7937         rsurface.entity = r_refdef.scene.worldentity;
7938         rsurface.skeleton = NULL;
7939         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7940         rsurface.ent_skinnum = 0;
7941         rsurface.ent_qwskin = -1;
7942         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7943         rsurface.shadertime = r_refdef.scene.time;
7944         rsurface.matrix = identitymatrix;
7945         rsurface.inversematrix = identitymatrix;
7946         rsurface.matrixscale = 1;
7947         rsurface.inversematrixscale = 1;
7948         R_EntityMatrix(&identitymatrix);
7949         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7950         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7951         rsurface.fograngerecip = r_refdef.fograngerecip;
7952         rsurface.fogheightfade = r_refdef.fogheightfade;
7953         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7954         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7955         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7956         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7957         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7958         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7959         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7960         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7961         rsurface.colormod[3] = 1;
7962         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);
7963         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7964         rsurface.frameblend[0].lerp = 1;
7965         rsurface.ent_alttextures = false;
7966         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7967         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7968         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7969         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7970         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7971         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7972         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7973         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7974         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7975         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7976         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7977         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7978         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7979         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7980         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7981         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7982         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7983         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7984         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7985         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7986         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7987         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7988         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7989         rsurface.modelelement3i = model->surfmesh.data_element3i;
7990         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7991         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7992         rsurface.modelelement3s = model->surfmesh.data_element3s;
7993         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7994         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7995         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7996         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7997         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7998         rsurface.modelsurfaces = model->data_surfaces;
7999         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8000         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8001         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8002         rsurface.modelgeneratedvertex = false;
8003         rsurface.batchgeneratedvertex = false;
8004         rsurface.batchfirstvertex = 0;
8005         rsurface.batchnumvertices = 0;
8006         rsurface.batchfirsttriangle = 0;
8007         rsurface.batchnumtriangles = 0;
8008         rsurface.batchvertex3f  = NULL;
8009         rsurface.batchvertex3f_vertexbuffer = NULL;
8010         rsurface.batchvertex3f_bufferoffset = 0;
8011         rsurface.batchsvector3f = NULL;
8012         rsurface.batchsvector3f_vertexbuffer = NULL;
8013         rsurface.batchsvector3f_bufferoffset = 0;
8014         rsurface.batchtvector3f = NULL;
8015         rsurface.batchtvector3f_vertexbuffer = NULL;
8016         rsurface.batchtvector3f_bufferoffset = 0;
8017         rsurface.batchnormal3f  = NULL;
8018         rsurface.batchnormal3f_vertexbuffer = NULL;
8019         rsurface.batchnormal3f_bufferoffset = 0;
8020         rsurface.batchlightmapcolor4f = NULL;
8021         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8022         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8023         rsurface.batchtexcoordtexture2f = NULL;
8024         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8025         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8026         rsurface.batchtexcoordlightmap2f = NULL;
8027         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8028         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8029         rsurface.batchvertexmesh = NULL;
8030         rsurface.batchvertexmeshbuffer = NULL;
8031         rsurface.batchvertex3fbuffer = NULL;
8032         rsurface.batchelement3i = NULL;
8033         rsurface.batchelement3i_indexbuffer = NULL;
8034         rsurface.batchelement3i_bufferoffset = 0;
8035         rsurface.batchelement3s = NULL;
8036         rsurface.batchelement3s_indexbuffer = NULL;
8037         rsurface.batchelement3s_bufferoffset = 0;
8038         rsurface.passcolor4f = NULL;
8039         rsurface.passcolor4f_vertexbuffer = NULL;
8040         rsurface.passcolor4f_bufferoffset = 0;
8041 }
8042
8043 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8044 {
8045         dp_model_t *model = ent->model;
8046         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8047         //      return;
8048         rsurface.entity = (entity_render_t *)ent;
8049         rsurface.skeleton = ent->skeleton;
8050         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8051         rsurface.ent_skinnum = ent->skinnum;
8052         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;
8053         rsurface.ent_flags = ent->flags;
8054         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8055         rsurface.matrix = ent->matrix;
8056         rsurface.inversematrix = ent->inversematrix;
8057         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8058         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8059         R_EntityMatrix(&rsurface.matrix);
8060         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8061         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8062         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8063         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8064         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8065         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8066         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8067         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8068         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8069         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8070         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8071         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8072         rsurface.colormod[3] = ent->alpha;
8073         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8074         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8075         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8076         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8077         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8078         if (ent->model->brush.submodel && !prepass)
8079         {
8080                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8081                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8082         }
8083         if (model->surfmesh.isanimated && model->AnimateVertices)
8084         {
8085                 if (ent->animcache_vertex3f)
8086                 {
8087                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8088                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8089                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8090                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8091                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8092                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8093                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8094                 }
8095                 else if (wanttangents)
8096                 {
8097                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8098                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8099                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8100                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8101                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8102                         rsurface.modelvertexmesh = NULL;
8103                         rsurface.modelvertexmeshbuffer = NULL;
8104                         rsurface.modelvertex3fbuffer = NULL;
8105                 }
8106                 else if (wantnormals)
8107                 {
8108                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8109                         rsurface.modelsvector3f = NULL;
8110                         rsurface.modeltvector3f = NULL;
8111                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8112                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8113                         rsurface.modelvertexmesh = NULL;
8114                         rsurface.modelvertexmeshbuffer = NULL;
8115                         rsurface.modelvertex3fbuffer = NULL;
8116                 }
8117                 else
8118                 {
8119                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8120                         rsurface.modelsvector3f = NULL;
8121                         rsurface.modeltvector3f = NULL;
8122                         rsurface.modelnormal3f = NULL;
8123                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8124                         rsurface.modelvertexmesh = NULL;
8125                         rsurface.modelvertexmeshbuffer = NULL;
8126                         rsurface.modelvertex3fbuffer = NULL;
8127                 }
8128                 rsurface.modelvertex3f_vertexbuffer = 0;
8129                 rsurface.modelvertex3f_bufferoffset = 0;
8130                 rsurface.modelsvector3f_vertexbuffer = 0;
8131                 rsurface.modelsvector3f_bufferoffset = 0;
8132                 rsurface.modeltvector3f_vertexbuffer = 0;
8133                 rsurface.modeltvector3f_bufferoffset = 0;
8134                 rsurface.modelnormal3f_vertexbuffer = 0;
8135                 rsurface.modelnormal3f_bufferoffset = 0;
8136                 rsurface.modelgeneratedvertex = true;
8137         }
8138         else
8139         {
8140                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8141                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8142                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8143                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8144                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8145                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8146                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8147                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8148                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8149                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8150                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8151                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8152                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8153                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8154                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8155                 rsurface.modelgeneratedvertex = false;
8156         }
8157         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8158         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8159         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8160         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8161         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8162         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8163         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8164         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8165         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8166         rsurface.modelelement3i = model->surfmesh.data_element3i;
8167         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8168         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8169         rsurface.modelelement3s = model->surfmesh.data_element3s;
8170         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8171         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8172         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8173         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8174         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8175         rsurface.modelsurfaces = model->data_surfaces;
8176         rsurface.batchgeneratedvertex = false;
8177         rsurface.batchfirstvertex = 0;
8178         rsurface.batchnumvertices = 0;
8179         rsurface.batchfirsttriangle = 0;
8180         rsurface.batchnumtriangles = 0;
8181         rsurface.batchvertex3f  = NULL;
8182         rsurface.batchvertex3f_vertexbuffer = NULL;
8183         rsurface.batchvertex3f_bufferoffset = 0;
8184         rsurface.batchsvector3f = NULL;
8185         rsurface.batchsvector3f_vertexbuffer = NULL;
8186         rsurface.batchsvector3f_bufferoffset = 0;
8187         rsurface.batchtvector3f = NULL;
8188         rsurface.batchtvector3f_vertexbuffer = NULL;
8189         rsurface.batchtvector3f_bufferoffset = 0;
8190         rsurface.batchnormal3f  = NULL;
8191         rsurface.batchnormal3f_vertexbuffer = NULL;
8192         rsurface.batchnormal3f_bufferoffset = 0;
8193         rsurface.batchlightmapcolor4f = NULL;
8194         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8195         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8196         rsurface.batchtexcoordtexture2f = NULL;
8197         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8198         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8199         rsurface.batchtexcoordlightmap2f = NULL;
8200         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8201         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8202         rsurface.batchvertexmesh = NULL;
8203         rsurface.batchvertexmeshbuffer = NULL;
8204         rsurface.batchvertex3fbuffer = NULL;
8205         rsurface.batchelement3i = NULL;
8206         rsurface.batchelement3i_indexbuffer = NULL;
8207         rsurface.batchelement3i_bufferoffset = 0;
8208         rsurface.batchelement3s = NULL;
8209         rsurface.batchelement3s_indexbuffer = NULL;
8210         rsurface.batchelement3s_bufferoffset = 0;
8211         rsurface.passcolor4f = NULL;
8212         rsurface.passcolor4f_vertexbuffer = NULL;
8213         rsurface.passcolor4f_bufferoffset = 0;
8214 }
8215
8216 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)
8217 {
8218         rsurface.entity = r_refdef.scene.worldentity;
8219         rsurface.skeleton = NULL;
8220         rsurface.ent_skinnum = 0;
8221         rsurface.ent_qwskin = -1;
8222         rsurface.ent_flags = entflags;
8223         rsurface.shadertime = r_refdef.scene.time - shadertime;
8224         rsurface.modelnumvertices = numvertices;
8225         rsurface.modelnumtriangles = numtriangles;
8226         rsurface.matrix = *matrix;
8227         rsurface.inversematrix = *inversematrix;
8228         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8229         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8230         R_EntityMatrix(&rsurface.matrix);
8231         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8232         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8233         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8234         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8235         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8236         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8237         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8238         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8239         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8240         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8241         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8242         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8243         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);
8244         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8245         rsurface.frameblend[0].lerp = 1;
8246         rsurface.ent_alttextures = false;
8247         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8248         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8249         if (wanttangents)
8250         {
8251                 rsurface.modelvertex3f = (float *)vertex3f;
8252                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8253                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8254                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8255         }
8256         else if (wantnormals)
8257         {
8258                 rsurface.modelvertex3f = (float *)vertex3f;
8259                 rsurface.modelsvector3f = NULL;
8260                 rsurface.modeltvector3f = NULL;
8261                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8262         }
8263         else
8264         {
8265                 rsurface.modelvertex3f = (float *)vertex3f;
8266                 rsurface.modelsvector3f = NULL;
8267                 rsurface.modeltvector3f = NULL;
8268                 rsurface.modelnormal3f = NULL;
8269         }
8270         rsurface.modelvertexmesh = NULL;
8271         rsurface.modelvertexmeshbuffer = NULL;
8272         rsurface.modelvertex3fbuffer = NULL;
8273         rsurface.modelvertex3f_vertexbuffer = 0;
8274         rsurface.modelvertex3f_bufferoffset = 0;
8275         rsurface.modelsvector3f_vertexbuffer = 0;
8276         rsurface.modelsvector3f_bufferoffset = 0;
8277         rsurface.modeltvector3f_vertexbuffer = 0;
8278         rsurface.modeltvector3f_bufferoffset = 0;
8279         rsurface.modelnormal3f_vertexbuffer = 0;
8280         rsurface.modelnormal3f_bufferoffset = 0;
8281         rsurface.modelgeneratedvertex = true;
8282         rsurface.modellightmapcolor4f  = (float *)color4f;
8283         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8284         rsurface.modellightmapcolor4f_bufferoffset = 0;
8285         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8286         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8287         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8288         rsurface.modeltexcoordlightmap2f  = NULL;
8289         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8290         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8291         rsurface.modelelement3i = (int *)element3i;
8292         rsurface.modelelement3i_indexbuffer = NULL;
8293         rsurface.modelelement3i_bufferoffset = 0;
8294         rsurface.modelelement3s = (unsigned short *)element3s;
8295         rsurface.modelelement3s_indexbuffer = NULL;
8296         rsurface.modelelement3s_bufferoffset = 0;
8297         rsurface.modellightmapoffsets = NULL;
8298         rsurface.modelsurfaces = NULL;
8299         rsurface.batchgeneratedvertex = false;
8300         rsurface.batchfirstvertex = 0;
8301         rsurface.batchnumvertices = 0;
8302         rsurface.batchfirsttriangle = 0;
8303         rsurface.batchnumtriangles = 0;
8304         rsurface.batchvertex3f  = NULL;
8305         rsurface.batchvertex3f_vertexbuffer = NULL;
8306         rsurface.batchvertex3f_bufferoffset = 0;
8307         rsurface.batchsvector3f = NULL;
8308         rsurface.batchsvector3f_vertexbuffer = NULL;
8309         rsurface.batchsvector3f_bufferoffset = 0;
8310         rsurface.batchtvector3f = NULL;
8311         rsurface.batchtvector3f_vertexbuffer = NULL;
8312         rsurface.batchtvector3f_bufferoffset = 0;
8313         rsurface.batchnormal3f  = NULL;
8314         rsurface.batchnormal3f_vertexbuffer = NULL;
8315         rsurface.batchnormal3f_bufferoffset = 0;
8316         rsurface.batchlightmapcolor4f = NULL;
8317         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8318         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8319         rsurface.batchtexcoordtexture2f = NULL;
8320         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8321         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8322         rsurface.batchtexcoordlightmap2f = NULL;
8323         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8324         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8325         rsurface.batchvertexmesh = NULL;
8326         rsurface.batchvertexmeshbuffer = NULL;
8327         rsurface.batchvertex3fbuffer = NULL;
8328         rsurface.batchelement3i = NULL;
8329         rsurface.batchelement3i_indexbuffer = NULL;
8330         rsurface.batchelement3i_bufferoffset = 0;
8331         rsurface.batchelement3s = NULL;
8332         rsurface.batchelement3s_indexbuffer = NULL;
8333         rsurface.batchelement3s_bufferoffset = 0;
8334         rsurface.passcolor4f = NULL;
8335         rsurface.passcolor4f_vertexbuffer = NULL;
8336         rsurface.passcolor4f_bufferoffset = 0;
8337
8338         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8339         {
8340                 if ((wantnormals || wanttangents) && !normal3f)
8341                 {
8342                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8343                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8344                 }
8345                 if (wanttangents && !svector3f)
8346                 {
8347                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8348                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8349                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8350                 }
8351         }
8352 }
8353
8354 float RSurf_FogPoint(const float *v)
8355 {
8356         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8357         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8358         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8359         float FogHeightFade = r_refdef.fogheightfade;
8360         float fogfrac;
8361         unsigned int fogmasktableindex;
8362         if (r_refdef.fogplaneviewabove)
8363                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8364         else
8365                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8366         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8367         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8368 }
8369
8370 float RSurf_FogVertex(const float *v)
8371 {
8372         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8373         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8374         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8375         float FogHeightFade = rsurface.fogheightfade;
8376         float fogfrac;
8377         unsigned int fogmasktableindex;
8378         if (r_refdef.fogplaneviewabove)
8379                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8380         else
8381                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8382         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8383         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8384 }
8385
8386 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8387 {
8388         int i;
8389         for (i = 0;i < numelements;i++)
8390                 outelement3i[i] = inelement3i[i] + adjust;
8391 }
8392
8393 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8394 extern cvar_t gl_vbo;
8395 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8396 {
8397         int deformindex;
8398         int firsttriangle;
8399         int numtriangles;
8400         int firstvertex;
8401         int endvertex;
8402         int numvertices;
8403         int surfacefirsttriangle;
8404         int surfacenumtriangles;
8405         int surfacefirstvertex;
8406         int surfaceendvertex;
8407         int surfacenumvertices;
8408         int batchnumvertices;
8409         int batchnumtriangles;
8410         int needsupdate;
8411         int i, j;
8412         qboolean gaps;
8413         qboolean dynamicvertex;
8414         float amplitude;
8415         float animpos;
8416         float scale;
8417         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8418         float waveparms[4];
8419         q3shaderinfo_deform_t *deform;
8420         const msurface_t *surface, *firstsurface;
8421         r_vertexmesh_t *vertexmesh;
8422         if (!texturenumsurfaces)
8423                 return;
8424         // find vertex range of this surface batch
8425         gaps = false;
8426         firstsurface = texturesurfacelist[0];
8427         firsttriangle = firstsurface->num_firsttriangle;
8428         batchnumvertices = 0;
8429         batchnumtriangles = 0;
8430         firstvertex = endvertex = firstsurface->num_firstvertex;
8431         for (i = 0;i < texturenumsurfaces;i++)
8432         {
8433                 surface = texturesurfacelist[i];
8434                 if (surface != firstsurface + i)
8435                         gaps = true;
8436                 surfacefirstvertex = surface->num_firstvertex;
8437                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8438                 surfacenumvertices = surface->num_vertices;
8439                 surfacenumtriangles = surface->num_triangles;
8440                 if (firstvertex > surfacefirstvertex)
8441                         firstvertex = surfacefirstvertex;
8442                 if (endvertex < surfaceendvertex)
8443                         endvertex = surfaceendvertex;
8444                 batchnumvertices += surfacenumvertices;
8445                 batchnumtriangles += surfacenumtriangles;
8446         }
8447
8448         // we now know the vertex range used, and if there are any gaps in it
8449         rsurface.batchfirstvertex = firstvertex;
8450         rsurface.batchnumvertices = endvertex - firstvertex;
8451         rsurface.batchfirsttriangle = firsttriangle;
8452         rsurface.batchnumtriangles = batchnumtriangles;
8453
8454         // this variable holds flags for which properties have been updated that
8455         // may require regenerating vertexmesh array...
8456         needsupdate = 0;
8457
8458         // check if any dynamic vertex processing must occur
8459         dynamicvertex = false;
8460
8461         // if there is a chance of animated vertex colors, it's a dynamic batch
8462         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8463         {
8464                 dynamicvertex = true;
8465                 batchneed |= BATCHNEED_NOGAPS;
8466                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8467         }
8468
8469         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8470         {
8471                 switch (deform->deform)
8472                 {
8473                 default:
8474                 case Q3DEFORM_PROJECTIONSHADOW:
8475                 case Q3DEFORM_TEXT0:
8476                 case Q3DEFORM_TEXT1:
8477                 case Q3DEFORM_TEXT2:
8478                 case Q3DEFORM_TEXT3:
8479                 case Q3DEFORM_TEXT4:
8480                 case Q3DEFORM_TEXT5:
8481                 case Q3DEFORM_TEXT6:
8482                 case Q3DEFORM_TEXT7:
8483                 case Q3DEFORM_NONE:
8484                         break;
8485                 case Q3DEFORM_AUTOSPRITE:
8486                         dynamicvertex = true;
8487                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8488                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8489                         break;
8490                 case Q3DEFORM_AUTOSPRITE2:
8491                         dynamicvertex = true;
8492                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8493                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8494                         break;
8495                 case Q3DEFORM_NORMAL:
8496                         dynamicvertex = true;
8497                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8498                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8499                         break;
8500                 case Q3DEFORM_WAVE:
8501                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8502                                 break; // if wavefunc is a nop, ignore this transform
8503                         dynamicvertex = true;
8504                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8505                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8506                         break;
8507                 case Q3DEFORM_BULGE:
8508                         dynamicvertex = true;
8509                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8510                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8511                         break;
8512                 case Q3DEFORM_MOVE:
8513                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8514                                 break; // if wavefunc is a nop, ignore this transform
8515                         dynamicvertex = true;
8516                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8517                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8518                         break;
8519                 }
8520         }
8521         switch(rsurface.texture->tcgen.tcgen)
8522         {
8523         default:
8524         case Q3TCGEN_TEXTURE:
8525                 break;
8526         case Q3TCGEN_LIGHTMAP:
8527                 dynamicvertex = true;
8528                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8529                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8530                 break;
8531         case Q3TCGEN_VECTOR:
8532                 dynamicvertex = true;
8533                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8534                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8535                 break;
8536         case Q3TCGEN_ENVIRONMENT:
8537                 dynamicvertex = true;
8538                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8539                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8540                 break;
8541         }
8542         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8543         {
8544                 dynamicvertex = true;
8545                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8546                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8547         }
8548
8549         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8550         {
8551                 dynamicvertex = true;
8552                 batchneed |= BATCHNEED_NOGAPS;
8553                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8554         }
8555
8556         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8557         {
8558                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8559                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8560                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8561                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8562                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8563                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8564                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8565         }
8566
8567         // when the model data has no vertex buffer (dynamic mesh), we need to
8568         // eliminate gaps
8569         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8570                 batchneed |= BATCHNEED_NOGAPS;
8571
8572         // if needsupdate, we have to do a dynamic vertex batch for sure
8573         if (needsupdate & batchneed)
8574                 dynamicvertex = true;
8575
8576         // see if we need to build vertexmesh from arrays
8577         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8578                 dynamicvertex = true;
8579
8580         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8581         // also some drivers strongly dislike firstvertex
8582         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8583                 dynamicvertex = true;
8584
8585         rsurface.batchvertex3f = rsurface.modelvertex3f;
8586         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8587         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8588         rsurface.batchsvector3f = rsurface.modelsvector3f;
8589         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8590         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8591         rsurface.batchtvector3f = rsurface.modeltvector3f;
8592         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8593         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8594         rsurface.batchnormal3f = rsurface.modelnormal3f;
8595         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8596         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8597         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8598         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8599         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8600         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8601         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8602         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8603         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8604         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8605         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8606         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8607         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8608         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8609         rsurface.batchelement3i = rsurface.modelelement3i;
8610         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8611         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8612         rsurface.batchelement3s = rsurface.modelelement3s;
8613         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8614         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8615
8616         // if any dynamic vertex processing has to occur in software, we copy the
8617         // entire surface list together before processing to rebase the vertices
8618         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8619         //
8620         // if any gaps exist and we do not have a static vertex buffer, we have to
8621         // copy the surface list together to avoid wasting upload bandwidth on the
8622         // vertices in the gaps.
8623         //
8624         // if gaps exist and we have a static vertex buffer, we still have to
8625         // combine the index buffer ranges into one dynamic index buffer.
8626         //
8627         // in all cases we end up with data that can be drawn in one call.
8628
8629         if (!dynamicvertex)
8630         {
8631                 // static vertex data, just set pointers...
8632                 rsurface.batchgeneratedvertex = false;
8633                 // if there are gaps, we want to build a combined index buffer,
8634                 // otherwise use the original static buffer with an appropriate offset
8635                 if (gaps)
8636                 {
8637                         // build a new triangle elements array for this batch
8638                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8639                         rsurface.batchfirsttriangle = 0;
8640                         numtriangles = 0;
8641                         for (i = 0;i < texturenumsurfaces;i++)
8642                         {
8643                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8644                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8645                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8646                                 numtriangles += surfacenumtriangles;
8647                         }
8648                         rsurface.batchelement3i_indexbuffer = NULL;
8649                         rsurface.batchelement3i_bufferoffset = 0;
8650                         rsurface.batchelement3s = NULL;
8651                         rsurface.batchelement3s_indexbuffer = NULL;
8652                         rsurface.batchelement3s_bufferoffset = 0;
8653                         if (endvertex <= 65536)
8654                         {
8655                                 // make a 16bit (unsigned short) index array if possible
8656                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8657                                 for (i = 0;i < numtriangles*3;i++)
8658                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8659                         }
8660                 }
8661                 return;
8662         }
8663
8664         // something needs software processing, do it for real...
8665         // we only directly handle separate array data in this case and then
8666         // generate interleaved data if needed...
8667         rsurface.batchgeneratedvertex = true;
8668
8669         // now copy the vertex data into a combined array and make an index array
8670         // (this is what Quake3 does all the time)
8671         //if (gaps || rsurface.batchfirstvertex)
8672         {
8673                 rsurface.batchvertex3fbuffer = NULL;
8674                 rsurface.batchvertexmesh = NULL;
8675                 rsurface.batchvertexmeshbuffer = NULL;
8676                 rsurface.batchvertex3f = NULL;
8677                 rsurface.batchvertex3f_vertexbuffer = NULL;
8678                 rsurface.batchvertex3f_bufferoffset = 0;
8679                 rsurface.batchsvector3f = NULL;
8680                 rsurface.batchsvector3f_vertexbuffer = NULL;
8681                 rsurface.batchsvector3f_bufferoffset = 0;
8682                 rsurface.batchtvector3f = NULL;
8683                 rsurface.batchtvector3f_vertexbuffer = NULL;
8684                 rsurface.batchtvector3f_bufferoffset = 0;
8685                 rsurface.batchnormal3f = NULL;
8686                 rsurface.batchnormal3f_vertexbuffer = NULL;
8687                 rsurface.batchnormal3f_bufferoffset = 0;
8688                 rsurface.batchlightmapcolor4f = NULL;
8689                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8690                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8691                 rsurface.batchtexcoordtexture2f = NULL;
8692                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8693                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8694                 rsurface.batchtexcoordlightmap2f = NULL;
8695                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8696                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8697                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8698                 rsurface.batchelement3i_indexbuffer = NULL;
8699                 rsurface.batchelement3i_bufferoffset = 0;
8700                 rsurface.batchelement3s = NULL;
8701                 rsurface.batchelement3s_indexbuffer = NULL;
8702                 rsurface.batchelement3s_bufferoffset = 0;
8703                 // we'll only be setting up certain arrays as needed
8704                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8705                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8706                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8707                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8708                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8709                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8710                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8711                 {
8712                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8713                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8714                 }
8715                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8716                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8717                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8718                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8719                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8720                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8721                 numvertices = 0;
8722                 numtriangles = 0;
8723                 for (i = 0;i < texturenumsurfaces;i++)
8724                 {
8725                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8726                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8727                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8728                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8729                         // copy only the data requested
8730                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8731                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8732                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8733                         {
8734                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8735                                 {
8736                                         if (rsurface.batchvertex3f)
8737                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8738                                         else
8739                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8740                                 }
8741                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8742                                 {
8743                                         if (rsurface.modelnormal3f)
8744                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8745                                         else
8746                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8747                                 }
8748                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8749                                 {
8750                                         if (rsurface.modelsvector3f)
8751                                         {
8752                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8753                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8754                                         }
8755                                         else
8756                                         {
8757                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8758                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8759                                         }
8760                                 }
8761                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8762                                 {
8763                                         if (rsurface.modellightmapcolor4f)
8764                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8765                                         else
8766                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8767                                 }
8768                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8769                                 {
8770                                         if (rsurface.modeltexcoordtexture2f)
8771                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8772                                         else
8773                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8774                                 }
8775                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8776                                 {
8777                                         if (rsurface.modeltexcoordlightmap2f)
8778                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8779                                         else
8780                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8781                                 }
8782                         }
8783                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8784                         numvertices += surfacenumvertices;
8785                         numtriangles += surfacenumtriangles;
8786                 }
8787
8788                 // generate a 16bit index array as well if possible
8789                 // (in general, dynamic batches fit)
8790                 if (numvertices <= 65536)
8791                 {
8792                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8793                         for (i = 0;i < numtriangles*3;i++)
8794                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8795                 }
8796
8797                 // since we've copied everything, the batch now starts at 0
8798                 rsurface.batchfirstvertex = 0;
8799                 rsurface.batchnumvertices = batchnumvertices;
8800                 rsurface.batchfirsttriangle = 0;
8801                 rsurface.batchnumtriangles = batchnumtriangles;
8802         }
8803
8804         // q1bsp surfaces rendered in vertex color mode have to have colors
8805         // calculated based on lightstyles
8806         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8807         {
8808                 // generate color arrays for the surfaces in this list
8809                 int c[4];
8810                 int scale;
8811                 int size3;
8812                 const int *offsets;
8813                 const unsigned char *lm;
8814                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8815                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8816                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8817                 numvertices = 0;
8818                 for (i = 0;i < texturenumsurfaces;i++)
8819                 {
8820                         surface = texturesurfacelist[i];
8821                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8822                         surfacenumvertices = surface->num_vertices;
8823                         if (surface->lightmapinfo->samples)
8824                         {
8825                                 for (j = 0;j < surfacenumvertices;j++)
8826                                 {
8827                                         lm = surface->lightmapinfo->samples + offsets[j];
8828                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8829                                         VectorScale(lm, scale, c);
8830                                         if (surface->lightmapinfo->styles[1] != 255)
8831                                         {
8832                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8833                                                 lm += size3;
8834                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8835                                                 VectorMA(c, scale, lm, c);
8836                                                 if (surface->lightmapinfo->styles[2] != 255)
8837                                                 {
8838                                                         lm += size3;
8839                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8840                                                         VectorMA(c, scale, lm, c);
8841                                                         if (surface->lightmapinfo->styles[3] != 255)
8842                                                         {
8843                                                                 lm += size3;
8844                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8845                                                                 VectorMA(c, scale, lm, c);
8846                                                         }
8847                                                 }
8848                                         }
8849                                         c[0] >>= 7;
8850                                         c[1] >>= 7;
8851                                         c[2] >>= 7;
8852                                         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);
8853                                         numvertices++;
8854                                 }
8855                         }
8856                         else
8857                         {
8858                                 for (j = 0;j < surfacenumvertices;j++)
8859                                 {
8860                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8861                                         numvertices++;
8862                                 }
8863                         }
8864                 }
8865         }
8866
8867         // if vertices are deformed (sprite flares and things in maps, possibly
8868         // water waves, bulges and other deformations), modify the copied vertices
8869         // in place
8870         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8871         {
8872                 switch (deform->deform)
8873                 {
8874                 default:
8875                 case Q3DEFORM_PROJECTIONSHADOW:
8876                 case Q3DEFORM_TEXT0:
8877                 case Q3DEFORM_TEXT1:
8878                 case Q3DEFORM_TEXT2:
8879                 case Q3DEFORM_TEXT3:
8880                 case Q3DEFORM_TEXT4:
8881                 case Q3DEFORM_TEXT5:
8882                 case Q3DEFORM_TEXT6:
8883                 case Q3DEFORM_TEXT7:
8884                 case Q3DEFORM_NONE:
8885                         break;
8886                 case Q3DEFORM_AUTOSPRITE:
8887                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8888                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8889                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8890                         VectorNormalize(newforward);
8891                         VectorNormalize(newright);
8892                         VectorNormalize(newup);
8893 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8894 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8895 //                      rsurface.batchvertex3f_bufferoffset = 0;
8896 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8897 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8898 //                      rsurface.batchsvector3f_bufferoffset = 0;
8899 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8900 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8901 //                      rsurface.batchtvector3f_bufferoffset = 0;
8902 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8903 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8904 //                      rsurface.batchnormal3f_bufferoffset = 0;
8905                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8906                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8907                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8908                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8909                                 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);
8910                         // a single autosprite surface can contain multiple sprites...
8911                         for (j = 0;j < batchnumvertices - 3;j += 4)
8912                         {
8913                                 VectorClear(center);
8914                                 for (i = 0;i < 4;i++)
8915                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8916                                 VectorScale(center, 0.25f, center);
8917                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8918                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8919                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8920                                 for (i = 0;i < 4;i++)
8921                                 {
8922                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8923                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8924                                 }
8925                         }
8926                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8927                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8928                         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);
8929                         break;
8930                 case Q3DEFORM_AUTOSPRITE2:
8931                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8932                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8933                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8934                         VectorNormalize(newforward);
8935                         VectorNormalize(newright);
8936                         VectorNormalize(newup);
8937 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8938 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8939 //                      rsurface.batchvertex3f_bufferoffset = 0;
8940                         {
8941                                 const float *v1, *v2;
8942                                 vec3_t start, end;
8943                                 float f, l;
8944                                 struct
8945                                 {
8946                                         float length2;
8947                                         const float *v1;
8948                                         const float *v2;
8949                                 }
8950                                 shortest[2];
8951                                 memset(shortest, 0, sizeof(shortest));
8952                                 // a single autosprite surface can contain multiple sprites...
8953                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8954                                 {
8955                                         VectorClear(center);
8956                                         for (i = 0;i < 4;i++)
8957                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8958                                         VectorScale(center, 0.25f, center);
8959                                         // find the two shortest edges, then use them to define the
8960                                         // axis vectors for rotating around the central axis
8961                                         for (i = 0;i < 6;i++)
8962                                         {
8963                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8964                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8965                                                 l = VectorDistance2(v1, v2);
8966                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8967                                                 if (v1[2] != v2[2])
8968                                                         l += (1.0f / 1024.0f);
8969                                                 if (shortest[0].length2 > l || i == 0)
8970                                                 {
8971                                                         shortest[1] = shortest[0];
8972                                                         shortest[0].length2 = l;
8973                                                         shortest[0].v1 = v1;
8974                                                         shortest[0].v2 = v2;
8975                                                 }
8976                                                 else if (shortest[1].length2 > l || i == 1)
8977                                                 {
8978                                                         shortest[1].length2 = l;
8979                                                         shortest[1].v1 = v1;
8980                                                         shortest[1].v2 = v2;
8981                                                 }
8982                                         }
8983                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8984                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8985                                         // this calculates the right vector from the shortest edge
8986                                         // and the up vector from the edge midpoints
8987                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8988                                         VectorNormalize(right);
8989                                         VectorSubtract(end, start, up);
8990                                         VectorNormalize(up);
8991                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8992                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8993                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8994                                         VectorNegate(forward, forward);
8995                                         VectorReflect(forward, 0, up, forward);
8996                                         VectorNormalize(forward);
8997                                         CrossProduct(up, forward, newright);
8998                                         VectorNormalize(newright);
8999                                         // rotate the quad around the up axis vector, this is made
9000                                         // especially easy by the fact we know the quad is flat,
9001                                         // so we only have to subtract the center position and
9002                                         // measure distance along the right vector, and then
9003                                         // multiply that by the newright vector and add back the
9004                                         // center position
9005                                         // we also need to subtract the old position to undo the
9006                                         // displacement from the center, which we do with a
9007                                         // DotProduct, the subtraction/addition of center is also
9008                                         // optimized into DotProducts here
9009                                         l = DotProduct(right, center);
9010                                         for (i = 0;i < 4;i++)
9011                                         {
9012                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9013                                                 f = DotProduct(right, v1) - l;
9014                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9015                                         }
9016                                 }
9017                         }
9018                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9019                         {
9020 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9021 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9022 //                              rsurface.batchnormal3f_bufferoffset = 0;
9023                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9024                         }
9025                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9026                         {
9027 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9028 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9029 //                              rsurface.batchsvector3f_bufferoffset = 0;
9030 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9031 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9032 //                              rsurface.batchtvector3f_bufferoffset = 0;
9033                                 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);
9034                         }
9035                         break;
9036                 case Q3DEFORM_NORMAL:
9037                         // deform the normals to make reflections wavey
9038                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9039                         rsurface.batchnormal3f_vertexbuffer = NULL;
9040                         rsurface.batchnormal3f_bufferoffset = 0;
9041                         for (j = 0;j < batchnumvertices;j++)
9042                         {
9043                                 float vertex[3];
9044                                 float *normal = rsurface.batchnormal3f + 3*j;
9045                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9046                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9047                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9048                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9049                                 VectorNormalize(normal);
9050                         }
9051                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9052                         {
9053 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9054 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9055 //                              rsurface.batchsvector3f_bufferoffset = 0;
9056 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9057 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9058 //                              rsurface.batchtvector3f_bufferoffset = 0;
9059                                 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);
9060                         }
9061                         break;
9062                 case Q3DEFORM_WAVE:
9063                         // deform vertex array to make wavey water and flags and such
9064                         waveparms[0] = deform->waveparms[0];
9065                         waveparms[1] = deform->waveparms[1];
9066                         waveparms[2] = deform->waveparms[2];
9067                         waveparms[3] = deform->waveparms[3];
9068                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9069                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9070                         // this is how a divisor of vertex influence on deformation
9071                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9072                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9073 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9074 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9075 //                      rsurface.batchvertex3f_bufferoffset = 0;
9076 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9077 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9078 //                      rsurface.batchnormal3f_bufferoffset = 0;
9079                         for (j = 0;j < batchnumvertices;j++)
9080                         {
9081                                 // if the wavefunc depends on time, evaluate it per-vertex
9082                                 if (waveparms[3])
9083                                 {
9084                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9085                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9086                                 }
9087                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9088                         }
9089                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9090                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9091                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9092                         {
9093 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9094 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9095 //                              rsurface.batchsvector3f_bufferoffset = 0;
9096 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9097 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9098 //                              rsurface.batchtvector3f_bufferoffset = 0;
9099                                 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);
9100                         }
9101                         break;
9102                 case Q3DEFORM_BULGE:
9103                         // deform vertex array to make the surface have moving bulges
9104 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9105 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9106 //                      rsurface.batchvertex3f_bufferoffset = 0;
9107 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9108 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9109 //                      rsurface.batchnormal3f_bufferoffset = 0;
9110                         for (j = 0;j < batchnumvertices;j++)
9111                         {
9112                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9113                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9114                         }
9115                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9116                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9117                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9118                         {
9119 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9120 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9121 //                              rsurface.batchsvector3f_bufferoffset = 0;
9122 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9123 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9124 //                              rsurface.batchtvector3f_bufferoffset = 0;
9125                                 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);
9126                         }
9127                         break;
9128                 case Q3DEFORM_MOVE:
9129                         // deform vertex array
9130                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9131                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9132                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9133                         VectorScale(deform->parms, scale, waveparms);
9134 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9135 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9136 //                      rsurface.batchvertex3f_bufferoffset = 0;
9137                         for (j = 0;j < batchnumvertices;j++)
9138                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9139                         break;
9140                 }
9141         }
9142
9143         // generate texcoords based on the chosen texcoord source
9144         switch(rsurface.texture->tcgen.tcgen)
9145         {
9146         default:
9147         case Q3TCGEN_TEXTURE:
9148                 break;
9149         case Q3TCGEN_LIGHTMAP:
9150 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9151 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9152 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9153                 if (rsurface.batchtexcoordlightmap2f)
9154                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9155                 break;
9156         case Q3TCGEN_VECTOR:
9157 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9158 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9159 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9160                 for (j = 0;j < batchnumvertices;j++)
9161                 {
9162                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9163                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9164                 }
9165                 break;
9166         case Q3TCGEN_ENVIRONMENT:
9167                 // make environment reflections using a spheremap
9168                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9169                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9170                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9171                 for (j = 0;j < batchnumvertices;j++)
9172                 {
9173                         // identical to Q3A's method, but executed in worldspace so
9174                         // carried models can be shiny too
9175
9176                         float viewer[3], d, reflected[3], worldreflected[3];
9177
9178                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9179                         // VectorNormalize(viewer);
9180
9181                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9182
9183                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9184                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9185                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9186                         // note: this is proportinal to viewer, so we can normalize later
9187
9188                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9189                         VectorNormalize(worldreflected);
9190
9191                         // note: this sphere map only uses world x and z!
9192                         // so positive and negative y will LOOK THE SAME.
9193                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9194                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9195                 }
9196                 break;
9197         }
9198         // the only tcmod that needs software vertex processing is turbulent, so
9199         // check for it here and apply the changes if needed
9200         // and we only support that as the first one
9201         // (handling a mixture of turbulent and other tcmods would be problematic
9202         //  without punting it entirely to a software path)
9203         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9204         {
9205                 amplitude = rsurface.texture->tcmods[0].parms[1];
9206                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9207 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9208 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9209 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9210                 for (j = 0;j < batchnumvertices;j++)
9211                 {
9212                         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);
9213                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9214                 }
9215         }
9216
9217         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9218         {
9219                 // convert the modified arrays to vertex structs
9220 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9221 //              rsurface.batchvertexmeshbuffer = NULL;
9222                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9223                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9224                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9225                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9226                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9227                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9228                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9229                 {
9230                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9231                         {
9232                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9233                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9234                         }
9235                 }
9236                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9237                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9238                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9239                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9240                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9241                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9242                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9243                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9244                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9245         }
9246 }
9247
9248 void RSurf_DrawBatch(void)
9249 {
9250         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9251         // through the pipeline, killing it earlier in the pipeline would have
9252         // per-surface overhead rather than per-batch overhead, so it's best to
9253         // reject it here, before it hits glDraw.
9254         if (rsurface.batchnumtriangles == 0)
9255                 return;
9256 #if 0
9257         // batch debugging code
9258         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9259         {
9260                 int i;
9261                 int j;
9262                 int c;
9263                 const int *e;
9264                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9265                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9266                 {
9267                         c = e[i];
9268                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9269                         {
9270                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9271                                 {
9272                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9273                                                 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);
9274                                         break;
9275                                 }
9276                         }
9277                 }
9278         }
9279 #endif
9280         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);
9281 }
9282
9283 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9284 {
9285         // pick the closest matching water plane
9286         int planeindex, vertexindex, bestplaneindex = -1;
9287         float d, bestd;
9288         vec3_t vert;
9289         const float *v;
9290         r_waterstate_waterplane_t *p;
9291         qboolean prepared = false;
9292         bestd = 0;
9293         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9294         {
9295                 if(p->camera_entity != rsurface.texture->camera_entity)
9296                         continue;
9297                 d = 0;
9298                 if(!prepared)
9299                 {
9300                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9301                         prepared = true;
9302                         if(rsurface.batchnumvertices == 0)
9303                                 break;
9304                 }
9305                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9306                 {
9307                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9308                         d += fabs(PlaneDiff(vert, &p->plane));
9309                 }
9310                 if (bestd > d || bestplaneindex < 0)
9311                 {
9312                         bestd = d;
9313                         bestplaneindex = planeindex;
9314                 }
9315         }
9316         return bestplaneindex;
9317         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9318         // this situation though, as it might be better to render single larger
9319         // batches with useless stuff (backface culled for example) than to
9320         // render multiple smaller batches
9321 }
9322
9323 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9324 {
9325         int i;
9326         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9327         rsurface.passcolor4f_vertexbuffer = 0;
9328         rsurface.passcolor4f_bufferoffset = 0;
9329         for (i = 0;i < rsurface.batchnumvertices;i++)
9330                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9331 }
9332
9333 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9334 {
9335         int i;
9336         float f;
9337         const float *v;
9338         const float *c;
9339         float *c2;
9340         if (rsurface.passcolor4f)
9341         {
9342                 // generate color arrays
9343                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9344                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9345                 rsurface.passcolor4f_vertexbuffer = 0;
9346                 rsurface.passcolor4f_bufferoffset = 0;
9347                 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)
9348                 {
9349                         f = RSurf_FogVertex(v);
9350                         c2[0] = c[0] * f;
9351                         c2[1] = c[1] * f;
9352                         c2[2] = c[2] * f;
9353                         c2[3] = c[3];
9354                 }
9355         }
9356         else
9357         {
9358                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9359                 rsurface.passcolor4f_vertexbuffer = 0;
9360                 rsurface.passcolor4f_bufferoffset = 0;
9361                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9362                 {
9363                         f = RSurf_FogVertex(v);
9364                         c2[0] = f;
9365                         c2[1] = f;
9366                         c2[2] = f;
9367                         c2[3] = 1;
9368                 }
9369         }
9370 }
9371
9372 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9373 {
9374         int i;
9375         float f;
9376         const float *v;
9377         const float *c;
9378         float *c2;
9379         if (!rsurface.passcolor4f)
9380                 return;
9381         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9382         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9383         rsurface.passcolor4f_vertexbuffer = 0;
9384         rsurface.passcolor4f_bufferoffset = 0;
9385         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)
9386         {
9387                 f = RSurf_FogVertex(v);
9388                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9389                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9390                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9391                 c2[3] = c[3];
9392         }
9393 }
9394
9395 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9396 {
9397         int i;
9398         const float *c;
9399         float *c2;
9400         if (!rsurface.passcolor4f)
9401                 return;
9402         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9403         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9404         rsurface.passcolor4f_vertexbuffer = 0;
9405         rsurface.passcolor4f_bufferoffset = 0;
9406         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9407         {
9408                 c2[0] = c[0] * r;
9409                 c2[1] = c[1] * g;
9410                 c2[2] = c[2] * b;
9411                 c2[3] = c[3] * a;
9412         }
9413 }
9414
9415 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9416 {
9417         int i;
9418         const float *c;
9419         float *c2;
9420         if (!rsurface.passcolor4f)
9421                 return;
9422         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9423         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9424         rsurface.passcolor4f_vertexbuffer = 0;
9425         rsurface.passcolor4f_bufferoffset = 0;
9426         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9427         {
9428                 c2[0] = c[0] + r_refdef.scene.ambient;
9429                 c2[1] = c[1] + r_refdef.scene.ambient;
9430                 c2[2] = c[2] + r_refdef.scene.ambient;
9431                 c2[3] = c[3];
9432         }
9433 }
9434
9435 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9436 {
9437         // TODO: optimize
9438         rsurface.passcolor4f = NULL;
9439         rsurface.passcolor4f_vertexbuffer = 0;
9440         rsurface.passcolor4f_bufferoffset = 0;
9441         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9442         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9443         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9444         GL_Color(r, g, b, a);
9445         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9446         RSurf_DrawBatch();
9447 }
9448
9449 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9450 {
9451         // TODO: optimize applyfog && applycolor case
9452         // just apply fog if necessary, and tint the fog color array if necessary
9453         rsurface.passcolor4f = NULL;
9454         rsurface.passcolor4f_vertexbuffer = 0;
9455         rsurface.passcolor4f_bufferoffset = 0;
9456         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9457         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9458         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9459         GL_Color(r, g, b, a);
9460         RSurf_DrawBatch();
9461 }
9462
9463 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9464 {
9465         // TODO: optimize
9466         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9467         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9468         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9469         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9470         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9471         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9472         GL_Color(r, g, b, a);
9473         RSurf_DrawBatch();
9474 }
9475
9476 static void RSurf_DrawBatch_GL11_ClampColor(void)
9477 {
9478         int i;
9479         const float *c1;
9480         float *c2;
9481         if (!rsurface.passcolor4f)
9482                 return;
9483         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9484         {
9485                 c2[0] = bound(0.0f, c1[0], 1.0f);
9486                 c2[1] = bound(0.0f, c1[1], 1.0f);
9487                 c2[2] = bound(0.0f, c1[2], 1.0f);
9488                 c2[3] = bound(0.0f, c1[3], 1.0f);
9489         }
9490 }
9491
9492 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9493 {
9494         int i;
9495         float f;
9496         const float *v;
9497         const float *n;
9498         float *c;
9499         //vec3_t eyedir;
9500
9501         // fake shading
9502         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9503         rsurface.passcolor4f_vertexbuffer = 0;
9504         rsurface.passcolor4f_bufferoffset = 0;
9505         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)
9506         {
9507                 f = -DotProduct(r_refdef.view.forward, n);
9508                 f = max(0, f);
9509                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9510                 f *= r_refdef.lightmapintensity;
9511                 Vector4Set(c, f, f, f, 1);
9512         }
9513 }
9514
9515 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9516 {
9517         RSurf_DrawBatch_GL11_ApplyFakeLight();
9518         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9519         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9520         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9521         GL_Color(r, g, b, a);
9522         RSurf_DrawBatch();
9523 }
9524
9525 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9526 {
9527         int i;
9528         float f;
9529         float alpha;
9530         const float *v;
9531         const float *n;
9532         float *c;
9533         vec3_t ambientcolor;
9534         vec3_t diffusecolor;
9535         vec3_t lightdir;
9536         // TODO: optimize
9537         // model lighting
9538         VectorCopy(rsurface.modellight_lightdir, lightdir);
9539         f = 0.5f * r_refdef.lightmapintensity;
9540         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9541         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9542         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9543         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9544         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9545         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9546         alpha = *a;
9547         if (VectorLength2(diffusecolor) > 0)
9548         {
9549                 // q3-style directional shading
9550                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9551                 rsurface.passcolor4f_vertexbuffer = 0;
9552                 rsurface.passcolor4f_bufferoffset = 0;
9553                 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)
9554                 {
9555                         if ((f = DotProduct(n, lightdir)) > 0)
9556                                 VectorMA(ambientcolor, f, diffusecolor, c);
9557                         else
9558                                 VectorCopy(ambientcolor, c);
9559                         c[3] = alpha;
9560                 }
9561                 *r = 1;
9562                 *g = 1;
9563                 *b = 1;
9564                 *a = 1;
9565                 *applycolor = false;
9566         }
9567         else
9568         {
9569                 *r = ambientcolor[0];
9570                 *g = ambientcolor[1];
9571                 *b = ambientcolor[2];
9572                 rsurface.passcolor4f = NULL;
9573                 rsurface.passcolor4f_vertexbuffer = 0;
9574                 rsurface.passcolor4f_bufferoffset = 0;
9575         }
9576 }
9577
9578 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9579 {
9580         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9581         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9582         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9583         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9584         GL_Color(r, g, b, a);
9585         RSurf_DrawBatch();
9586 }
9587
9588 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9589 {
9590         int i;
9591         float f;
9592         const float *v;
9593         float *c;
9594
9595         // fake shading
9596         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9597         rsurface.passcolor4f_vertexbuffer = 0;
9598         rsurface.passcolor4f_bufferoffset = 0;
9599
9600         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9601         {
9602                 f = 1 - RSurf_FogVertex(v);
9603                 c[0] = r;
9604                 c[1] = g;
9605                 c[2] = b;
9606                 c[3] = f * a;
9607         }
9608 }
9609
9610 void RSurf_SetupDepthAndCulling(void)
9611 {
9612         // submodels are biased to avoid z-fighting with world surfaces that they
9613         // may be exactly overlapping (avoids z-fighting artifacts on certain
9614         // doors and things in Quake maps)
9615         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9616         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9617         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9618         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9619 }
9620
9621 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9622 {
9623         // transparent sky would be ridiculous
9624         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9625                 return;
9626         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9627         skyrenderlater = true;
9628         RSurf_SetupDepthAndCulling();
9629         GL_DepthMask(true);
9630         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9631         // skymasking on them, and Quake3 never did sky masking (unlike
9632         // software Quake and software Quake2), so disable the sky masking
9633         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9634         // and skymasking also looks very bad when noclipping outside the
9635         // level, so don't use it then either.
9636         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9637         {
9638                 R_Mesh_ResetTextureState();
9639                 if (skyrendermasked)
9640                 {
9641                         R_SetupShader_DepthOrShadow(false);
9642                         // depth-only (masking)
9643                         GL_ColorMask(0,0,0,0);
9644                         // just to make sure that braindead drivers don't draw
9645                         // anything despite that colormask...
9646                         GL_BlendFunc(GL_ZERO, GL_ONE);
9647                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9648                         if (rsurface.batchvertex3fbuffer)
9649                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9650                         else
9651                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9652                 }
9653                 else
9654                 {
9655                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9656                         // fog sky
9657                         GL_BlendFunc(GL_ONE, GL_ZERO);
9658                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9659                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9660                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9661                 }
9662                 RSurf_DrawBatch();
9663                 if (skyrendermasked)
9664                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9665         }
9666         R_Mesh_ResetTextureState();
9667         GL_Color(1, 1, 1, 1);
9668 }
9669
9670 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9671 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9672 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9673 {
9674         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9675                 return;
9676         if (prepass)
9677         {
9678                 // render screenspace normalmap to texture
9679                 GL_DepthMask(true);
9680                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9681                 RSurf_DrawBatch();
9682         }
9683
9684         // bind lightmap texture
9685
9686         // water/refraction/reflection/camera surfaces have to be handled specially
9687         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9688         {
9689                 int start, end, startplaneindex;
9690                 for (start = 0;start < texturenumsurfaces;start = end)
9691                 {
9692                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9693                         if(startplaneindex < 0)
9694                         {
9695                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9696                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9697                                 end = start + 1;
9698                                 continue;
9699                         }
9700                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9701                                 ;
9702                         // now that we have a batch using the same planeindex, render it
9703                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9704                         {
9705                                 // render water or distortion background
9706                                 GL_DepthMask(true);
9707                                 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);
9708                                 RSurf_DrawBatch();
9709                                 // blend surface on top
9710                                 GL_DepthMask(false);
9711                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9712                                 RSurf_DrawBatch();
9713                         }
9714                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9715                         {
9716                                 // render surface with reflection texture as input
9717                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9718                                 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);
9719                                 RSurf_DrawBatch();
9720                         }
9721                 }
9722                 return;
9723         }
9724
9725         // render surface batch normally
9726         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9727         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);
9728         RSurf_DrawBatch();
9729 }
9730
9731 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9732 {
9733         // OpenGL 1.3 path - anything not completely ancient
9734         qboolean applycolor;
9735         qboolean applyfog;
9736         int layerindex;
9737         const texturelayer_t *layer;
9738         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);
9739         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9740
9741         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9742         {
9743                 vec4_t layercolor;
9744                 int layertexrgbscale;
9745                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9746                 {
9747                         if (layerindex == 0)
9748                                 GL_AlphaTest(true);
9749                         else
9750                         {
9751                                 GL_AlphaTest(false);
9752                                 GL_DepthFunc(GL_EQUAL);
9753                         }
9754                 }
9755                 GL_DepthMask(layer->depthmask && writedepth);
9756                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9757                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9758                 {
9759                         layertexrgbscale = 4;
9760                         VectorScale(layer->color, 0.25f, layercolor);
9761                 }
9762                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9763                 {
9764                         layertexrgbscale = 2;
9765                         VectorScale(layer->color, 0.5f, layercolor);
9766                 }
9767                 else
9768                 {
9769                         layertexrgbscale = 1;
9770                         VectorScale(layer->color, 1.0f, layercolor);
9771                 }
9772                 layercolor[3] = layer->color[3];
9773                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9774                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9775                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9776                 switch (layer->type)
9777                 {
9778                 case TEXTURELAYERTYPE_LITTEXTURE:
9779                         // single-pass lightmapped texture with 2x rgbscale
9780                         R_Mesh_TexBind(0, r_texture_white);
9781                         R_Mesh_TexMatrix(0, NULL);
9782                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9783                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9784                         R_Mesh_TexBind(1, layer->texture);
9785                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9786                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9787                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9788                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9789                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9790                         else if (FAKELIGHT_ENABLED)
9791                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9792                         else if (rsurface.uselightmaptexture)
9793                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9794                         else
9795                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9796                         break;
9797                 case TEXTURELAYERTYPE_TEXTURE:
9798                         // singletexture unlit texture with transparency support
9799                         R_Mesh_TexBind(0, layer->texture);
9800                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9801                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9802                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9803                         R_Mesh_TexBind(1, 0);
9804                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9805                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9806                         break;
9807                 case TEXTURELAYERTYPE_FOG:
9808                         // singletexture fogging
9809                         if (layer->texture)
9810                         {
9811                                 R_Mesh_TexBind(0, layer->texture);
9812                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9813                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9814                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9815                         }
9816                         else
9817                         {
9818                                 R_Mesh_TexBind(0, 0);
9819                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9820                         }
9821                         R_Mesh_TexBind(1, 0);
9822                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9823                         // generate a color array for the fog pass
9824                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9825                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9826                         RSurf_DrawBatch();
9827                         break;
9828                 default:
9829                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9830                 }
9831         }
9832         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9833         {
9834                 GL_DepthFunc(GL_LEQUAL);
9835                 GL_AlphaTest(false);
9836         }
9837 }
9838
9839 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9840 {
9841         // OpenGL 1.1 - crusty old voodoo path
9842         qboolean applyfog;
9843         int layerindex;
9844         const texturelayer_t *layer;
9845         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);
9846         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9847
9848         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9849         {
9850                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9851                 {
9852                         if (layerindex == 0)
9853                                 GL_AlphaTest(true);
9854                         else
9855                         {
9856                                 GL_AlphaTest(false);
9857                                 GL_DepthFunc(GL_EQUAL);
9858                         }
9859                 }
9860                 GL_DepthMask(layer->depthmask && writedepth);
9861                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9862                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9863                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9864                 switch (layer->type)
9865                 {
9866                 case TEXTURELAYERTYPE_LITTEXTURE:
9867                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9868                         {
9869                                 // two-pass lit texture with 2x rgbscale
9870                                 // first the lightmap pass
9871                                 R_Mesh_TexBind(0, r_texture_white);
9872                                 R_Mesh_TexMatrix(0, NULL);
9873                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9874                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9875                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9876                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9877                                 else if (FAKELIGHT_ENABLED)
9878                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9879                                 else if (rsurface.uselightmaptexture)
9880                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9881                                 else
9882                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9883                                 // then apply the texture to it
9884                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9885                                 R_Mesh_TexBind(0, layer->texture);
9886                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9887                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9888                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9889                                 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);
9890                         }
9891                         else
9892                         {
9893                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9894                                 R_Mesh_TexBind(0, layer->texture);
9895                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9896                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9897                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9898                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9899                                         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);
9900                                 else
9901                                         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);
9902                         }
9903                         break;
9904                 case TEXTURELAYERTYPE_TEXTURE:
9905                         // singletexture unlit texture with transparency support
9906                         R_Mesh_TexBind(0, layer->texture);
9907                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9908                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9909                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9910                         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);
9911                         break;
9912                 case TEXTURELAYERTYPE_FOG:
9913                         // singletexture fogging
9914                         if (layer->texture)
9915                         {
9916                                 R_Mesh_TexBind(0, layer->texture);
9917                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9918                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9919                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9920                         }
9921                         else
9922                         {
9923                                 R_Mesh_TexBind(0, 0);
9924                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9925                         }
9926                         // generate a color array for the fog pass
9927                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9928                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9929                         RSurf_DrawBatch();
9930                         break;
9931                 default:
9932                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9933                 }
9934         }
9935         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9936         {
9937                 GL_DepthFunc(GL_LEQUAL);
9938                 GL_AlphaTest(false);
9939         }
9940 }
9941
9942 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9943 {
9944         int vi;
9945         int j;
9946         r_vertexgeneric_t *batchvertex;
9947         float c[4];
9948
9949 //      R_Mesh_ResetTextureState();
9950         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9951
9952         if(rsurface.texture && rsurface.texture->currentskinframe)
9953         {
9954                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9955                 c[3] *= rsurface.texture->currentalpha;
9956         }
9957         else
9958         {
9959                 c[0] = 1;
9960                 c[1] = 0;
9961                 c[2] = 1;
9962                 c[3] = 1;
9963         }
9964
9965         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9966         {
9967                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9968                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9969                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9970         }
9971
9972         // brighten it up (as texture value 127 means "unlit")
9973         c[0] *= 2 * r_refdef.view.colorscale;
9974         c[1] *= 2 * r_refdef.view.colorscale;
9975         c[2] *= 2 * r_refdef.view.colorscale;
9976
9977         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9978                 c[3] *= r_wateralpha.value;
9979
9980         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9981         {
9982                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9983                 GL_DepthMask(false);
9984         }
9985         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9986         {
9987                 GL_BlendFunc(GL_ONE, GL_ONE);
9988                 GL_DepthMask(false);
9989         }
9990         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9991         {
9992                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9993                 GL_DepthMask(false);
9994         }
9995         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9996         {
9997                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9998                 GL_DepthMask(false);
9999         }
10000         else
10001         {
10002                 GL_BlendFunc(GL_ONE, GL_ZERO);
10003                 GL_DepthMask(writedepth);
10004         }
10005
10006         if (r_showsurfaces.integer == 3)
10007         {
10008                 rsurface.passcolor4f = NULL;
10009
10010                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10011                 {
10012                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10013
10014                         rsurface.passcolor4f = NULL;
10015                         rsurface.passcolor4f_vertexbuffer = 0;
10016                         rsurface.passcolor4f_bufferoffset = 0;
10017                 }
10018                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10019                 {
10020                         qboolean applycolor = true;
10021                         float one = 1.0;
10022
10023                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10024
10025                         r_refdef.lightmapintensity = 1;
10026                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10027                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10028                 }
10029                 else if (FAKELIGHT_ENABLED)
10030                 {
10031                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10032
10033                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10034                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10035                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10036                 }
10037                 else
10038                 {
10039                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10040
10041                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10042                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10043                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10044                 }
10045
10046                 if(!rsurface.passcolor4f)
10047                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10048
10049                 RSurf_DrawBatch_GL11_ApplyAmbient();
10050                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10051                 if(r_refdef.fogenabled)
10052                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10053                 RSurf_DrawBatch_GL11_ClampColor();
10054
10055                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10056                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10057                 RSurf_DrawBatch();
10058         }
10059         else if (!r_refdef.view.showdebug)
10060         {
10061                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10062                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10063                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10064                 {
10065                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10066                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10067                 }
10068                 R_Mesh_PrepareVertices_Generic_Unlock();
10069                 RSurf_DrawBatch();
10070         }
10071         else if (r_showsurfaces.integer == 4)
10072         {
10073                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10074                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10075                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10076                 {
10077                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10078                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10079                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10080                 }
10081                 R_Mesh_PrepareVertices_Generic_Unlock();
10082                 RSurf_DrawBatch();
10083         }
10084         else if (r_showsurfaces.integer == 2)
10085         {
10086                 const int *e;
10087                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10088                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10089                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10090                 {
10091                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10092                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10093                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10094                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10095                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10096                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10097                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10098                 }
10099                 R_Mesh_PrepareVertices_Generic_Unlock();
10100                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10101         }
10102         else
10103         {
10104                 int texturesurfaceindex;
10105                 int k;
10106                 const msurface_t *surface;
10107                 float surfacecolor4f[4];
10108                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10109                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10110                 vi = 0;
10111                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10112                 {
10113                         surface = texturesurfacelist[texturesurfaceindex];
10114                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10115                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10116                         for (j = 0;j < surface->num_vertices;j++)
10117                         {
10118                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10119                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10120                                 vi++;
10121                         }
10122                 }
10123                 R_Mesh_PrepareVertices_Generic_Unlock();
10124                 RSurf_DrawBatch();
10125         }
10126 }
10127
10128 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10129 {
10130         CHECKGLERROR
10131         RSurf_SetupDepthAndCulling();
10132         if (r_showsurfaces.integer)
10133         {
10134                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10135                 return;
10136         }
10137         switch (vid.renderpath)
10138         {
10139         case RENDERPATH_GL20:
10140         case RENDERPATH_D3D9:
10141         case RENDERPATH_D3D10:
10142         case RENDERPATH_D3D11:
10143         case RENDERPATH_SOFT:
10144         case RENDERPATH_GLES2:
10145                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10146                 break;
10147         case RENDERPATH_GL13:
10148         case RENDERPATH_GLES1:
10149                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10150                 break;
10151         case RENDERPATH_GL11:
10152                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10153                 break;
10154         }
10155         CHECKGLERROR
10156 }
10157
10158 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10159 {
10160         CHECKGLERROR
10161         RSurf_SetupDepthAndCulling();
10162         if (r_showsurfaces.integer)
10163         {
10164                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10165                 return;
10166         }
10167         switch (vid.renderpath)
10168         {
10169         case RENDERPATH_GL20:
10170         case RENDERPATH_D3D9:
10171         case RENDERPATH_D3D10:
10172         case RENDERPATH_D3D11:
10173         case RENDERPATH_SOFT:
10174         case RENDERPATH_GLES2:
10175                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10176                 break;
10177         case RENDERPATH_GL13:
10178         case RENDERPATH_GLES1:
10179                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10180                 break;
10181         case RENDERPATH_GL11:
10182                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10183                 break;
10184         }
10185         CHECKGLERROR
10186 }
10187
10188 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10189 {
10190         int i, j;
10191         int texturenumsurfaces, endsurface;
10192         texture_t *texture;
10193         const msurface_t *surface;
10194         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10195
10196         // if the model is static it doesn't matter what value we give for
10197         // wantnormals and wanttangents, so this logic uses only rules applicable
10198         // to a model, knowing that they are meaningless otherwise
10199         if (ent == r_refdef.scene.worldentity)
10200                 RSurf_ActiveWorldEntity();
10201         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10202                 RSurf_ActiveModelEntity(ent, false, false, false);
10203         else
10204         {
10205                 switch (vid.renderpath)
10206                 {
10207                 case RENDERPATH_GL20:
10208                 case RENDERPATH_D3D9:
10209                 case RENDERPATH_D3D10:
10210                 case RENDERPATH_D3D11:
10211                 case RENDERPATH_SOFT:
10212                 case RENDERPATH_GLES2:
10213                         RSurf_ActiveModelEntity(ent, true, true, false);
10214                         break;
10215                 case RENDERPATH_GL11:
10216                 case RENDERPATH_GL13:
10217                 case RENDERPATH_GLES1:
10218                         RSurf_ActiveModelEntity(ent, true, false, false);
10219                         break;
10220                 }
10221         }
10222
10223         if (r_transparentdepthmasking.integer)
10224         {
10225                 qboolean setup = false;
10226                 for (i = 0;i < numsurfaces;i = j)
10227                 {
10228                         j = i + 1;
10229                         surface = rsurface.modelsurfaces + surfacelist[i];
10230                         texture = surface->texture;
10231                         rsurface.texture = R_GetCurrentTexture(texture);
10232                         rsurface.lightmaptexture = NULL;
10233                         rsurface.deluxemaptexture = NULL;
10234                         rsurface.uselightmaptexture = false;
10235                         // scan ahead until we find a different texture
10236                         endsurface = min(i + 1024, numsurfaces);
10237                         texturenumsurfaces = 0;
10238                         texturesurfacelist[texturenumsurfaces++] = surface;
10239                         for (;j < endsurface;j++)
10240                         {
10241                                 surface = rsurface.modelsurfaces + surfacelist[j];
10242                                 if (texture != surface->texture)
10243                                         break;
10244                                 texturesurfacelist[texturenumsurfaces++] = surface;
10245                         }
10246                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10247                                 continue;
10248                         // render the range of surfaces as depth
10249                         if (!setup)
10250                         {
10251                                 setup = true;
10252                                 GL_ColorMask(0,0,0,0);
10253                                 GL_Color(1,1,1,1);
10254                                 GL_DepthTest(true);
10255                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10256                                 GL_DepthMask(true);
10257 //                              R_Mesh_ResetTextureState();
10258                                 R_SetupShader_DepthOrShadow(false);
10259                         }
10260                         RSurf_SetupDepthAndCulling();
10261                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10262                         if (rsurface.batchvertex3fbuffer)
10263                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10264                         else
10265                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10266                         RSurf_DrawBatch();
10267                 }
10268                 if (setup)
10269                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10270         }
10271
10272         for (i = 0;i < numsurfaces;i = j)
10273         {
10274                 j = i + 1;
10275                 surface = rsurface.modelsurfaces + surfacelist[i];
10276                 texture = surface->texture;
10277                 rsurface.texture = R_GetCurrentTexture(texture);
10278                 // scan ahead until we find a different texture
10279                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10280                 texturenumsurfaces = 0;
10281                 texturesurfacelist[texturenumsurfaces++] = surface;
10282                 if(FAKELIGHT_ENABLED)
10283                 {
10284                         rsurface.lightmaptexture = NULL;
10285                         rsurface.deluxemaptexture = NULL;
10286                         rsurface.uselightmaptexture = false;
10287                         for (;j < endsurface;j++)
10288                         {
10289                                 surface = rsurface.modelsurfaces + surfacelist[j];
10290                                 if (texture != surface->texture)
10291                                         break;
10292                                 texturesurfacelist[texturenumsurfaces++] = surface;
10293                         }
10294                 }
10295                 else
10296                 {
10297                         rsurface.lightmaptexture = surface->lightmaptexture;
10298                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10299                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10300                         for (;j < endsurface;j++)
10301                         {
10302                                 surface = rsurface.modelsurfaces + surfacelist[j];
10303                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10304                                         break;
10305                                 texturesurfacelist[texturenumsurfaces++] = surface;
10306                         }
10307                 }
10308                 // render the range of surfaces
10309                 if (ent == r_refdef.scene.worldentity)
10310                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10311                 else
10312                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10313         }
10314         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10315 }
10316
10317 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10318 {
10319         // transparent surfaces get pushed off into the transparent queue
10320         int surfacelistindex;
10321         const msurface_t *surface;
10322         vec3_t tempcenter, center;
10323         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10324         {
10325                 surface = texturesurfacelist[surfacelistindex];
10326                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10327                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10328                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10329                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10330                 if (queueentity->transparent_offset) // transparent offset
10331                 {
10332                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10333                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10334                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10335                 }
10336                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10337         }
10338 }
10339
10340 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10341 {
10342         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10343                 return;
10344         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10345                 return;
10346         RSurf_SetupDepthAndCulling();
10347         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10348         if (rsurface.batchvertex3fbuffer)
10349                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10350         else
10351                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10352         RSurf_DrawBatch();
10353 }
10354
10355 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10356 {
10357         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10358         CHECKGLERROR
10359         if (depthonly)
10360                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10361         else if (prepass)
10362         {
10363                 if (!rsurface.texture->currentnumlayers)
10364                         return;
10365                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10366                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10367                 else
10368                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10369         }
10370         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10371                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10372         else if (!rsurface.texture->currentnumlayers)
10373                 return;
10374         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10375         {
10376                 // in the deferred case, transparent surfaces were queued during prepass
10377                 if (!r_shadow_usingdeferredprepass)
10378                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10379         }
10380         else
10381         {
10382                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10383                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10384         }
10385         CHECKGLERROR
10386 }
10387
10388 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10389 {
10390         int i, j;
10391         texture_t *texture;
10392         R_FrameData_SetMark();
10393         // break the surface list down into batches by texture and use of lightmapping
10394         for (i = 0;i < numsurfaces;i = j)
10395         {
10396                 j = i + 1;
10397                 // texture is the base texture pointer, rsurface.texture is the
10398                 // current frame/skin the texture is directing us to use (for example
10399                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10400                 // use skin 1 instead)
10401                 texture = surfacelist[i]->texture;
10402                 rsurface.texture = R_GetCurrentTexture(texture);
10403                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10404                 {
10405                         // if this texture is not the kind we want, skip ahead to the next one
10406                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10407                                 ;
10408                         continue;
10409                 }
10410                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10411                 {
10412                         rsurface.lightmaptexture = NULL;
10413                         rsurface.deluxemaptexture = NULL;
10414                         rsurface.uselightmaptexture = false;
10415                         // simply scan ahead until we find a different texture or lightmap state
10416                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10417                                 ;
10418                 }
10419                 else
10420                 {
10421                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10422                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10423                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10424                         // simply scan ahead until we find a different texture or lightmap state
10425                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10426                                 ;
10427                 }
10428                 // render the range of surfaces
10429                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10430         }
10431         R_FrameData_ReturnToMark();
10432 }
10433
10434 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10435 {
10436         CHECKGLERROR
10437         if (depthonly)
10438                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10439         else if (prepass)
10440         {
10441                 if (!rsurface.texture->currentnumlayers)
10442                         return;
10443                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10444                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10445                 else
10446                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10447         }
10448         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10449                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10450         else if (!rsurface.texture->currentnumlayers)
10451                 return;
10452         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10453         {
10454                 // in the deferred case, transparent surfaces were queued during prepass
10455                 if (!r_shadow_usingdeferredprepass)
10456                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10457         }
10458         else
10459         {
10460                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10461                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10462         }
10463         CHECKGLERROR
10464 }
10465
10466 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10467 {
10468         int i, j;
10469         texture_t *texture;
10470         R_FrameData_SetMark();
10471         // break the surface list down into batches by texture and use of lightmapping
10472         for (i = 0;i < numsurfaces;i = j)
10473         {
10474                 j = i + 1;
10475                 // texture is the base texture pointer, rsurface.texture is the
10476                 // current frame/skin the texture is directing us to use (for example
10477                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10478                 // use skin 1 instead)
10479                 texture = surfacelist[i]->texture;
10480                 rsurface.texture = R_GetCurrentTexture(texture);
10481                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10482                 {
10483                         // if this texture is not the kind we want, skip ahead to the next one
10484                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10485                                 ;
10486                         continue;
10487                 }
10488                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10489                 {
10490                         rsurface.lightmaptexture = NULL;
10491                         rsurface.deluxemaptexture = NULL;
10492                         rsurface.uselightmaptexture = false;
10493                         // simply scan ahead until we find a different texture or lightmap state
10494                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10495                                 ;
10496                 }
10497                 else
10498                 {
10499                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10500                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10501                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10502                         // simply scan ahead until we find a different texture or lightmap state
10503                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10504                                 ;
10505                 }
10506                 // render the range of surfaces
10507                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10508         }
10509         R_FrameData_ReturnToMark();
10510 }
10511
10512 float locboxvertex3f[6*4*3] =
10513 {
10514         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10515         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10516         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10517         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10518         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10519         1,0,0, 0,0,0, 0,1,0, 1,1,0
10520 };
10521
10522 unsigned short locboxelements[6*2*3] =
10523 {
10524          0, 1, 2, 0, 2, 3,
10525          4, 5, 6, 4, 6, 7,
10526          8, 9,10, 8,10,11,
10527         12,13,14, 12,14,15,
10528         16,17,18, 16,18,19,
10529         20,21,22, 20,22,23
10530 };
10531
10532 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10533 {
10534         int i, j;
10535         cl_locnode_t *loc = (cl_locnode_t *)ent;
10536         vec3_t mins, size;
10537         float vertex3f[6*4*3];
10538         CHECKGLERROR
10539         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10540         GL_DepthMask(false);
10541         GL_DepthRange(0, 1);
10542         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10543         GL_DepthTest(true);
10544         GL_CullFace(GL_NONE);
10545         R_EntityMatrix(&identitymatrix);
10546
10547 //      R_Mesh_ResetTextureState();
10548
10549         i = surfacelist[0];
10550         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10551                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10552                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10553                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10554
10555         if (VectorCompare(loc->mins, loc->maxs))
10556         {
10557                 VectorSet(size, 2, 2, 2);
10558                 VectorMA(loc->mins, -0.5f, size, mins);
10559         }
10560         else
10561         {
10562                 VectorCopy(loc->mins, mins);
10563                 VectorSubtract(loc->maxs, loc->mins, size);
10564         }
10565
10566         for (i = 0;i < 6*4*3;)
10567                 for (j = 0;j < 3;j++, i++)
10568                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10569
10570         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10571         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10572         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10573 }
10574
10575 void R_DrawLocs(void)
10576 {
10577         int index;
10578         cl_locnode_t *loc, *nearestloc;
10579         vec3_t center;
10580         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10581         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10582         {
10583                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10584                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10585         }
10586 }
10587
10588 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10589 {
10590         if (decalsystem->decals)
10591                 Mem_Free(decalsystem->decals);
10592         memset(decalsystem, 0, sizeof(*decalsystem));
10593 }
10594
10595 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)
10596 {
10597         tridecal_t *decal;
10598         tridecal_t *decals;
10599         int i;
10600
10601         // expand or initialize the system
10602         if (decalsystem->maxdecals <= decalsystem->numdecals)
10603         {
10604                 decalsystem_t old = *decalsystem;
10605                 qboolean useshortelements;
10606                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10607                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10608                 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)));
10609                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10610                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10611                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10612                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10613                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10614                 if (decalsystem->numdecals)
10615                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10616                 if (old.decals)
10617                         Mem_Free(old.decals);
10618                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10619                         decalsystem->element3i[i] = i;
10620                 if (useshortelements)
10621                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10622                                 decalsystem->element3s[i] = i;
10623         }
10624
10625         // grab a decal and search for another free slot for the next one
10626         decals = decalsystem->decals;
10627         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10628         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10629                 ;
10630         decalsystem->freedecal = i;
10631         if (decalsystem->numdecals <= i)
10632                 decalsystem->numdecals = i + 1;
10633
10634         // initialize the decal
10635         decal->lived = 0;
10636         decal->triangleindex = triangleindex;
10637         decal->surfaceindex = surfaceindex;
10638         decal->decalsequence = decalsequence;
10639         decal->color4f[0][0] = c0[0];
10640         decal->color4f[0][1] = c0[1];
10641         decal->color4f[0][2] = c0[2];
10642         decal->color4f[0][3] = 1;
10643         decal->color4f[1][0] = c1[0];
10644         decal->color4f[1][1] = c1[1];
10645         decal->color4f[1][2] = c1[2];
10646         decal->color4f[1][3] = 1;
10647         decal->color4f[2][0] = c2[0];
10648         decal->color4f[2][1] = c2[1];
10649         decal->color4f[2][2] = c2[2];
10650         decal->color4f[2][3] = 1;
10651         decal->vertex3f[0][0] = v0[0];
10652         decal->vertex3f[0][1] = v0[1];
10653         decal->vertex3f[0][2] = v0[2];
10654         decal->vertex3f[1][0] = v1[0];
10655         decal->vertex3f[1][1] = v1[1];
10656         decal->vertex3f[1][2] = v1[2];
10657         decal->vertex3f[2][0] = v2[0];
10658         decal->vertex3f[2][1] = v2[1];
10659         decal->vertex3f[2][2] = v2[2];
10660         decal->texcoord2f[0][0] = t0[0];
10661         decal->texcoord2f[0][1] = t0[1];
10662         decal->texcoord2f[1][0] = t1[0];
10663         decal->texcoord2f[1][1] = t1[1];
10664         decal->texcoord2f[2][0] = t2[0];
10665         decal->texcoord2f[2][1] = t2[1];
10666         TriangleNormal(v0, v1, v2, decal->plane);
10667         VectorNormalize(decal->plane);
10668         decal->plane[3] = DotProduct(v0, decal->plane);
10669 }
10670
10671 extern cvar_t cl_decals_bias;
10672 extern cvar_t cl_decals_models;
10673 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10674 // baseparms, parms, temps
10675 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)
10676 {
10677         int cornerindex;
10678         int index;
10679         float v[9][3];
10680         const float *vertex3f;
10681         const float *normal3f;
10682         int numpoints;
10683         float points[2][9][3];
10684         float temp[3];
10685         float tc[9][2];
10686         float f;
10687         float c[9][4];
10688         const int *e;
10689
10690         e = rsurface.modelelement3i + 3*triangleindex;
10691
10692         vertex3f = rsurface.modelvertex3f;
10693         normal3f = rsurface.modelnormal3f;
10694
10695         if (normal3f)
10696         {
10697                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10698                 {
10699                         index = 3*e[cornerindex];
10700                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10701                 }
10702         }
10703         else
10704         {
10705                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10706                 {
10707                         index = 3*e[cornerindex];
10708                         VectorCopy(vertex3f + index, v[cornerindex]);
10709                 }
10710         }
10711
10712         // cull backfaces
10713         //TriangleNormal(v[0], v[1], v[2], normal);
10714         //if (DotProduct(normal, localnormal) < 0.0f)
10715         //      continue;
10716         // clip by each of the box planes formed from the projection matrix
10717         // if anything survives, we emit the decal
10718         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]);
10719         if (numpoints < 3)
10720                 return;
10721         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]);
10722         if (numpoints < 3)
10723                 return;
10724         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]);
10725         if (numpoints < 3)
10726                 return;
10727         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]);
10728         if (numpoints < 3)
10729                 return;
10730         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]);
10731         if (numpoints < 3)
10732                 return;
10733         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]);
10734         if (numpoints < 3)
10735                 return;
10736         // some part of the triangle survived, so we have to accept it...
10737         if (dynamic)
10738         {
10739                 // dynamic always uses the original triangle
10740                 numpoints = 3;
10741                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10742                 {
10743                         index = 3*e[cornerindex];
10744                         VectorCopy(vertex3f + index, v[cornerindex]);
10745                 }
10746         }
10747         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10748         {
10749                 // convert vertex positions to texcoords
10750                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10751                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10752                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10753                 // calculate distance fade from the projection origin
10754                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10755                 f = bound(0.0f, f, 1.0f);
10756                 c[cornerindex][0] = r * f;
10757                 c[cornerindex][1] = g * f;
10758                 c[cornerindex][2] = b * f;
10759                 c[cornerindex][3] = 1.0f;
10760                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10761         }
10762         if (dynamic)
10763                 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);
10764         else
10765                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10766                         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);
10767 }
10768 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)
10769 {
10770         matrix4x4_t projection;
10771         decalsystem_t *decalsystem;
10772         qboolean dynamic;
10773         dp_model_t *model;
10774         const msurface_t *surface;
10775         const msurface_t *surfaces;
10776         const int *surfacelist;
10777         const texture_t *texture;
10778         int numtriangles;
10779         int numsurfacelist;
10780         int surfacelistindex;
10781         int surfaceindex;
10782         int triangleindex;
10783         float localorigin[3];
10784         float localnormal[3];
10785         float localmins[3];
10786         float localmaxs[3];
10787         float localsize;
10788         //float normal[3];
10789         float planes[6][4];
10790         float angles[3];
10791         bih_t *bih;
10792         int bih_triangles_count;
10793         int bih_triangles[256];
10794         int bih_surfaces[256];
10795
10796         decalsystem = &ent->decalsystem;
10797         model = ent->model;
10798         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10799         {
10800                 R_DecalSystem_Reset(&ent->decalsystem);
10801                 return;
10802         }
10803
10804         if (!model->brush.data_leafs && !cl_decals_models.integer)
10805         {
10806                 if (decalsystem->model)
10807                         R_DecalSystem_Reset(decalsystem);
10808                 return;
10809         }
10810
10811         if (decalsystem->model != model)
10812                 R_DecalSystem_Reset(decalsystem);
10813         decalsystem->model = model;
10814
10815         RSurf_ActiveModelEntity(ent, true, false, false);
10816
10817         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10818         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10819         VectorNormalize(localnormal);
10820         localsize = worldsize*rsurface.inversematrixscale;
10821         localmins[0] = localorigin[0] - localsize;
10822         localmins[1] = localorigin[1] - localsize;
10823         localmins[2] = localorigin[2] - localsize;
10824         localmaxs[0] = localorigin[0] + localsize;
10825         localmaxs[1] = localorigin[1] + localsize;
10826         localmaxs[2] = localorigin[2] + localsize;
10827
10828         //VectorCopy(localnormal, planes[4]);
10829         //VectorVectors(planes[4], planes[2], planes[0]);
10830         AnglesFromVectors(angles, localnormal, NULL, false);
10831         AngleVectors(angles, planes[0], planes[2], planes[4]);
10832         VectorNegate(planes[0], planes[1]);
10833         VectorNegate(planes[2], planes[3]);
10834         VectorNegate(planes[4], planes[5]);
10835         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10836         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10837         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10838         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10839         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10840         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10841
10842 #if 1
10843 // works
10844 {
10845         matrix4x4_t forwardprojection;
10846         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10847         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10848 }
10849 #else
10850 // broken
10851 {
10852         float projectionvector[4][3];
10853         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10854         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10855         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10856         projectionvector[0][0] = planes[0][0] * ilocalsize;
10857         projectionvector[0][1] = planes[1][0] * ilocalsize;
10858         projectionvector[0][2] = planes[2][0] * ilocalsize;
10859         projectionvector[1][0] = planes[0][1] * ilocalsize;
10860         projectionvector[1][1] = planes[1][1] * ilocalsize;
10861         projectionvector[1][2] = planes[2][1] * ilocalsize;
10862         projectionvector[2][0] = planes[0][2] * ilocalsize;
10863         projectionvector[2][1] = planes[1][2] * ilocalsize;
10864         projectionvector[2][2] = planes[2][2] * ilocalsize;
10865         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10866         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10867         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10868         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10869 }
10870 #endif
10871
10872         dynamic = model->surfmesh.isanimated;
10873         numsurfacelist = model->nummodelsurfaces;
10874         surfacelist = model->sortedmodelsurfaces;
10875         surfaces = model->data_surfaces;
10876
10877         bih = NULL;
10878         bih_triangles_count = -1;
10879         if(!dynamic)
10880         {
10881                 if(model->render_bih.numleafs)
10882                         bih = &model->render_bih;
10883                 else if(model->collision_bih.numleafs)
10884                         bih = &model->collision_bih;
10885         }
10886         if(bih)
10887                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10888         if(bih_triangles_count == 0)
10889                 return;
10890         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10891                 return;
10892         if(bih_triangles_count > 0)
10893         {
10894                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10895                 {
10896                         surfaceindex = bih_surfaces[triangleindex];
10897                         surface = surfaces + surfaceindex;
10898                         texture = surface->texture;
10899                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10900                                 continue;
10901                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10902                                 continue;
10903                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10904                 }
10905         }
10906         else
10907         {
10908                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10909                 {
10910                         surfaceindex = surfacelist[surfacelistindex];
10911                         surface = surfaces + surfaceindex;
10912                         // check cull box first because it rejects more than any other check
10913                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10914                                 continue;
10915                         // skip transparent surfaces
10916                         texture = surface->texture;
10917                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10918                                 continue;
10919                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10920                                 continue;
10921                         numtriangles = surface->num_triangles;
10922                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10923                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10924                 }
10925         }
10926 }
10927
10928 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10929 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)
10930 {
10931         int renderentityindex;
10932         float worldmins[3];
10933         float worldmaxs[3];
10934         entity_render_t *ent;
10935
10936         if (!cl_decals_newsystem.integer)
10937                 return;
10938
10939         worldmins[0] = worldorigin[0] - worldsize;
10940         worldmins[1] = worldorigin[1] - worldsize;
10941         worldmins[2] = worldorigin[2] - worldsize;
10942         worldmaxs[0] = worldorigin[0] + worldsize;
10943         worldmaxs[1] = worldorigin[1] + worldsize;
10944         worldmaxs[2] = worldorigin[2] + worldsize;
10945
10946         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10947
10948         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10949         {
10950                 ent = r_refdef.scene.entities[renderentityindex];
10951                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10952                         continue;
10953
10954                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10955         }
10956 }
10957
10958 typedef struct r_decalsystem_splatqueue_s
10959 {
10960         vec3_t worldorigin;
10961         vec3_t worldnormal;
10962         float color[4];
10963         float tcrange[4];
10964         float worldsize;
10965         int decalsequence;
10966 }
10967 r_decalsystem_splatqueue_t;
10968
10969 int r_decalsystem_numqueued = 0;
10970 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10971
10972 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)
10973 {
10974         r_decalsystem_splatqueue_t *queue;
10975
10976         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10977                 return;
10978
10979         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10980         VectorCopy(worldorigin, queue->worldorigin);
10981         VectorCopy(worldnormal, queue->worldnormal);
10982         Vector4Set(queue->color, r, g, b, a);
10983         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10984         queue->worldsize = worldsize;
10985         queue->decalsequence = cl.decalsequence++;
10986 }
10987
10988 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10989 {
10990         int i;
10991         r_decalsystem_splatqueue_t *queue;
10992
10993         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10994                 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);
10995         r_decalsystem_numqueued = 0;
10996 }
10997
10998 extern cvar_t cl_decals_max;
10999 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11000 {
11001         int i;
11002         decalsystem_t *decalsystem = &ent->decalsystem;
11003         int numdecals;
11004         int killsequence;
11005         tridecal_t *decal;
11006         float frametime;
11007         float lifetime;
11008
11009         if (!decalsystem->numdecals)
11010                 return;
11011
11012         if (r_showsurfaces.integer)
11013                 return;
11014
11015         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11016         {
11017                 R_DecalSystem_Reset(decalsystem);
11018                 return;
11019         }
11020
11021         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11022         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11023
11024         if (decalsystem->lastupdatetime)
11025                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11026         else
11027                 frametime = 0;
11028         decalsystem->lastupdatetime = r_refdef.scene.time;
11029         decal = decalsystem->decals;
11030         numdecals = decalsystem->numdecals;
11031
11032         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11033         {
11034                 if (decal->color4f[0][3])
11035                 {
11036                         decal->lived += frametime;
11037                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11038                         {
11039                                 memset(decal, 0, sizeof(*decal));
11040                                 if (decalsystem->freedecal > i)
11041                                         decalsystem->freedecal = i;
11042                         }
11043                 }
11044         }
11045         decal = decalsystem->decals;
11046         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11047                 numdecals--;
11048
11049         // collapse the array by shuffling the tail decals into the gaps
11050         for (;;)
11051         {
11052                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11053                         decalsystem->freedecal++;
11054                 if (decalsystem->freedecal == numdecals)
11055                         break;
11056                 decal[decalsystem->freedecal] = decal[--numdecals];
11057         }
11058
11059         decalsystem->numdecals = numdecals;
11060
11061         if (numdecals <= 0)
11062         {
11063                 // if there are no decals left, reset decalsystem
11064                 R_DecalSystem_Reset(decalsystem);
11065         }
11066 }
11067
11068 extern skinframe_t *decalskinframe;
11069 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11070 {
11071         int i;
11072         decalsystem_t *decalsystem = &ent->decalsystem;
11073         int numdecals;
11074         tridecal_t *decal;
11075         float faderate;
11076         float alpha;
11077         float *v3f;
11078         float *c4f;
11079         float *t2f;
11080         const int *e;
11081         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11082         int numtris = 0;
11083
11084         numdecals = decalsystem->numdecals;
11085         if (!numdecals)
11086                 return;
11087
11088         if (r_showsurfaces.integer)
11089                 return;
11090
11091         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11092         {
11093                 R_DecalSystem_Reset(decalsystem);
11094                 return;
11095         }
11096
11097         // if the model is static it doesn't matter what value we give for
11098         // wantnormals and wanttangents, so this logic uses only rules applicable
11099         // to a model, knowing that they are meaningless otherwise
11100         if (ent == r_refdef.scene.worldentity)
11101                 RSurf_ActiveWorldEntity();
11102         else
11103                 RSurf_ActiveModelEntity(ent, false, false, false);
11104
11105         decalsystem->lastupdatetime = r_refdef.scene.time;
11106         decal = decalsystem->decals;
11107
11108         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11109
11110         // update vertex positions for animated models
11111         v3f = decalsystem->vertex3f;
11112         c4f = decalsystem->color4f;
11113         t2f = decalsystem->texcoord2f;
11114         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11115         {
11116                 if (!decal->color4f[0][3])
11117                         continue;
11118
11119                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11120                         continue;
11121
11122                 // skip backfaces
11123                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11124                         continue;
11125
11126                 // update color values for fading decals
11127                 if (decal->lived >= cl_decals_time.value)
11128                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11129                 else
11130                         alpha = 1.0f;
11131
11132                 c4f[ 0] = decal->color4f[0][0] * alpha;
11133                 c4f[ 1] = decal->color4f[0][1] * alpha;
11134                 c4f[ 2] = decal->color4f[0][2] * alpha;
11135                 c4f[ 3] = 1;
11136                 c4f[ 4] = decal->color4f[1][0] * alpha;
11137                 c4f[ 5] = decal->color4f[1][1] * alpha;
11138                 c4f[ 6] = decal->color4f[1][2] * alpha;
11139                 c4f[ 7] = 1;
11140                 c4f[ 8] = decal->color4f[2][0] * alpha;
11141                 c4f[ 9] = decal->color4f[2][1] * alpha;
11142                 c4f[10] = decal->color4f[2][2] * alpha;
11143                 c4f[11] = 1;
11144
11145                 t2f[0] = decal->texcoord2f[0][0];
11146                 t2f[1] = decal->texcoord2f[0][1];
11147                 t2f[2] = decal->texcoord2f[1][0];
11148                 t2f[3] = decal->texcoord2f[1][1];
11149                 t2f[4] = decal->texcoord2f[2][0];
11150                 t2f[5] = decal->texcoord2f[2][1];
11151
11152                 // update vertex positions for animated models
11153                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11154                 {
11155                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11156                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11157                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11158                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11159                 }
11160                 else
11161                 {
11162                         VectorCopy(decal->vertex3f[0], v3f);
11163                         VectorCopy(decal->vertex3f[1], v3f + 3);
11164                         VectorCopy(decal->vertex3f[2], v3f + 6);
11165                 }
11166
11167                 if (r_refdef.fogenabled)
11168                 {
11169                         alpha = RSurf_FogVertex(v3f);
11170                         VectorScale(c4f, alpha, c4f);
11171                         alpha = RSurf_FogVertex(v3f + 3);
11172                         VectorScale(c4f + 4, alpha, c4f + 4);
11173                         alpha = RSurf_FogVertex(v3f + 6);
11174                         VectorScale(c4f + 8, alpha, c4f + 8);
11175                 }
11176
11177                 v3f += 9;
11178                 c4f += 12;
11179                 t2f += 6;
11180                 numtris++;
11181         }
11182
11183         if (numtris > 0)
11184         {
11185                 r_refdef.stats.drawndecals += numtris;
11186
11187                 // now render the decals all at once
11188                 // (this assumes they all use one particle font texture!)
11189                 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);
11190 //              R_Mesh_ResetTextureState();
11191                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11192                 GL_DepthMask(false);
11193                 GL_DepthRange(0, 1);
11194                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11195                 GL_DepthTest(true);
11196                 GL_CullFace(GL_NONE);
11197                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11198                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11199                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11200         }
11201 }
11202
11203 static void R_DrawModelDecals(void)
11204 {
11205         int i, numdecals;
11206
11207         // fade faster when there are too many decals
11208         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11209         for (i = 0;i < r_refdef.scene.numentities;i++)
11210                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11211
11212         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11213         for (i = 0;i < r_refdef.scene.numentities;i++)
11214                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11215                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11216
11217         R_DecalSystem_ApplySplatEntitiesQueue();
11218
11219         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11220         for (i = 0;i < r_refdef.scene.numentities;i++)
11221                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11222
11223         r_refdef.stats.totaldecals += numdecals;
11224
11225         if (r_showsurfaces.integer)
11226                 return;
11227
11228         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11229
11230         for (i = 0;i < r_refdef.scene.numentities;i++)
11231         {
11232                 if (!r_refdef.viewcache.entityvisible[i])
11233                         continue;
11234                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11235                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11236         }
11237 }
11238
11239 extern cvar_t mod_collision_bih;
11240 void R_DrawDebugModel(void)
11241 {
11242         entity_render_t *ent = rsurface.entity;
11243         int i, j, k, l, flagsmask;
11244         const msurface_t *surface;
11245         dp_model_t *model = ent->model;
11246         vec3_t v;
11247
11248         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11249                 return;
11250
11251         if (r_showoverdraw.value > 0)
11252         {
11253                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11254                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11255                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11256                 GL_DepthTest(false);
11257                 GL_DepthMask(false);
11258                 GL_DepthRange(0, 1);
11259                 GL_BlendFunc(GL_ONE, GL_ONE);
11260                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11261                 {
11262                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11263                                 continue;
11264                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11265                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11266                         {
11267                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11268                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11269                                 if (!rsurface.texture->currentlayers->depthmask)
11270                                         GL_Color(c, 0, 0, 1.0f);
11271                                 else if (ent == r_refdef.scene.worldentity)
11272                                         GL_Color(c, c, c, 1.0f);
11273                                 else
11274                                         GL_Color(0, c, 0, 1.0f);
11275                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11276                                 RSurf_DrawBatch();
11277                         }
11278                 }
11279                 rsurface.texture = NULL;
11280         }
11281
11282         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11283
11284 //      R_Mesh_ResetTextureState();
11285         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11286         GL_DepthRange(0, 1);
11287         GL_DepthTest(!r_showdisabledepthtest.integer);
11288         GL_DepthMask(false);
11289         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11290
11291         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11292         {
11293                 int triangleindex;
11294                 int bihleafindex;
11295                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11296                 const q3mbrush_t *brush;
11297                 const bih_t *bih = &model->collision_bih;
11298                 const bih_leaf_t *bihleaf;
11299                 float vertex3f[3][3];
11300                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11301                 cullbox = false;
11302                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11303                 {
11304                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11305                                 continue;
11306                         switch (bihleaf->type)
11307                         {
11308                         case BIH_BRUSH:
11309                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11310                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11311                                 {
11312                                         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);
11313                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11314                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11315                                 }
11316                                 break;
11317                         case BIH_COLLISIONTRIANGLE:
11318                                 triangleindex = bihleaf->itemindex;
11319                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11320                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11321                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11322                                 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);
11323                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11324                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11325                                 break;
11326                         case BIH_RENDERTRIANGLE:
11327                                 triangleindex = bihleaf->itemindex;
11328                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11329                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11330                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11331                                 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);
11332                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11333                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11334                                 break;
11335                         }
11336                 }
11337         }
11338
11339         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11340
11341         if (r_showtris.integer && qglPolygonMode)
11342         {
11343                 if (r_showdisabledepthtest.integer)
11344                 {
11345                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11346                         GL_DepthMask(false);
11347                 }
11348                 else
11349                 {
11350                         GL_BlendFunc(GL_ONE, GL_ZERO);
11351                         GL_DepthMask(true);
11352                 }
11353                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11354                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11355                 {
11356                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11357                                 continue;
11358                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11359                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11360                         {
11361                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11362                                 if (!rsurface.texture->currentlayers->depthmask)
11363                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11364                                 else if (ent == r_refdef.scene.worldentity)
11365                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11366                                 else
11367                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11368                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11369                                 RSurf_DrawBatch();
11370                         }
11371                 }
11372                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11373                 rsurface.texture = NULL;
11374         }
11375
11376         if (r_shownormals.value != 0 && qglBegin)
11377         {
11378                 if (r_showdisabledepthtest.integer)
11379                 {
11380                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11381                         GL_DepthMask(false);
11382                 }
11383                 else
11384                 {
11385                         GL_BlendFunc(GL_ONE, GL_ZERO);
11386                         GL_DepthMask(true);
11387                 }
11388                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11389                 {
11390                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11391                                 continue;
11392                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11393                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11394                         {
11395                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11396                                 qglBegin(GL_LINES);
11397                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11398                                 {
11399                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11400                                         {
11401                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11402                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11403                                                 qglVertex3f(v[0], v[1], v[2]);
11404                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11405                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11406                                                 qglVertex3f(v[0], v[1], v[2]);
11407                                         }
11408                                 }
11409                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11410                                 {
11411                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11412                                         {
11413                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11414                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11415                                                 qglVertex3f(v[0], v[1], v[2]);
11416                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11417                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11418                                                 qglVertex3f(v[0], v[1], v[2]);
11419                                         }
11420                                 }
11421                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11422                                 {
11423                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11424                                         {
11425                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11426                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11427                                                 qglVertex3f(v[0], v[1], v[2]);
11428                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11429                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11430                                                 qglVertex3f(v[0], v[1], v[2]);
11431                                         }
11432                                 }
11433                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11434                                 {
11435                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11436                                         {
11437                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11438                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11439                                                 qglVertex3f(v[0], v[1], v[2]);
11440                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11441                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11442                                                 qglVertex3f(v[0], v[1], v[2]);
11443                                         }
11444                                 }
11445                                 qglEnd();
11446                                 CHECKGLERROR
11447                         }
11448                 }
11449                 rsurface.texture = NULL;
11450         }
11451 }
11452
11453 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11454 int r_maxsurfacelist = 0;
11455 const msurface_t **r_surfacelist = NULL;
11456 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11457 {
11458         int i, j, endj, flagsmask;
11459         dp_model_t *model = r_refdef.scene.worldmodel;
11460         msurface_t *surfaces;
11461         unsigned char *update;
11462         int numsurfacelist = 0;
11463         if (model == NULL)
11464                 return;
11465
11466         if (r_maxsurfacelist < model->num_surfaces)
11467         {
11468                 r_maxsurfacelist = model->num_surfaces;
11469                 if (r_surfacelist)
11470                         Mem_Free((msurface_t**)r_surfacelist);
11471                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11472         }
11473
11474         RSurf_ActiveWorldEntity();
11475
11476         surfaces = model->data_surfaces;
11477         update = model->brushq1.lightmapupdateflags;
11478
11479         // update light styles on this submodel
11480         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11481         {
11482                 model_brush_lightstyleinfo_t *style;
11483                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11484                 {
11485                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11486                         {
11487                                 int *list = style->surfacelist;
11488                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11489                                 for (j = 0;j < style->numsurfaces;j++)
11490                                         update[list[j]] = true;
11491                         }
11492                 }
11493         }
11494
11495         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11496
11497         if (debug)
11498         {
11499                 R_DrawDebugModel();
11500                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11501                 return;
11502         }
11503
11504         rsurface.lightmaptexture = NULL;
11505         rsurface.deluxemaptexture = NULL;
11506         rsurface.uselightmaptexture = false;
11507         rsurface.texture = NULL;
11508         rsurface.rtlight = NULL;
11509         numsurfacelist = 0;
11510         // add visible surfaces to draw list
11511         for (i = 0;i < model->nummodelsurfaces;i++)
11512         {
11513                 j = model->sortedmodelsurfaces[i];
11514                 if (r_refdef.viewcache.world_surfacevisible[j])
11515                         r_surfacelist[numsurfacelist++] = surfaces + j;
11516         }
11517         // update lightmaps if needed
11518         if (model->brushq1.firstrender)
11519         {
11520                 model->brushq1.firstrender = false;
11521                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11522                         if (update[j])
11523                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11524         }
11525         else if (update)
11526         {
11527                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11528                         if (r_refdef.viewcache.world_surfacevisible[j])
11529                                 if (update[j])
11530                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11531         }
11532         // don't do anything if there were no surfaces
11533         if (!numsurfacelist)
11534         {
11535                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11536                 return;
11537         }
11538         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11539
11540         // add to stats if desired
11541         if (r_speeds.integer && !skysurfaces && !depthonly)
11542         {
11543                 r_refdef.stats.world_surfaces += numsurfacelist;
11544                 for (j = 0;j < numsurfacelist;j++)
11545                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11546         }
11547
11548         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11549 }
11550
11551 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11552 {
11553         int i, j, endj, flagsmask;
11554         dp_model_t *model = ent->model;
11555         msurface_t *surfaces;
11556         unsigned char *update;
11557         int numsurfacelist = 0;
11558         if (model == NULL)
11559                 return;
11560
11561         if (r_maxsurfacelist < model->num_surfaces)
11562         {
11563                 r_maxsurfacelist = model->num_surfaces;
11564                 if (r_surfacelist)
11565                         Mem_Free((msurface_t **)r_surfacelist);
11566                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11567         }
11568
11569         // if the model is static it doesn't matter what value we give for
11570         // wantnormals and wanttangents, so this logic uses only rules applicable
11571         // to a model, knowing that they are meaningless otherwise
11572         if (ent == r_refdef.scene.worldentity)
11573                 RSurf_ActiveWorldEntity();
11574         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11575                 RSurf_ActiveModelEntity(ent, false, false, false);
11576         else if (prepass)
11577                 RSurf_ActiveModelEntity(ent, true, true, true);
11578         else if (depthonly)
11579         {
11580                 switch (vid.renderpath)
11581                 {
11582                 case RENDERPATH_GL20:
11583                 case RENDERPATH_D3D9:
11584                 case RENDERPATH_D3D10:
11585                 case RENDERPATH_D3D11:
11586                 case RENDERPATH_SOFT:
11587                 case RENDERPATH_GLES2:
11588                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11589                         break;
11590                 case RENDERPATH_GL11:
11591                 case RENDERPATH_GL13:
11592                 case RENDERPATH_GLES1:
11593                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11594                         break;
11595                 }
11596         }
11597         else
11598         {
11599                 switch (vid.renderpath)
11600                 {
11601                 case RENDERPATH_GL20:
11602                 case RENDERPATH_D3D9:
11603                 case RENDERPATH_D3D10:
11604                 case RENDERPATH_D3D11:
11605                 case RENDERPATH_SOFT:
11606                 case RENDERPATH_GLES2:
11607                         RSurf_ActiveModelEntity(ent, true, true, false);
11608                         break;
11609                 case RENDERPATH_GL11:
11610                 case RENDERPATH_GL13:
11611                 case RENDERPATH_GLES1:
11612                         RSurf_ActiveModelEntity(ent, true, false, false);
11613                         break;
11614                 }
11615         }
11616
11617         surfaces = model->data_surfaces;
11618         update = model->brushq1.lightmapupdateflags;
11619
11620         // update light styles
11621         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11622         {
11623                 model_brush_lightstyleinfo_t *style;
11624                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11625                 {
11626                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11627                         {
11628                                 int *list = style->surfacelist;
11629                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11630                                 for (j = 0;j < style->numsurfaces;j++)
11631                                         update[list[j]] = true;
11632                         }
11633                 }
11634         }
11635
11636         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11637
11638         if (debug)
11639         {
11640                 R_DrawDebugModel();
11641                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11642                 return;
11643         }
11644
11645         rsurface.lightmaptexture = NULL;
11646         rsurface.deluxemaptexture = NULL;
11647         rsurface.uselightmaptexture = false;
11648         rsurface.texture = NULL;
11649         rsurface.rtlight = NULL;
11650         numsurfacelist = 0;
11651         // add visible surfaces to draw list
11652         for (i = 0;i < model->nummodelsurfaces;i++)
11653                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11654         // don't do anything if there were no surfaces
11655         if (!numsurfacelist)
11656         {
11657                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11658                 return;
11659         }
11660         // update lightmaps if needed
11661         if (update)
11662         {
11663                 int updated = 0;
11664                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11665                 {
11666                         if (update[j])
11667                         {
11668                                 updated++;
11669                                 R_BuildLightMap(ent, surfaces + j);
11670                         }
11671                 }
11672         }
11673         if (update)
11674                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11675                         if (update[j])
11676                                 R_BuildLightMap(ent, surfaces + j);
11677         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11678
11679         // add to stats if desired
11680         if (r_speeds.integer && !skysurfaces && !depthonly)
11681         {
11682                 r_refdef.stats.entities_surfaces += numsurfacelist;
11683                 for (j = 0;j < numsurfacelist;j++)
11684                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11685         }
11686
11687         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11688 }
11689
11690 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11691 {
11692         static texture_t texture;
11693         static msurface_t surface;
11694         const msurface_t *surfacelist = &surface;
11695
11696         // fake enough texture and surface state to render this geometry
11697
11698         texture.update_lastrenderframe = -1; // regenerate this texture
11699         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11700         texture.currentskinframe = skinframe;
11701         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11702         texture.offsetmapping = OFFSETMAPPING_OFF;
11703         texture.offsetscale = 1;
11704         texture.specularscalemod = 1;
11705         texture.specularpowermod = 1;
11706
11707         surface.texture = &texture;
11708         surface.num_triangles = numtriangles;
11709         surface.num_firsttriangle = firsttriangle;
11710         surface.num_vertices = numvertices;
11711         surface.num_firstvertex = firstvertex;
11712
11713         // now render it
11714         rsurface.texture = R_GetCurrentTexture(surface.texture);
11715         rsurface.lightmaptexture = NULL;
11716         rsurface.deluxemaptexture = NULL;
11717         rsurface.uselightmaptexture = false;
11718         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11719 }
11720
11721 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)
11722 {
11723         static msurface_t surface;
11724         const msurface_t *surfacelist = &surface;
11725
11726         // fake enough texture and surface state to render this geometry
11727         surface.texture = texture;
11728         surface.num_triangles = numtriangles;
11729         surface.num_firsttriangle = firsttriangle;
11730         surface.num_vertices = numvertices;
11731         surface.num_firstvertex = firstvertex;
11732
11733         // now render it
11734         rsurface.texture = R_GetCurrentTexture(surface.texture);
11735         rsurface.lightmaptexture = NULL;
11736         rsurface.deluxemaptexture = NULL;
11737         rsurface.uselightmaptexture = false;
11738         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11739 }