]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
eb83eac79d6373ea2cd3a39f5c06c9a2459339c0
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
86 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
89 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
90 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
99 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
103 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
104
105 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
106 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
107 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
108
109 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
110 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
111 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
112 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
113 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
114 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
115 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
116 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
117 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
118 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
119 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
120 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
121 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
122 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
123 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
124 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
126 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
127 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
128 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
129 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
130 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
131
132 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
133 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
134 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
135 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
136 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
137 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
138 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
139 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
140
141 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
142 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
143
144 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
145 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
146 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
147
148 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
149 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
150 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
151 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
152 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
153 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
154 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
155 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
156
157 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
158 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
159 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
160 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
161 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
162 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
163 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
164 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
165 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
166 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
167 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
168 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
169 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
170 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
171 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
172 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
173
174 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
175 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
176 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
177 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
178 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
179 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
180 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
181
182 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
183 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
184 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
185 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
186
187 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
188 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
189 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
190 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
191 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
192 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
193 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
194
195 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
196 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
197 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
198 cvar_t r_hdr_range = {CVAR_SAVE, "r_hdr_range", "4", "how much dynamic range to render bloom with (equivalent to multiplying r_bloom_brighten by this value and dividing r_bloom_colorscale by this value)"};
199 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
200 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
201 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
202 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
203 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
204 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
205 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
206
207 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
208
209 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
210
211 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
212
213 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
214
215 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
216 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
217
218 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer."};
219
220 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
221
222 extern cvar_t v_glslgamma;
223
224 extern qboolean v_flipped_state;
225
226 static struct r_bloomstate_s
227 {
228         qboolean enabled;
229         qboolean hdr;
230
231         int bloomwidth, bloomheight;
232
233         textype_t texturetype;
234         int viewfbo; // used to check if r_viewfbo cvar has changed
235
236         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
237         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
238         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
239
240         int screentexturewidth, screentextureheight;
241         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
242
243         int bloomtexturewidth, bloomtextureheight;
244         rtexture_t *texture_bloom;
245
246         // arrays for rendering the screen passes
247         float screentexcoord2f[8];
248         float bloomtexcoord2f[8];
249         float offsettexcoord2f[8];
250
251         r_viewport_t viewport;
252 }
253 r_bloomstate;
254
255 r_waterstate_t r_waterstate;
256
257 /// shadow volume bsp struct with automatically growing nodes buffer
258 svbsp_t r_svbsp;
259
260 rtexture_t *r_texture_blanknormalmap;
261 rtexture_t *r_texture_white;
262 rtexture_t *r_texture_grey128;
263 rtexture_t *r_texture_black;
264 rtexture_t *r_texture_notexture;
265 rtexture_t *r_texture_whitecube;
266 rtexture_t *r_texture_normalizationcube;
267 rtexture_t *r_texture_fogattenuation;
268 rtexture_t *r_texture_fogheighttexture;
269 rtexture_t *r_texture_gammaramps;
270 unsigned int r_texture_gammaramps_serial;
271 //rtexture_t *r_texture_fogintensity;
272 rtexture_t *r_texture_reflectcube;
273
274 // TODO: hash lookups?
275 typedef struct cubemapinfo_s
276 {
277         char basename[64];
278         rtexture_t *texture;
279 }
280 cubemapinfo_t;
281
282 int r_texture_numcubemaps;
283 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
284
285 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
286 unsigned int r_numqueries;
287 unsigned int r_maxqueries;
288
289 typedef struct r_qwskincache_s
290 {
291         char name[MAX_QPATH];
292         skinframe_t *skinframe;
293 }
294 r_qwskincache_t;
295
296 static r_qwskincache_t *r_qwskincache;
297 static int r_qwskincache_size;
298
299 /// vertex coordinates for a quad that covers the screen exactly
300 extern const float r_screenvertex3f[12];
301 extern const float r_d3dscreenvertex3f[12];
302 const float r_screenvertex3f[12] =
303 {
304         0, 0, 0,
305         1, 0, 0,
306         1, 1, 0,
307         0, 1, 0
308 };
309 const float r_d3dscreenvertex3f[12] =
310 {
311         0, 1, 0,
312         1, 1, 0,
313         1, 0, 0,
314         0, 0, 0
315 };
316
317 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
318 {
319         int i;
320         for (i = 0;i < verts;i++)
321         {
322                 out[0] = in[0] * r;
323                 out[1] = in[1] * g;
324                 out[2] = in[2] * b;
325                 out[3] = in[3];
326                 in += 4;
327                 out += 4;
328         }
329 }
330
331 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
332 {
333         int i;
334         for (i = 0;i < verts;i++)
335         {
336                 out[0] = r;
337                 out[1] = g;
338                 out[2] = b;
339                 out[3] = a;
340                 out += 4;
341         }
342 }
343
344 // FIXME: move this to client?
345 void FOG_clear(void)
346 {
347         if (gamemode == GAME_NEHAHRA)
348         {
349                 Cvar_Set("gl_fogenable", "0");
350                 Cvar_Set("gl_fogdensity", "0.2");
351                 Cvar_Set("gl_fogred", "0.3");
352                 Cvar_Set("gl_foggreen", "0.3");
353                 Cvar_Set("gl_fogblue", "0.3");
354         }
355         r_refdef.fog_density = 0;
356         r_refdef.fog_red = 0;
357         r_refdef.fog_green = 0;
358         r_refdef.fog_blue = 0;
359         r_refdef.fog_alpha = 1;
360         r_refdef.fog_start = 0;
361         r_refdef.fog_end = 16384;
362         r_refdef.fog_height = 1<<30;
363         r_refdef.fog_fadedepth = 128;
364         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
365 }
366
367 static void R_BuildBlankTextures(void)
368 {
369         unsigned char data[4];
370         data[2] = 128; // normal X
371         data[1] = 128; // normal Y
372         data[0] = 255; // normal Z
373         data[3] = 128; // height
374         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
375         data[0] = 255;
376         data[1] = 255;
377         data[2] = 255;
378         data[3] = 255;
379         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
380         data[0] = 128;
381         data[1] = 128;
382         data[2] = 128;
383         data[3] = 255;
384         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
385         data[0] = 0;
386         data[1] = 0;
387         data[2] = 0;
388         data[3] = 255;
389         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
390 }
391
392 static void R_BuildNoTexture(void)
393 {
394         int x, y;
395         unsigned char pix[16][16][4];
396         // this makes a light grey/dark grey checkerboard texture
397         for (y = 0;y < 16;y++)
398         {
399                 for (x = 0;x < 16;x++)
400                 {
401                         if ((y < 8) ^ (x < 8))
402                         {
403                                 pix[y][x][0] = 128;
404                                 pix[y][x][1] = 128;
405                                 pix[y][x][2] = 128;
406                                 pix[y][x][3] = 255;
407                         }
408                         else
409                         {
410                                 pix[y][x][0] = 64;
411                                 pix[y][x][1] = 64;
412                                 pix[y][x][2] = 64;
413                                 pix[y][x][3] = 255;
414                         }
415                 }
416         }
417         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
418 }
419
420 static void R_BuildWhiteCube(void)
421 {
422         unsigned char data[6*1*1*4];
423         memset(data, 255, sizeof(data));
424         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
425 }
426
427 static void R_BuildNormalizationCube(void)
428 {
429         int x, y, side;
430         vec3_t v;
431         vec_t s, t, intensity;
432 #define NORMSIZE 64
433         unsigned char *data;
434         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
435         for (side = 0;side < 6;side++)
436         {
437                 for (y = 0;y < NORMSIZE;y++)
438                 {
439                         for (x = 0;x < NORMSIZE;x++)
440                         {
441                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
442                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 switch(side)
444                                 {
445                                 default:
446                                 case 0:
447                                         v[0] = 1;
448                                         v[1] = -t;
449                                         v[2] = -s;
450                                         break;
451                                 case 1:
452                                         v[0] = -1;
453                                         v[1] = -t;
454                                         v[2] = s;
455                                         break;
456                                 case 2:
457                                         v[0] = s;
458                                         v[1] = 1;
459                                         v[2] = t;
460                                         break;
461                                 case 3:
462                                         v[0] = s;
463                                         v[1] = -1;
464                                         v[2] = -t;
465                                         break;
466                                 case 4:
467                                         v[0] = s;
468                                         v[1] = -t;
469                                         v[2] = 1;
470                                         break;
471                                 case 5:
472                                         v[0] = -s;
473                                         v[1] = -t;
474                                         v[2] = -1;
475                                         break;
476                                 }
477                                 intensity = 127.0f / sqrt(DotProduct(v, v));
478                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
479                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
480                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
481                                 data[((side*64+y)*64+x)*4+3] = 255;
482                         }
483                 }
484         }
485         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
486         Mem_Free(data);
487 }
488
489 static void R_BuildFogTexture(void)
490 {
491         int x, b;
492 #define FOGWIDTH 256
493         unsigned char data1[FOGWIDTH][4];
494         //unsigned char data2[FOGWIDTH][4];
495         double d, r, alpha;
496
497         r_refdef.fogmasktable_start = r_refdef.fog_start;
498         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
499         r_refdef.fogmasktable_range = r_refdef.fogrange;
500         r_refdef.fogmasktable_density = r_refdef.fog_density;
501
502         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
503         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
504         {
505                 d = (x * r - r_refdef.fogmasktable_start);
506                 if(developer_extra.integer)
507                         Con_DPrintf("%f ", d);
508                 d = max(0, d);
509                 if (r_fog_exp2.integer)
510                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
511                 else
512                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
513                 if(developer_extra.integer)
514                         Con_DPrintf(" : %f ", alpha);
515                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
516                 if(developer_extra.integer)
517                         Con_DPrintf(" = %f\n", alpha);
518                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
519         }
520
521         for (x = 0;x < FOGWIDTH;x++)
522         {
523                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
524                 data1[x][0] = b;
525                 data1[x][1] = b;
526                 data1[x][2] = b;
527                 data1[x][3] = 255;
528                 //data2[x][0] = 255 - b;
529                 //data2[x][1] = 255 - b;
530                 //data2[x][2] = 255 - b;
531                 //data2[x][3] = 255;
532         }
533         if (r_texture_fogattenuation)
534         {
535                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
536                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537         }
538         else
539         {
540                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
541                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
542         }
543 }
544
545 static void R_BuildFogHeightTexture(void)
546 {
547         unsigned char *inpixels;
548         int size;
549         int x;
550         int y;
551         int j;
552         float c[4];
553         float f;
554         inpixels = NULL;
555         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
556         if (r_refdef.fogheighttexturename[0])
557                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
558         if (!inpixels)
559         {
560                 r_refdef.fog_height_tablesize = 0;
561                 if (r_texture_fogheighttexture)
562                         R_FreeTexture(r_texture_fogheighttexture);
563                 r_texture_fogheighttexture = NULL;
564                 if (r_refdef.fog_height_table2d)
565                         Mem_Free(r_refdef.fog_height_table2d);
566                 r_refdef.fog_height_table2d = NULL;
567                 if (r_refdef.fog_height_table1d)
568                         Mem_Free(r_refdef.fog_height_table1d);
569                 r_refdef.fog_height_table1d = NULL;
570                 return;
571         }
572         size = image_width;
573         r_refdef.fog_height_tablesize = size;
574         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
575         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
576         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
577         Mem_Free(inpixels);
578         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
579         // average fog color table accounting for every fog layer between a point
580         // and the camera.  (Note: attenuation is handled separately!)
581         for (y = 0;y < size;y++)
582         {
583                 for (x = 0;x < size;x++)
584                 {
585                         Vector4Clear(c);
586                         f = 0;
587                         if (x < y)
588                         {
589                                 for (j = x;j <= y;j++)
590                                 {
591                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
592                                         f++;
593                                 }
594                         }
595                         else
596                         {
597                                 for (j = x;j >= y;j--)
598                                 {
599                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
600                                         f++;
601                                 }
602                         }
603                         f = 1.0f / f;
604                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
605                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
608                 }
609         }
610         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
611 }
612
613 //=======================================================================================================================================================
614
615 static const char *builtinshaderstring =
616 #include "shader_glsl.h"
617 ;
618
619 const char *builtinhlslshaderstring =
620 #include "shader_hlsl.h"
621 ;
622
623 char *glslshaderstring = NULL;
624 char *hlslshaderstring = NULL;
625
626 //=======================================================================================================================================================
627
628 typedef struct shaderpermutationinfo_s
629 {
630         const char *pretext;
631         const char *name;
632 }
633 shaderpermutationinfo_t;
634
635 typedef struct shadermodeinfo_s
636 {
637         const char *vertexfilename;
638         const char *geometryfilename;
639         const char *fragmentfilename;
640         const char *pretext;
641         const char *name;
642 }
643 shadermodeinfo_t;
644
645 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
646 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
647 {
648         {"#define USEDIFFUSE\n", " diffuse"},
649         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
650         {"#define USEVIEWTINT\n", " viewtint"},
651         {"#define USECOLORMAPPING\n", " colormapping"},
652         {"#define USESATURATION\n", " saturation"},
653         {"#define USEFOGINSIDE\n", " foginside"},
654         {"#define USEFOGOUTSIDE\n", " fogoutside"},
655         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
656         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
657         {"#define USEGAMMARAMPS\n", " gammaramps"},
658         {"#define USECUBEFILTER\n", " cubefilter"},
659         {"#define USEGLOW\n", " glow"},
660         {"#define USEBLOOM\n", " bloom"},
661         {"#define USESPECULAR\n", " specular"},
662         {"#define USEPOSTPROCESSING\n", " postprocessing"},
663         {"#define USEREFLECTION\n", " reflection"},
664         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
665         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
666         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
667         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
668         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
669         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
670         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
671         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673         {"#define USEALPHAKILL\n", " alphakill"},
674         {"#define USEREFLECTCUBE\n", " reflectcube"},
675         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676         {"#define USEBOUNCEGRID\n", " bouncegrid"},
677         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
678         {"#define USETRIPPY\n", " trippy"},
679 };
680
681 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
682 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
683 {
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
686         {"glsl/default.glsl", NULL, NULL               , "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
700 };
701
702 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
703 {
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
720 };
721
722 struct r_glsl_permutation_s;
723 typedef struct r_glsl_permutation_s
724 {
725         /// hash lookup data
726         struct r_glsl_permutation_s *hashnext;
727         unsigned int mode;
728         unsigned int permutation;
729
730         /// indicates if we have tried compiling this permutation already
731         qboolean compiled;
732         /// 0 if compilation failed
733         int program;
734         // texture units assigned to each detected uniform
735         int tex_Texture_First;
736         int tex_Texture_Second;
737         int tex_Texture_GammaRamps;
738         int tex_Texture_Normal;
739         int tex_Texture_Color;
740         int tex_Texture_Gloss;
741         int tex_Texture_Glow;
742         int tex_Texture_SecondaryNormal;
743         int tex_Texture_SecondaryColor;
744         int tex_Texture_SecondaryGloss;
745         int tex_Texture_SecondaryGlow;
746         int tex_Texture_Pants;
747         int tex_Texture_Shirt;
748         int tex_Texture_FogHeightTexture;
749         int tex_Texture_FogMask;
750         int tex_Texture_Lightmap;
751         int tex_Texture_Deluxemap;
752         int tex_Texture_Attenuation;
753         int tex_Texture_Cube;
754         int tex_Texture_Refraction;
755         int tex_Texture_Reflection;
756         int tex_Texture_ShadowMap2D;
757         int tex_Texture_CubeProjection;
758         int tex_Texture_ScreenDepth;
759         int tex_Texture_ScreenNormalMap;
760         int tex_Texture_ScreenDiffuse;
761         int tex_Texture_ScreenSpecular;
762         int tex_Texture_ReflectMask;
763         int tex_Texture_ReflectCube;
764         int tex_Texture_BounceGrid;
765         /// locations of detected uniforms in program object, or -1 if not found
766         int loc_Texture_First;
767         int loc_Texture_Second;
768         int loc_Texture_GammaRamps;
769         int loc_Texture_Normal;
770         int loc_Texture_Color;
771         int loc_Texture_Gloss;
772         int loc_Texture_Glow;
773         int loc_Texture_SecondaryNormal;
774         int loc_Texture_SecondaryColor;
775         int loc_Texture_SecondaryGloss;
776         int loc_Texture_SecondaryGlow;
777         int loc_Texture_Pants;
778         int loc_Texture_Shirt;
779         int loc_Texture_FogHeightTexture;
780         int loc_Texture_FogMask;
781         int loc_Texture_Lightmap;
782         int loc_Texture_Deluxemap;
783         int loc_Texture_Attenuation;
784         int loc_Texture_Cube;
785         int loc_Texture_Refraction;
786         int loc_Texture_Reflection;
787         int loc_Texture_ShadowMap2D;
788         int loc_Texture_CubeProjection;
789         int loc_Texture_ScreenDepth;
790         int loc_Texture_ScreenNormalMap;
791         int loc_Texture_ScreenDiffuse;
792         int loc_Texture_ScreenSpecular;
793         int loc_Texture_ReflectMask;
794         int loc_Texture_ReflectCube;
795         int loc_Texture_BounceGrid;
796         int loc_Alpha;
797         int loc_BloomBlur_Parameters;
798         int loc_ClientTime;
799         int loc_Color_Ambient;
800         int loc_Color_Diffuse;
801         int loc_Color_Specular;
802         int loc_Color_Glow;
803         int loc_Color_Pants;
804         int loc_Color_Shirt;
805         int loc_DeferredColor_Ambient;
806         int loc_DeferredColor_Diffuse;
807         int loc_DeferredColor_Specular;
808         int loc_DeferredMod_Diffuse;
809         int loc_DeferredMod_Specular;
810         int loc_DistortScaleRefractReflect;
811         int loc_EyePosition;
812         int loc_FogColor;
813         int loc_FogHeightFade;
814         int loc_FogPlane;
815         int loc_FogPlaneViewDist;
816         int loc_FogRangeRecip;
817         int loc_LightColor;
818         int loc_LightDir;
819         int loc_LightPosition;
820         int loc_OffsetMapping_ScaleSteps;
821         int loc_PixelSize;
822         int loc_ReflectColor;
823         int loc_ReflectFactor;
824         int loc_ReflectOffset;
825         int loc_RefractColor;
826         int loc_Saturation;
827         int loc_ScreenCenterRefractReflect;
828         int loc_ScreenScaleRefractReflect;
829         int loc_ScreenToDepth;
830         int loc_ShadowMap_Parameters;
831         int loc_ShadowMap_TextureScale;
832         int loc_SpecularPower;
833         int loc_UserVec1;
834         int loc_UserVec2;
835         int loc_UserVec3;
836         int loc_UserVec4;
837         int loc_ViewTintColor;
838         int loc_ViewToLight;
839         int loc_ModelToLight;
840         int loc_TexMatrix;
841         int loc_BackgroundTexMatrix;
842         int loc_ModelViewProjectionMatrix;
843         int loc_ModelViewMatrix;
844         int loc_PixelToScreenTexCoord;
845         int loc_ModelToReflectCube;
846         int loc_ShadowMapMatrix;
847         int loc_BloomColorSubtract;
848         int loc_NormalmapScrollBlend;
849         int loc_BounceGridMatrix;
850         int loc_BounceGridIntensity;
851 }
852 r_glsl_permutation_t;
853
854 #define SHADERPERMUTATION_HASHSIZE 256
855
856
857 // non-degradable "lightweight" shader parameters to keep the permutations simpler
858 // these can NOT degrade! only use for simple stuff
859 enum
860 {
861         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
862         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
863         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
864         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
865         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
866         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
867         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
868 };
869 #define SHADERSTATICPARMS_COUNT 7
870
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
873
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876 qboolean R_CompileShader_CheckStaticParms(void)
877 {
878         static int r_compileshader_staticparms_save[1];
879         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
880         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
881
882         // detect all
883         if (r_glsl_saturation_redcompensate.integer)
884                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
885         if (r_glsl_vertextextureblend_usebothalphas.integer)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
887         if (r_shadow_glossexact.integer)
888                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
889         if (r_glsl_postprocess.integer)
890         {
891                 if (r_glsl_postprocess_uservec1_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
893                 if (r_glsl_postprocess_uservec2_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
895                 if (r_glsl_postprocess_uservec3_enable.integer)
896                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
897                 if (r_glsl_postprocess_uservec4_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
899         }
900         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
901 }
902
903 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
904         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
905                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
906         else \
907                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
908 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
909 {
910         shaderstaticparms_count = 0;
911
912         // emit all
913         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
920 }
921
922 /// information about each possible shader permutation
923 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
924 /// currently selected permutation
925 r_glsl_permutation_t *r_glsl_permutation;
926 /// storage for permutations linked in the hash table
927 memexpandablearray_t r_glsl_permutationarray;
928
929 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
930 {
931         //unsigned int hashdepth = 0;
932         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
933         r_glsl_permutation_t *p;
934         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
935         {
936                 if (p->mode == mode && p->permutation == permutation)
937                 {
938                         //if (hashdepth > 10)
939                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
940                         return p;
941                 }
942                 //hashdepth++;
943         }
944         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
945         p->mode = mode;
946         p->permutation = permutation;
947         p->hashnext = r_glsl_permutationhash[mode][hashindex];
948         r_glsl_permutationhash[mode][hashindex] = p;
949         //if (hashdepth > 10)
950         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
951         return p;
952 }
953
954 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
955 {
956         char *shaderstring;
957         if (!filename || !filename[0])
958                 return NULL;
959         if (!strcmp(filename, "glsl/default.glsl"))
960         {
961                 if (!glslshaderstring)
962                 {
963                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
964                         if (glslshaderstring)
965                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
966                         else
967                                 glslshaderstring = (char *)builtinshaderstring;
968                 }
969                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
970                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
971                 return shaderstring;
972         }
973         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
974         if (shaderstring)
975         {
976                 if (printfromdisknotice)
977                         Con_DPrintf("from disk %s... ", filename);
978                 return shaderstring;
979         }
980         return shaderstring;
981 }
982
983 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
984 {
985         int i;
986         int sampler;
987         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
988         char *vertexstring, *geometrystring, *fragmentstring;
989         char permutationname[256];
990         int vertstrings_count = 0;
991         int geomstrings_count = 0;
992         int fragstrings_count = 0;
993         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
994         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
995         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
996
997         if (p->compiled)
998                 return;
999         p->compiled = true;
1000         p->program = 0;
1001
1002         permutationname[0] = 0;
1003         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1004         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1005         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1006
1007         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1008
1009         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1010         if(vid.support.gl20shaders130)
1011         {
1012                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1013                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1014                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1015                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1016                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1017                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1018         }
1019
1020         // the first pretext is which type of shader to compile as
1021         // (later these will all be bound together as a program object)
1022         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1023         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1024         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1025
1026         // the second pretext is the mode (for example a light source)
1027         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1028         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1029         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1030         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1031
1032         // now add all the permutation pretexts
1033         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1034         {
1035                 if (permutation & (1<<i))
1036                 {
1037                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1038                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1039                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1040                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1041                 }
1042                 else
1043                 {
1044                         // keep line numbers correct
1045                         vertstrings_list[vertstrings_count++] = "\n";
1046                         geomstrings_list[geomstrings_count++] = "\n";
1047                         fragstrings_list[fragstrings_count++] = "\n";
1048                 }
1049         }
1050
1051         // add static parms
1052         R_CompileShader_AddStaticParms(mode, permutation);
1053         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1054         vertstrings_count += shaderstaticparms_count;
1055         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1056         geomstrings_count += shaderstaticparms_count;
1057         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1058         fragstrings_count += shaderstaticparms_count;
1059
1060         // now append the shader text itself
1061         vertstrings_list[vertstrings_count++] = vertexstring;
1062         geomstrings_list[geomstrings_count++] = geometrystring;
1063         fragstrings_list[fragstrings_count++] = fragmentstring;
1064
1065         // if any sources were NULL, clear the respective list
1066         if (!vertexstring)
1067                 vertstrings_count = 0;
1068         if (!geometrystring)
1069                 geomstrings_count = 0;
1070         if (!fragmentstring)
1071                 fragstrings_count = 0;
1072
1073         // compile the shader program
1074         if (vertstrings_count + geomstrings_count + fragstrings_count)
1075                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1076         if (p->program)
1077         {
1078                 CHECKGLERROR
1079                 qglUseProgram(p->program);CHECKGLERROR
1080                 // look up all the uniform variable names we care about, so we don't
1081                 // have to look them up every time we set them
1082
1083                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1084                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1085                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1086                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1087                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1088                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1089                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1090                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1091                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1092                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1093                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1094                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1095                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1096                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1097                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1098                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1099                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1100                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1101                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1102                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1103                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1104                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1105                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1106                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1107                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1108                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1109                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1110                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1111                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1112                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1113                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1114                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1115                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1116                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1117                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1118                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1119                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1120                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1121                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1122                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1123                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1124                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1125                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1126                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1127                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1128                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1129                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1130                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1131                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1132                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1133                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1134                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1135                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1136                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1137                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1138                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1139                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1140                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1141                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1142                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1143                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1144                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1145                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1146                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1147                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1148                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1149                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1150                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1151                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1152                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1153                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1154                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1155                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1156                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1157                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1158                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1159                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1160                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1161                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1162                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1163                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1164                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1165                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1166                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1167                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1168                 // initialize the samplers to refer to the texture units we use
1169                 p->tex_Texture_First = -1;
1170                 p->tex_Texture_Second = -1;
1171                 p->tex_Texture_GammaRamps = -1;
1172                 p->tex_Texture_Normal = -1;
1173                 p->tex_Texture_Color = -1;
1174                 p->tex_Texture_Gloss = -1;
1175                 p->tex_Texture_Glow = -1;
1176                 p->tex_Texture_SecondaryNormal = -1;
1177                 p->tex_Texture_SecondaryColor = -1;
1178                 p->tex_Texture_SecondaryGloss = -1;
1179                 p->tex_Texture_SecondaryGlow = -1;
1180                 p->tex_Texture_Pants = -1;
1181                 p->tex_Texture_Shirt = -1;
1182                 p->tex_Texture_FogHeightTexture = -1;
1183                 p->tex_Texture_FogMask = -1;
1184                 p->tex_Texture_Lightmap = -1;
1185                 p->tex_Texture_Deluxemap = -1;
1186                 p->tex_Texture_Attenuation = -1;
1187                 p->tex_Texture_Cube = -1;
1188                 p->tex_Texture_Refraction = -1;
1189                 p->tex_Texture_Reflection = -1;
1190                 p->tex_Texture_ShadowMap2D = -1;
1191                 p->tex_Texture_CubeProjection = -1;
1192                 p->tex_Texture_ScreenDepth = -1;
1193                 p->tex_Texture_ScreenNormalMap = -1;
1194                 p->tex_Texture_ScreenDiffuse = -1;
1195                 p->tex_Texture_ScreenSpecular = -1;
1196                 p->tex_Texture_ReflectMask = -1;
1197                 p->tex_Texture_ReflectCube = -1;
1198                 p->tex_Texture_BounceGrid = -1;
1199                 sampler = 0;
1200                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1201                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1202                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1203                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1204                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1205                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1206                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1207                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1208                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1209                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1210                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1211                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1212                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1213                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1214                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1215                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1216                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1217                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1218                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1219                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1220                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1221                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1222                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1223                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1224                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1225                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1226                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1227                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1228                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1229                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1230                 CHECKGLERROR
1231                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1232         }
1233         else
1234                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1235
1236         // free the strings
1237         if (vertexstring)
1238                 Mem_Free(vertexstring);
1239         if (geometrystring)
1240                 Mem_Free(geometrystring);
1241         if (fragmentstring)
1242                 Mem_Free(fragmentstring);
1243 }
1244
1245 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1246 {
1247         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1248         if (r_glsl_permutation != perm)
1249         {
1250                 r_glsl_permutation = perm;
1251                 if (!r_glsl_permutation->program)
1252                 {
1253                         if (!r_glsl_permutation->compiled)
1254                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1255                         if (!r_glsl_permutation->program)
1256                         {
1257                                 // remove features until we find a valid permutation
1258                                 int i;
1259                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1260                                 {
1261                                         // reduce i more quickly whenever it would not remove any bits
1262                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1263                                         if (!(permutation & j))
1264                                                 continue;
1265                                         permutation -= j;
1266                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1267                                         if (!r_glsl_permutation->compiled)
1268                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1269                                         if (r_glsl_permutation->program)
1270                                                 break;
1271                                 }
1272                                 if (i >= SHADERPERMUTATION_COUNT)
1273                                 {
1274                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1275                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1276                                         qglUseProgram(0);CHECKGLERROR
1277                                         return; // no bit left to clear, entire mode is broken
1278                                 }
1279                         }
1280                 }
1281                 CHECKGLERROR
1282                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1283         }
1284         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1285         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1286         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1287 }
1288
1289 #ifdef SUPPORTD3D
1290
1291 #ifdef SUPPORTD3D
1292 #include <d3d9.h>
1293 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1294 extern D3DCAPS9 vid_d3d9caps;
1295 #endif
1296
1297 struct r_hlsl_permutation_s;
1298 typedef struct r_hlsl_permutation_s
1299 {
1300         /// hash lookup data
1301         struct r_hlsl_permutation_s *hashnext;
1302         unsigned int mode;
1303         unsigned int permutation;
1304
1305         /// indicates if we have tried compiling this permutation already
1306         qboolean compiled;
1307         /// NULL if compilation failed
1308         IDirect3DVertexShader9 *vertexshader;
1309         IDirect3DPixelShader9 *pixelshader;
1310 }
1311 r_hlsl_permutation_t;
1312
1313 typedef enum D3DVSREGISTER_e
1314 {
1315         D3DVSREGISTER_TexMatrix = 0, // float4x4
1316         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1317         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1318         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1319         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1320         D3DVSREGISTER_ModelToLight = 20, // float4x4
1321         D3DVSREGISTER_EyePosition = 24,
1322         D3DVSREGISTER_FogPlane = 25,
1323         D3DVSREGISTER_LightDir = 26,
1324         D3DVSREGISTER_LightPosition = 27,
1325 }
1326 D3DVSREGISTER_t;
1327
1328 typedef enum D3DPSREGISTER_e
1329 {
1330         D3DPSREGISTER_Alpha = 0,
1331         D3DPSREGISTER_BloomBlur_Parameters = 1,
1332         D3DPSREGISTER_ClientTime = 2,
1333         D3DPSREGISTER_Color_Ambient = 3,
1334         D3DPSREGISTER_Color_Diffuse = 4,
1335         D3DPSREGISTER_Color_Specular = 5,
1336         D3DPSREGISTER_Color_Glow = 6,
1337         D3DPSREGISTER_Color_Pants = 7,
1338         D3DPSREGISTER_Color_Shirt = 8,
1339         D3DPSREGISTER_DeferredColor_Ambient = 9,
1340         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1341         D3DPSREGISTER_DeferredColor_Specular = 11,
1342         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1343         D3DPSREGISTER_DeferredMod_Specular = 13,
1344         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1345         D3DPSREGISTER_EyePosition = 15, // unused
1346         D3DPSREGISTER_FogColor = 16,
1347         D3DPSREGISTER_FogHeightFade = 17,
1348         D3DPSREGISTER_FogPlane = 18,
1349         D3DPSREGISTER_FogPlaneViewDist = 19,
1350         D3DPSREGISTER_FogRangeRecip = 20,
1351         D3DPSREGISTER_LightColor = 21,
1352         D3DPSREGISTER_LightDir = 22, // unused
1353         D3DPSREGISTER_LightPosition = 23,
1354         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1355         D3DPSREGISTER_PixelSize = 25,
1356         D3DPSREGISTER_ReflectColor = 26,
1357         D3DPSREGISTER_ReflectFactor = 27,
1358         D3DPSREGISTER_ReflectOffset = 28,
1359         D3DPSREGISTER_RefractColor = 29,
1360         D3DPSREGISTER_Saturation = 30,
1361         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1362         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1363         D3DPSREGISTER_ScreenToDepth = 33,
1364         D3DPSREGISTER_ShadowMap_Parameters = 34,
1365         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1366         D3DPSREGISTER_SpecularPower = 36,
1367         D3DPSREGISTER_UserVec1 = 37,
1368         D3DPSREGISTER_UserVec2 = 38,
1369         D3DPSREGISTER_UserVec3 = 39,
1370         D3DPSREGISTER_UserVec4 = 40,
1371         D3DPSREGISTER_ViewTintColor = 41,
1372         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1373         D3DPSREGISTER_BloomColorSubtract = 43,
1374         D3DPSREGISTER_ViewToLight = 44, // float4x4
1375         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1376         D3DPSREGISTER_NormalmapScrollBlend = 52,
1377         // next at 53
1378 }
1379 D3DPSREGISTER_t;
1380
1381 /// information about each possible shader permutation
1382 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1383 /// currently selected permutation
1384 r_hlsl_permutation_t *r_hlsl_permutation;
1385 /// storage for permutations linked in the hash table
1386 memexpandablearray_t r_hlsl_permutationarray;
1387
1388 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1389 {
1390         //unsigned int hashdepth = 0;
1391         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1392         r_hlsl_permutation_t *p;
1393         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1394         {
1395                 if (p->mode == mode && p->permutation == permutation)
1396                 {
1397                         //if (hashdepth > 10)
1398                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1399                         return p;
1400                 }
1401                 //hashdepth++;
1402         }
1403         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1404         p->mode = mode;
1405         p->permutation = permutation;
1406         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1407         r_hlsl_permutationhash[mode][hashindex] = p;
1408         //if (hashdepth > 10)
1409         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1410         return p;
1411 }
1412
1413 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1414 {
1415         char *shaderstring;
1416         if (!filename || !filename[0])
1417                 return NULL;
1418         if (!strcmp(filename, "hlsl/default.hlsl"))
1419         {
1420                 if (!hlslshaderstring)
1421                 {
1422                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1423                         if (hlslshaderstring)
1424                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1425                         else
1426                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1427                 }
1428                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1429                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1430                 return shaderstring;
1431         }
1432         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1433         if (shaderstring)
1434         {
1435                 if (printfromdisknotice)
1436                         Con_DPrintf("from disk %s... ", filename);
1437                 return shaderstring;
1438         }
1439         return shaderstring;
1440 }
1441
1442 #include <d3dx9.h>
1443 //#include <d3dx9shader.h>
1444 //#include <d3dx9mesh.h>
1445
1446 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1447 {
1448         DWORD *vsbin = NULL;
1449         DWORD *psbin = NULL;
1450         fs_offset_t vsbinsize;
1451         fs_offset_t psbinsize;
1452 //      IDirect3DVertexShader9 *vs = NULL;
1453 //      IDirect3DPixelShader9 *ps = NULL;
1454         ID3DXBuffer *vslog = NULL;
1455         ID3DXBuffer *vsbuffer = NULL;
1456         ID3DXConstantTable *vsconstanttable = NULL;
1457         ID3DXBuffer *pslog = NULL;
1458         ID3DXBuffer *psbuffer = NULL;
1459         ID3DXConstantTable *psconstanttable = NULL;
1460         int vsresult = 0;
1461         int psresult = 0;
1462         char temp[MAX_INPUTLINE];
1463         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1464         qboolean debugshader = gl_paranoid.integer != 0;
1465         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1466         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1467         if (!debugshader)
1468         {
1469                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1470                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1471         }
1472         if ((!vsbin && vertstring) || (!psbin && fragstring))
1473         {
1474                 const char* dllnames_d3dx9 [] =
1475                 {
1476                         "d3dx9_43.dll",
1477                         "d3dx9_42.dll",
1478                         "d3dx9_41.dll",
1479                         "d3dx9_40.dll",
1480                         "d3dx9_39.dll",
1481                         "d3dx9_38.dll",
1482                         "d3dx9_37.dll",
1483                         "d3dx9_36.dll",
1484                         "d3dx9_35.dll",
1485                         "d3dx9_34.dll",
1486                         "d3dx9_33.dll",
1487                         "d3dx9_32.dll",
1488                         "d3dx9_31.dll",
1489                         "d3dx9_30.dll",
1490                         "d3dx9_29.dll",
1491                         "d3dx9_28.dll",
1492                         "d3dx9_27.dll",
1493                         "d3dx9_26.dll",
1494                         "d3dx9_25.dll",
1495                         "d3dx9_24.dll",
1496                         NULL
1497                 };
1498                 dllhandle_t d3dx9_dll = NULL;
1499                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1500                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1501                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1502                 dllfunction_t d3dx9_dllfuncs[] =
1503                 {
1504                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1505                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1506                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1507                         {NULL, NULL}
1508                 };
1509                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1510                 {
1511                         DWORD shaderflags = 0;
1512                         if (debugshader)
1513                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1514                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1515                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1516                         if (vertstring && vertstring[0])
1517                         {
1518                                 if (debugshader)
1519                                 {
1520 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1521 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1522                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1523                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1524                                 }
1525                                 else
1526                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1527                                 if (vsbuffer)
1528                                 {
1529                                         vsbinsize = vsbuffer->GetBufferSize();
1530                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1531                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1532                                         vsbuffer->Release();
1533                                 }
1534                                 if (vslog)
1535                                 {
1536                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1537                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1538                                         vslog->Release();
1539                                 }
1540                         }
1541                         if (fragstring && fragstring[0])
1542                         {
1543                                 if (debugshader)
1544                                 {
1545 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1546 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1547                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1548                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1549                                 }
1550                                 else
1551                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1552                                 if (psbuffer)
1553                                 {
1554                                         psbinsize = psbuffer->GetBufferSize();
1555                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1556                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1557                                         psbuffer->Release();
1558                                 }
1559                                 if (pslog)
1560                                 {
1561                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1562                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1563                                         pslog->Release();
1564                                 }
1565                         }
1566                         Sys_UnloadLibrary(&d3dx9_dll);
1567                 }
1568                 else
1569                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1570         }
1571         if (vsbin && psbin)
1572         {
1573                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1574                 if (FAILED(vsresult))
1575                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1576                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1577                 if (FAILED(psresult))
1578                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1579         }
1580         // free the shader data
1581         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1582         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1583 }
1584
1585 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1586 {
1587         int i;
1588         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1589         int vertstring_length = 0;
1590         int geomstring_length = 0;
1591         int fragstring_length = 0;
1592         char *t;
1593         char *vertexstring, *geometrystring, *fragmentstring;
1594         char *vertstring, *geomstring, *fragstring;
1595         char permutationname[256];
1596         char cachename[256];
1597         int vertstrings_count = 0;
1598         int geomstrings_count = 0;
1599         int fragstrings_count = 0;
1600         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1601         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1602         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1603
1604         if (p->compiled)
1605                 return;
1606         p->compiled = true;
1607         p->vertexshader = NULL;
1608         p->pixelshader = NULL;
1609
1610         permutationname[0] = 0;
1611         cachename[0] = 0;
1612         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1613         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1614         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1615
1616         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1617         strlcat(cachename, "hlsl/", sizeof(cachename));
1618
1619         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1620         vertstrings_count = 0;
1621         geomstrings_count = 0;
1622         fragstrings_count = 0;
1623         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1624         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1625         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1626
1627         // the first pretext is which type of shader to compile as
1628         // (later these will all be bound together as a program object)
1629         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1630         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1631         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1632
1633         // the second pretext is the mode (for example a light source)
1634         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1635         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1636         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1637         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1638         strlcat(cachename, modeinfo->name, sizeof(cachename));
1639
1640         // now add all the permutation pretexts
1641         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1642         {
1643                 if (permutation & (1<<i))
1644                 {
1645                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1646                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1647                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1648                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1649                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1650                 }
1651                 else
1652                 {
1653                         // keep line numbers correct
1654                         vertstrings_list[vertstrings_count++] = "\n";
1655                         geomstrings_list[geomstrings_count++] = "\n";
1656                         fragstrings_list[fragstrings_count++] = "\n";
1657                 }
1658         }
1659
1660         // add static parms
1661         R_CompileShader_AddStaticParms(mode, permutation);
1662         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1663         vertstrings_count += shaderstaticparms_count;
1664         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1665         geomstrings_count += shaderstaticparms_count;
1666         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1667         fragstrings_count += shaderstaticparms_count;
1668
1669         // replace spaces in the cachename with _ characters
1670         for (i = 0;cachename[i];i++)
1671                 if (cachename[i] == ' ')
1672                         cachename[i] = '_';
1673
1674         // now append the shader text itself
1675         vertstrings_list[vertstrings_count++] = vertexstring;
1676         geomstrings_list[geomstrings_count++] = geometrystring;
1677         fragstrings_list[fragstrings_count++] = fragmentstring;
1678
1679         // if any sources were NULL, clear the respective list
1680         if (!vertexstring)
1681                 vertstrings_count = 0;
1682         if (!geometrystring)
1683                 geomstrings_count = 0;
1684         if (!fragmentstring)
1685                 fragstrings_count = 0;
1686
1687         vertstring_length = 0;
1688         for (i = 0;i < vertstrings_count;i++)
1689                 vertstring_length += strlen(vertstrings_list[i]);
1690         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1691         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1692                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1693
1694         geomstring_length = 0;
1695         for (i = 0;i < geomstrings_count;i++)
1696                 geomstring_length += strlen(geomstrings_list[i]);
1697         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1698         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1699                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1700
1701         fragstring_length = 0;
1702         for (i = 0;i < fragstrings_count;i++)
1703                 fragstring_length += strlen(fragstrings_list[i]);
1704         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1705         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1706                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1707
1708         // try to load the cached shader, or generate one
1709         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1710
1711         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1712                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1713         else
1714                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1715
1716         // free the strings
1717         if (vertstring)
1718                 Mem_Free(vertstring);
1719         if (geomstring)
1720                 Mem_Free(geomstring);
1721         if (fragstring)
1722                 Mem_Free(fragstring);
1723         if (vertexstring)
1724                 Mem_Free(vertexstring);
1725         if (geometrystring)
1726                 Mem_Free(geometrystring);
1727         if (fragmentstring)
1728                 Mem_Free(fragmentstring);
1729 }
1730
1731 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1732 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1733 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1734 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1735 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1736 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1737
1738 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1741 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1742 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1743 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1744
1745 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1746 {
1747         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1748         if (r_hlsl_permutation != perm)
1749         {
1750                 r_hlsl_permutation = perm;
1751                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1752                 {
1753                         if (!r_hlsl_permutation->compiled)
1754                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1755                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1756                         {
1757                                 // remove features until we find a valid permutation
1758                                 int i;
1759                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1760                                 {
1761                                         // reduce i more quickly whenever it would not remove any bits
1762                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1763                                         if (!(permutation & j))
1764                                                 continue;
1765                                         permutation -= j;
1766                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1767                                         if (!r_hlsl_permutation->compiled)
1768                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1769                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1770                                                 break;
1771                                 }
1772                                 if (i >= SHADERPERMUTATION_COUNT)
1773                                 {
1774                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1775                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1776                                         return; // no bit left to clear, entire mode is broken
1777                                 }
1778                         }
1779                 }
1780                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1781                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1782         }
1783         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1784         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1785         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1786 }
1787 #endif
1788
1789 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1790 {
1791         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1792         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1793         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1794         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1795 }
1796
1797 void R_GLSL_Restart_f(void)
1798 {
1799         unsigned int i, limit;
1800         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1801                 Mem_Free(glslshaderstring);
1802         glslshaderstring = NULL;
1803         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1804                 Mem_Free(hlslshaderstring);
1805         hlslshaderstring = NULL;
1806         switch(vid.renderpath)
1807         {
1808         case RENDERPATH_D3D9:
1809 #ifdef SUPPORTD3D
1810                 {
1811                         r_hlsl_permutation_t *p;
1812                         r_hlsl_permutation = NULL;
1813                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1814                         for (i = 0;i < limit;i++)
1815                         {
1816                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1817                                 {
1818                                         if (p->vertexshader)
1819                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1820                                         if (p->pixelshader)
1821                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1822                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1823                                 }
1824                         }
1825                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1826                 }
1827 #endif
1828                 break;
1829         case RENDERPATH_D3D10:
1830                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1831                 break;
1832         case RENDERPATH_D3D11:
1833                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1834                 break;
1835         case RENDERPATH_GL20:
1836         case RENDERPATH_GLES2:
1837                 {
1838                         r_glsl_permutation_t *p;
1839                         r_glsl_permutation = NULL;
1840                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1841                         for (i = 0;i < limit;i++)
1842                         {
1843                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1844                                 {
1845                                         GL_Backend_FreeProgram(p->program);
1846                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1847                                 }
1848                         }
1849                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1850                 }
1851                 break;
1852         case RENDERPATH_GL11:
1853         case RENDERPATH_GL13:
1854         case RENDERPATH_GLES1:
1855                 break;
1856         case RENDERPATH_SOFT:
1857                 break;
1858         }
1859 }
1860
1861 void R_GLSL_DumpShader_f(void)
1862 {
1863         int i;
1864         qfile_t *file;
1865
1866         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1867         if (file)
1868         {
1869                 FS_Print(file, "/* The engine may define the following macros:\n");
1870                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1871                 for (i = 0;i < SHADERMODE_COUNT;i++)
1872                         FS_Print(file, glslshadermodeinfo[i].pretext);
1873                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1874                         FS_Print(file, shaderpermutationinfo[i].pretext);
1875                 FS_Print(file, "*/\n");
1876                 FS_Print(file, builtinshaderstring);
1877                 FS_Close(file);
1878                 Con_Printf("glsl/default.glsl written\n");
1879         }
1880         else
1881                 Con_Printf("failed to write to glsl/default.glsl\n");
1882
1883         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1884         if (file)
1885         {
1886                 FS_Print(file, "/* The engine may define the following macros:\n");
1887                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1888                 for (i = 0;i < SHADERMODE_COUNT;i++)
1889                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1890                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1891                         FS_Print(file, shaderpermutationinfo[i].pretext);
1892                 FS_Print(file, "*/\n");
1893                 FS_Print(file, builtinhlslshaderstring);
1894                 FS_Close(file);
1895                 Con_Printf("hlsl/default.hlsl written\n");
1896         }
1897         else
1898                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1899 }
1900
1901 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean 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 (vid.allowalphatocoverage)
2005                 GL_AlphaToCoverage(false);
2006         switch (vid.renderpath)
2007         {
2008         case RENDERPATH_D3D9:
2009 #ifdef SUPPORTHLSL
2010                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2011 #endif
2012                 break;
2013         case RENDERPATH_D3D10:
2014                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2015                 break;
2016         case RENDERPATH_D3D11:
2017                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2018                 break;
2019         case RENDERPATH_GL20:
2020         case RENDERPATH_GLES2:
2021                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2022                 break;
2023         case RENDERPATH_GL13:
2024         case RENDERPATH_GLES1:
2025                 break;
2026         case RENDERPATH_GL11:
2027                 break;
2028         case RENDERPATH_SOFT:
2029                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2030                 break;
2031         }
2032 }
2033
2034 extern qboolean r_shadow_usingdeferredprepass;
2035 extern cvar_t r_shadow_deferred_8bitrange;
2036 extern rtexture_t *r_shadow_attenuationgradienttexture;
2037 extern rtexture_t *r_shadow_attenuation2dtexture;
2038 extern rtexture_t *r_shadow_attenuation3dtexture;
2039 extern qboolean r_shadow_usingshadowmap2d;
2040 extern qboolean r_shadow_usingshadowmaportho;
2041 extern float r_shadow_shadowmap_texturescale[2];
2042 extern float r_shadow_shadowmap_parameters[4];
2043 extern qboolean r_shadow_shadowmapvsdct;
2044 extern qboolean r_shadow_shadowmapsampler;
2045 extern int r_shadow_shadowmappcf;
2046 extern rtexture_t *r_shadow_shadowmap2dtexture;
2047 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2048 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2049 extern matrix4x4_t r_shadow_shadowmapmatrix;
2050 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2051 extern int r_shadow_prepass_width;
2052 extern int r_shadow_prepass_height;
2053 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2054 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2055 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2056 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2057 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2058
2059 #define BLENDFUNC_ALLOWS_COLORMOD      1
2060 #define BLENDFUNC_ALLOWS_FOG           2
2061 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2062 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2063 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2064 static int R_BlendFuncFlags(int src, int dst)
2065 {
2066         int r = 0;
2067
2068         // a blendfunc allows colormod if:
2069         // a) it can never keep the destination pixel invariant, or
2070         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2071         // this is to prevent unintended side effects from colormod
2072
2073         // a blendfunc allows fog if:
2074         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2075         // this is to prevent unintended side effects from fog
2076
2077         // these checks are the output of fogeval.pl
2078
2079         r |= BLENDFUNC_ALLOWS_COLORMOD;
2080         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2081         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2082         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2083         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2084         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2085         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2086         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2087         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2088         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2089         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2090         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2091         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2092         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2094         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2095         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2096         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2097         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2098         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2099         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2100         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2101
2102         return r;
2103 }
2104
2105 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)
2106 {
2107         // select a permutation of the lighting shader appropriate to this
2108         // combination of texture, entity, light source, and fogging, only use the
2109         // minimum features necessary to avoid wasting rendering time in the
2110         // fragment shader on features that are not being used
2111         unsigned int permutation = 0;
2112         unsigned int mode = 0;
2113         int blendfuncflags;
2114         static float dummy_colormod[3] = {1, 1, 1};
2115         float *colormod = rsurface.colormod;
2116         float m16f[16];
2117         matrix4x4_t tempmatrix;
2118         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2119         if (r_trippy.integer && !notrippy)
2120                 permutation |= SHADERPERMUTATION_TRIPPY;
2121         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2122                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2123         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2124                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2125         if (rsurfacepass == RSURFPASS_BACKGROUND)
2126         {
2127                 // distorted background
2128                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2129                 {
2130                         mode = SHADERMODE_WATER;
2131                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2132                         {
2133                                 // this is the right thing to do for wateralpha
2134                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2135                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2136                         }
2137                         else
2138                         {
2139                                 // this is the right thing to do for entity alpha
2140                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2141                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2142                         }
2143                 }
2144                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2145                 {
2146                         mode = SHADERMODE_REFRACTION;
2147                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2148                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2149                 }
2150                 else
2151                 {
2152                         mode = SHADERMODE_GENERIC;
2153                         permutation |= SHADERPERMUTATION_DIFFUSE;
2154                         GL_BlendFunc(GL_ONE, GL_ZERO);
2155                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2156                 }
2157                 if (vid.allowalphatocoverage)
2158                         GL_AlphaToCoverage(false);
2159         }
2160         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2161         {
2162                 if (r_glsl_offsetmapping.integer)
2163                 {
2164                         switch(rsurface.texture->offsetmapping)
2165                         {
2166                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2167                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2168                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2169                         case OFFSETMAPPING_OFF: break;
2170                         }
2171                 }
2172                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2173                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2174                 // normalmap (deferred prepass), may use alpha test on diffuse
2175                 mode = SHADERMODE_DEFERREDGEOMETRY;
2176                 GL_BlendFunc(GL_ONE, GL_ZERO);
2177                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2178                 if (vid.allowalphatocoverage)
2179                         GL_AlphaToCoverage(false);
2180         }
2181         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2182         {
2183                 if (r_glsl_offsetmapping.integer)
2184                 {
2185                         switch(rsurface.texture->offsetmapping)
2186                         {
2187                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2188                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2189                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2190                         case OFFSETMAPPING_OFF: break;
2191                         }
2192                 }
2193                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2194                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2195                 // light source
2196                 mode = SHADERMODE_LIGHTSOURCE;
2197                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2198                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2199                 if (diffusescale > 0)
2200                         permutation |= SHADERPERMUTATION_DIFFUSE;
2201                 if (specularscale > 0)
2202                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2203                 if (r_refdef.fogenabled)
2204                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2205                 if (rsurface.texture->colormapping)
2206                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2207                 if (r_shadow_usingshadowmap2d)
2208                 {
2209                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2210                         if(r_shadow_shadowmapvsdct)
2211                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2212
2213                         if (r_shadow_shadowmapsampler)
2214                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2215                         if (r_shadow_shadowmappcf > 1)
2216                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2217                         else if (r_shadow_shadowmappcf)
2218                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2219                 }
2220                 if (rsurface.texture->reflectmasktexture)
2221                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2222                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2223                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2224                 if (vid.allowalphatocoverage)
2225                         GL_AlphaToCoverage(false);
2226         }
2227         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2228         {
2229                 if (r_glsl_offsetmapping.integer)
2230                 {
2231                         switch(rsurface.texture->offsetmapping)
2232                         {
2233                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2234                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2235                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2236                         case OFFSETMAPPING_OFF: break;
2237                         }
2238                 }
2239                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2240                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2241                 // unshaded geometry (fullbright or ambient model lighting)
2242                 mode = SHADERMODE_FLATCOLOR;
2243                 ambientscale = diffusescale = specularscale = 0;
2244                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2245                         permutation |= SHADERPERMUTATION_GLOW;
2246                 if (r_refdef.fogenabled)
2247                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2248                 if (rsurface.texture->colormapping)
2249                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2250                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2251                 {
2252                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2253                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2254
2255                         if (r_shadow_shadowmapsampler)
2256                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2257                         if (r_shadow_shadowmappcf > 1)
2258                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2259                         else if (r_shadow_shadowmappcf)
2260                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2261                 }
2262                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2263                         permutation |= SHADERPERMUTATION_REFLECTION;
2264                 if (rsurface.texture->reflectmasktexture)
2265                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2266                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2267                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2268                 // when using alphatocoverage, we don't need alphakill
2269                 if (vid.allowalphatocoverage)
2270                 {
2271                         if (r_transparent_alphatocoverage.integer)
2272                         {
2273                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2274                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2275                         }
2276                         else
2277                                 GL_AlphaToCoverage(false);
2278                 }
2279         }
2280         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2281         {
2282                 if (r_glsl_offsetmapping.integer)
2283                 {
2284                         switch(rsurface.texture->offsetmapping)
2285                         {
2286                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2287                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2288                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2289                         case OFFSETMAPPING_OFF: break;
2290                         }
2291                 }
2292                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2293                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2294                 // directional model lighting
2295                 mode = SHADERMODE_LIGHTDIRECTION;
2296                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2297                         permutation |= SHADERPERMUTATION_GLOW;
2298                 permutation |= SHADERPERMUTATION_DIFFUSE;
2299                 if (specularscale > 0)
2300                         permutation |= SHADERPERMUTATION_SPECULAR;
2301                 if (r_refdef.fogenabled)
2302                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2303                 if (rsurface.texture->colormapping)
2304                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2305                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2306                 {
2307                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2308                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2309
2310                         if (r_shadow_shadowmapsampler)
2311                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2312                         if (r_shadow_shadowmappcf > 1)
2313                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2314                         else if (r_shadow_shadowmappcf)
2315                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2316                 }
2317                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2318                         permutation |= SHADERPERMUTATION_REFLECTION;
2319                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2320                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2321                 if (rsurface.texture->reflectmasktexture)
2322                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2323                 if (r_shadow_bouncegridtexture)
2324                 {
2325                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2326                         if (r_shadow_bouncegriddirectional)
2327                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2328                 }
2329                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2330                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2331                 // when using alphatocoverage, we don't need alphakill
2332                 if (vid.allowalphatocoverage)
2333                 {
2334                         if (r_transparent_alphatocoverage.integer)
2335                         {
2336                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2337                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2338                         }
2339                         else
2340                                 GL_AlphaToCoverage(false);
2341                 }
2342         }
2343         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2344         {
2345                 if (r_glsl_offsetmapping.integer)
2346                 {
2347                         switch(rsurface.texture->offsetmapping)
2348                         {
2349                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2350                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2351                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2352                         case OFFSETMAPPING_OFF: break;
2353                         }
2354                 }
2355                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2356                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2357                 // ambient model lighting
2358                 mode = SHADERMODE_LIGHTDIRECTION;
2359                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2360                         permutation |= SHADERPERMUTATION_GLOW;
2361                 if (r_refdef.fogenabled)
2362                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2363                 if (rsurface.texture->colormapping)
2364                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2365                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2366                 {
2367                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2368                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2369
2370                         if (r_shadow_shadowmapsampler)
2371                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2372                         if (r_shadow_shadowmappcf > 1)
2373                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2374                         else if (r_shadow_shadowmappcf)
2375                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2376                 }
2377                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2378                         permutation |= SHADERPERMUTATION_REFLECTION;
2379                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2380                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2381                 if (rsurface.texture->reflectmasktexture)
2382                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2383                 if (r_shadow_bouncegridtexture)
2384                 {
2385                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2386                         if (r_shadow_bouncegriddirectional)
2387                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2388                 }
2389                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2390                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2391                 // when using alphatocoverage, we don't need alphakill
2392                 if (vid.allowalphatocoverage)
2393                 {
2394                         if (r_transparent_alphatocoverage.integer)
2395                         {
2396                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2397                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2398                         }
2399                         else
2400                                 GL_AlphaToCoverage(false);
2401                 }
2402         }
2403         else
2404         {
2405                 if (r_glsl_offsetmapping.integer)
2406                 {
2407                         switch(rsurface.texture->offsetmapping)
2408                         {
2409                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2410                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2411                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2412                         case OFFSETMAPPING_OFF: break;
2413                         }
2414                 }
2415                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2416                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2417                 // lightmapped wall
2418                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2419                         permutation |= SHADERPERMUTATION_GLOW;
2420                 if (r_refdef.fogenabled)
2421                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2422                 if (rsurface.texture->colormapping)
2423                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2424                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2425                 {
2426                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2427                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2428
2429                         if (r_shadow_shadowmapsampler)
2430                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2431                         if (r_shadow_shadowmappcf > 1)
2432                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2433                         else if (r_shadow_shadowmappcf)
2434                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2435                 }
2436                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2437                         permutation |= SHADERPERMUTATION_REFLECTION;
2438                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2439                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2440                 if (rsurface.texture->reflectmasktexture)
2441                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2442                 if (FAKELIGHT_ENABLED)
2443                 {
2444                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2445                         mode = SHADERMODE_FAKELIGHT;
2446                         permutation |= SHADERPERMUTATION_DIFFUSE;
2447                         if (specularscale > 0)
2448                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2449                 }
2450                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2451                 {
2452                         // deluxemapping (light direction texture)
2453                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2454                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2455                         else
2456                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2457                         permutation |= SHADERPERMUTATION_DIFFUSE;
2458                         if (specularscale > 0)
2459                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2460                 }
2461                 else if (r_glsl_deluxemapping.integer >= 2 && rsurface.uselightmaptexture)
2462                 {
2463                         // fake deluxemapping (uniform light direction in tangentspace)
2464                         mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2465                         permutation |= SHADERPERMUTATION_DIFFUSE;
2466                         if (specularscale > 0)
2467                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2468                 }
2469                 else if (rsurface.uselightmaptexture)
2470                 {
2471                         // ordinary lightmapping (q1bsp, q3bsp)
2472                         mode = SHADERMODE_LIGHTMAP;
2473                 }
2474                 else
2475                 {
2476                         // ordinary vertex coloring (q3bsp)
2477                         mode = SHADERMODE_VERTEXCOLOR;
2478                 }
2479                 if (r_shadow_bouncegridtexture)
2480                 {
2481                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2482                         if (r_shadow_bouncegriddirectional)
2483                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2484                 }
2485                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2486                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2487                 // when using alphatocoverage, we don't need alphakill
2488                 if (vid.allowalphatocoverage)
2489                 {
2490                         if (r_transparent_alphatocoverage.integer)
2491                         {
2492                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2493                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2494                         }
2495                         else
2496                                 GL_AlphaToCoverage(false);
2497                 }
2498         }
2499         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2500                 colormod = dummy_colormod;
2501         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2502                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2503         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2504                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2505         switch(vid.renderpath)
2506         {
2507         case RENDERPATH_D3D9:
2508 #ifdef SUPPORTD3D
2509                 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);
2510                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2511                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2512                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2513                 if (mode == SHADERMODE_LIGHTSOURCE)
2514                 {
2515                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2516                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2517                 }
2518                 else
2519                 {
2520                         if (mode == SHADERMODE_LIGHTDIRECTION)
2521                         {
2522                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2523                         }
2524                 }
2525                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2526                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2527                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2528                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2529                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2530
2531                 if (mode == SHADERMODE_LIGHTSOURCE)
2532                 {
2533                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2534                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2535                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2536                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2537                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2538
2539                         // additive passes are only darkened by fog, not tinted
2540                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2541                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2542                 }
2543                 else
2544                 {
2545                         if (mode == SHADERMODE_FLATCOLOR)
2546                         {
2547                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2548                         }
2549                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2550                         {
2551                                 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]);
2552                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2553                                 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);
2554                                 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);
2555                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2556                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2557                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2558                         }
2559                         else
2560                         {
2561                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2563                                 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);
2564                                 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);
2565                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2566                         }
2567                         // additive passes are only darkened by fog, not tinted
2568                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2570                         else
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2572                         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);
2573                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2574                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2575                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2576                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2577                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2578                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2579                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2580                         if (mode == SHADERMODE_WATER)
2581                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2582                 }
2583                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2584                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2585                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2586                 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));
2587                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2588                 if (rsurface.texture->pantstexture)
2589                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2590                 else
2591                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2592                 if (rsurface.texture->shirttexture)
2593                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2594                 else
2595                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2596                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2597                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2598                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2599                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2600                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2601                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2602                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2603                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2604                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2605                         );
2606                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2607                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2608
2609                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2610                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2611                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2612                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2613                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2614                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2615                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2616                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2617                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2618                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2619                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2620                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2621                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2622                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2623                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2624                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2625                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2626                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2627                 {
2628                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2629                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2630                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2631                 }
2632                 else
2633                 {
2634                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2635                 }
2636 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2637 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2638                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2639                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2640                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2641                 {
2642                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2643                         if (rsurface.rtlight)
2644                         {
2645                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2646                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2647                         }
2648                 }
2649 #endif
2650                 break;
2651         case RENDERPATH_D3D10:
2652                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2653                 break;
2654         case RENDERPATH_D3D11:
2655                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2656                 break;
2657         case RENDERPATH_GL20:
2658         case RENDERPATH_GLES2:
2659                 if (!vid.useinterleavedarrays)
2660                 {
2661                         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);
2662                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2663                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2664                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2665                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2666                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2667                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2668                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2669                 }
2670                 else
2671                 {
2672                         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);
2673                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2674                 }
2675                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2676                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2677                 if (mode == SHADERMODE_LIGHTSOURCE)
2678                 {
2679                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2680                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2681                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2682                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2683                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2684                         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);
2685         
2686                         // additive passes are only darkened by fog, not tinted
2687                         if (r_glsl_permutation->loc_FogColor >= 0)
2688                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2689                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2690                 }
2691                 else
2692                 {
2693                         if (mode == SHADERMODE_FLATCOLOR)
2694                         {
2695                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2696                         }
2697                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2698                         {
2699                                 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]);
2700                                 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]);
2701                                 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);
2702                                 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);
2703                                 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);
2704                                 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]);
2705                                 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]);
2706                         }
2707                         else
2708                         {
2709                                 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]);
2710                                 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]);
2711                                 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);
2712                                 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);
2713                                 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);
2714                         }
2715                         // additive passes are only darkened by fog, not tinted
2716                         if (r_glsl_permutation->loc_FogColor >= 0)
2717                         {
2718                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2719                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2720                                 else
2721                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2722                         }
2723                         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);
2724                         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]);
2725                         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]);
2726                         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]);
2727                         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]);
2728                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2729                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2730                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2731                         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]);
2732                 }
2733                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2734                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2735                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2736                 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]);
2737                 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]);
2738
2739                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2740                 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));
2741                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2742                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2743                 {
2744                         if (rsurface.texture->pantstexture)
2745                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2746                         else
2747                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2748                 }
2749                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2750                 {
2751                         if (rsurface.texture->shirttexture)
2752                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2753                         else
2754                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2755                 }
2756                 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]);
2757                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2758                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2759                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2760                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2761                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2762                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2763                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2764                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2765                         );
2766                 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]);
2767                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2768                 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);}
2769                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2770
2771                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2772                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2773                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2774                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2775                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2776                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2777                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2778                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2779                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2780                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2781                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2782                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2783                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2784                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2785                 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);
2786                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2787                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2788                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2789                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2790                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2791                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2792                 {
2793                         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);
2794                         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);
2795                         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);
2796                 }
2797                 else
2798                 {
2799                         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);
2800                 }
2801                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2802                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2803                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2804                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2805                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2806                 {
2807                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2808                         if (rsurface.rtlight)
2809                         {
2810                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2811                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2812                         }
2813                 }
2814                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2815                 CHECKGLERROR
2816                 break;
2817         case RENDERPATH_GL11:
2818         case RENDERPATH_GL13:
2819         case RENDERPATH_GLES1:
2820                 break;
2821         case RENDERPATH_SOFT:
2822                 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);
2823                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2824                 R_SetupShader_SetPermutationSoft(mode, permutation);
2825                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2826                 if (mode == SHADERMODE_LIGHTSOURCE)
2827                 {
2828                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2829                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2830                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2831                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2832                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2833                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2834         
2835                         // additive passes are only darkened by fog, not tinted
2836                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2837                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2838                 }
2839                 else
2840                 {
2841                         if (mode == SHADERMODE_FLATCOLOR)
2842                         {
2843                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2844                         }
2845                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2846                         {
2847                                 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]);
2848                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2849                                 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);
2850                                 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);
2851                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2852                                 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]);
2853                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2854                         }
2855                         else
2856                         {
2857                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2858                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2859                                 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);
2860                                 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);
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2862                         }
2863                         // additive passes are only darkened by fog, not tinted
2864                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2866                         else
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2868                         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);
2869                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2870                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2871                         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]);
2872                         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]);
2873                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2874                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2875                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2876                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2877                 }
2878                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2879                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2880                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2881                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2882                 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]);
2883
2884                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2885                 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));
2886                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2887                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2888                 {
2889                         if (rsurface.texture->pantstexture)
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2891                         else
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2893                 }
2894                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2895                 {
2896                         if (rsurface.texture->shirttexture)
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2898                         else
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2900                 }
2901                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2902                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2903                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2904                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2905                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2906                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2907                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2908                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2909                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2910                         );
2911                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2912                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2913
2914                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2915                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2916                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2917                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2918                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2919                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2920                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2921                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2922                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2923                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2924                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2925                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2926                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2927                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2928                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2929                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2930                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2931                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2932                 {
2933                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2934                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2935                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2936                 }
2937                 else
2938                 {
2939                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2940                 }
2941 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2942 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2943                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2944                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2945                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2946                 {
2947                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2948                         if (rsurface.rtlight)
2949                         {
2950                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2951                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2952                         }
2953                 }
2954                 break;
2955         }
2956 }
2957
2958 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2959 {
2960         // select a permutation of the lighting shader appropriate to this
2961         // combination of texture, entity, light source, and fogging, only use the
2962         // minimum features necessary to avoid wasting rendering time in the
2963         // fragment shader on features that are not being used
2964         unsigned int permutation = 0;
2965         unsigned int mode = 0;
2966         const float *lightcolorbase = rtlight->currentcolor;
2967         float ambientscale = rtlight->ambientscale;
2968         float diffusescale = rtlight->diffusescale;
2969         float specularscale = rtlight->specularscale;
2970         // this is the location of the light in view space
2971         vec3_t viewlightorigin;
2972         // this transforms from view space (camera) to light space (cubemap)
2973         matrix4x4_t viewtolight;
2974         matrix4x4_t lighttoview;
2975         float viewtolight16f[16];
2976         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2977         // light source
2978         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2979         if (rtlight->currentcubemap != r_texture_whitecube)
2980                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2981         if (diffusescale > 0)
2982                 permutation |= SHADERPERMUTATION_DIFFUSE;
2983         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2984                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2985         if (r_shadow_usingshadowmap2d)
2986         {
2987                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2988                 if (r_shadow_shadowmapvsdct)
2989                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2990
2991                 if (r_shadow_shadowmapsampler)
2992                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2993                 if (r_shadow_shadowmappcf > 1)
2994                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2995                 else if (r_shadow_shadowmappcf)
2996                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2997         }
2998         if (vid.allowalphatocoverage)
2999                 GL_AlphaToCoverage(false);
3000         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3001         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3002         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3003         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3004         switch(vid.renderpath)
3005         {
3006         case RENDERPATH_D3D9:
3007 #ifdef SUPPORTD3D
3008                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3009                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3010                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3011                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3012                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3013                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3014                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3015                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3016                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
3017                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3018                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3019
3020                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3021                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3022                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3023                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3024                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3025                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3026 #endif
3027                 break;
3028         case RENDERPATH_D3D10:
3029                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3030                 break;
3031         case RENDERPATH_D3D11:
3032                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3033                 break;
3034         case RENDERPATH_GL20:
3035         case RENDERPATH_GLES2:
3036                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3037                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3038                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3039                 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);
3040                 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);
3041                 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);
3042                 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]);
3043                 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]);
3044                 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));
3045                 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]);
3046                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3047
3048                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3049                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3050                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3051                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3052                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3053                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3054                 break;
3055         case RENDERPATH_GL11:
3056         case RENDERPATH_GL13:
3057         case RENDERPATH_GLES1:
3058                 break;
3059         case RENDERPATH_SOFT:
3060                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3061                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3062                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3063                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3064                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3065                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3066                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3067                 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]);
3068                 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));
3069                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3070                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3071
3072                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3073                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3074                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3075                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3076                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3077                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3078                 break;
3079         }
3080 }
3081
3082 #define SKINFRAME_HASH 1024
3083
3084 typedef struct
3085 {
3086         int loadsequence; // incremented each level change
3087         memexpandablearray_t array;
3088         skinframe_t *hash[SKINFRAME_HASH];
3089 }
3090 r_skinframe_t;
3091 r_skinframe_t r_skinframe;
3092
3093 void R_SkinFrame_PrepareForPurge(void)
3094 {
3095         r_skinframe.loadsequence++;
3096         // wrap it without hitting zero
3097         if (r_skinframe.loadsequence >= 200)
3098                 r_skinframe.loadsequence = 1;
3099 }
3100
3101 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3102 {
3103         if (!skinframe)
3104                 return;
3105         // mark the skinframe as used for the purging code
3106         skinframe->loadsequence = r_skinframe.loadsequence;
3107 }
3108
3109 void R_SkinFrame_Purge(void)
3110 {
3111         int i;
3112         skinframe_t *s;
3113         for (i = 0;i < SKINFRAME_HASH;i++)
3114         {
3115                 for (s = r_skinframe.hash[i];s;s = s->next)
3116                 {
3117                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3118                         {
3119                                 if (s->merged == s->base)
3120                                         s->merged = NULL;
3121                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3122                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3123                                 R_PurgeTexture(s->merged);s->merged = NULL;
3124                                 R_PurgeTexture(s->base  );s->base   = NULL;
3125                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3126                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3127                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3128                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3129                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3130                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3131                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3132                                 s->loadsequence = 0;
3133                         }
3134                 }
3135         }
3136 }
3137
3138 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3139         skinframe_t *item;
3140         char basename[MAX_QPATH];
3141
3142         Image_StripImageExtension(name, basename, sizeof(basename));
3143
3144         if( last == NULL ) {
3145                 int hashindex;
3146                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3147                 item = r_skinframe.hash[hashindex];
3148         } else {
3149                 item = last->next;
3150         }
3151
3152         // linearly search through the hash bucket
3153         for( ; item ; item = item->next ) {
3154                 if( !strcmp( item->basename, basename ) ) {
3155                         return item;
3156                 }
3157         }
3158         return NULL;
3159 }
3160
3161 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3162 {
3163         skinframe_t *item;
3164         int hashindex;
3165         char basename[MAX_QPATH];
3166
3167         Image_StripImageExtension(name, basename, sizeof(basename));
3168
3169         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3170         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3171                 if (!strcmp(item->basename, basename) && item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)
3172                         break;
3173
3174         if (!item) {
3175                 rtexture_t *dyntexture;
3176                 // check whether its a dynamic texture
3177                 dyntexture = CL_GetDynTexture( basename );
3178                 if (!add && !dyntexture)
3179                         return NULL;
3180                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3181                 memset(item, 0, sizeof(*item));
3182                 strlcpy(item->basename, basename, sizeof(item->basename));
3183                 item->base = dyntexture; // either NULL or dyntexture handle
3184                 item->textureflags = textureflags;
3185                 item->comparewidth = comparewidth;
3186                 item->compareheight = compareheight;
3187                 item->comparecrc = comparecrc;
3188                 item->next = r_skinframe.hash[hashindex];
3189                 r_skinframe.hash[hashindex] = item;
3190         }
3191         else if( item->base == NULL )
3192         {
3193                 rtexture_t *dyntexture;
3194                 // check whether its a dynamic texture
3195                 // 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]
3196                 dyntexture = CL_GetDynTexture( basename );
3197                 item->base = dyntexture; // either NULL or dyntexture handle
3198         }
3199
3200         R_SkinFrame_MarkUsed(item);
3201         return item;
3202 }
3203
3204 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3205         { \
3206                 unsigned long long avgcolor[5], wsum; \
3207                 int pix, comp, w; \
3208                 avgcolor[0] = 0; \
3209                 avgcolor[1] = 0; \
3210                 avgcolor[2] = 0; \
3211                 avgcolor[3] = 0; \
3212                 avgcolor[4] = 0; \
3213                 wsum = 0; \
3214                 for(pix = 0; pix < cnt; ++pix) \
3215                 { \
3216                         w = 0; \
3217                         for(comp = 0; comp < 3; ++comp) \
3218                                 w += getpixel; \
3219                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3220                         { \
3221                                 ++wsum; \
3222                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3223                                 w = getpixel; \
3224                                 for(comp = 0; comp < 3; ++comp) \
3225                                         avgcolor[comp] += getpixel * w; \
3226                                 avgcolor[3] += w; \
3227                         } \
3228                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3229                         avgcolor[4] += getpixel; \
3230                 } \
3231                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3232                         avgcolor[3] = 1; \
3233                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3234                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3235                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3236                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3237         }
3238
3239 extern cvar_t gl_picmip;
3240 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3241 {
3242         int j;
3243         unsigned char *pixels;
3244         unsigned char *bumppixels;
3245         unsigned char *basepixels = NULL;
3246         int basepixels_width = 0;
3247         int basepixels_height = 0;
3248         skinframe_t *skinframe;
3249         rtexture_t *ddsbase = NULL;
3250         qboolean ddshasalpha = false;
3251         float ddsavgcolor[4];
3252         char basename[MAX_QPATH];
3253         int miplevel = R_PicmipForFlags(textureflags);
3254         int savemiplevel = miplevel;
3255         int mymiplevel;
3256
3257         if (cls.state == ca_dedicated)
3258                 return NULL;
3259
3260         // return an existing skinframe if already loaded
3261         // if loading of the first image fails, don't make a new skinframe as it
3262         // would cause all future lookups of this to be missing
3263         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3264         if (skinframe && skinframe->base)
3265                 return skinframe;
3266
3267         Image_StripImageExtension(name, basename, sizeof(basename));
3268
3269         // check for DDS texture file first
3270         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3271         {
3272                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3273                 if (basepixels == NULL)
3274                         return NULL;
3275         }
3276
3277         // FIXME handle miplevel
3278
3279         if (developer_loading.integer)
3280                 Con_Printf("loading skin \"%s\"\n", name);
3281
3282         // we've got some pixels to store, so really allocate this new texture now
3283         if (!skinframe)
3284                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3285         skinframe->stain = NULL;
3286         skinframe->merged = NULL;
3287         skinframe->base = NULL;
3288         skinframe->pants = NULL;
3289         skinframe->shirt = NULL;
3290         skinframe->nmap = NULL;
3291         skinframe->gloss = NULL;
3292         skinframe->glow = NULL;
3293         skinframe->fog = NULL;
3294         skinframe->reflect = NULL;
3295         skinframe->hasalpha = false;
3296
3297         if (ddsbase)
3298         {
3299                 skinframe->base = ddsbase;
3300                 skinframe->hasalpha = ddshasalpha;
3301                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3302                 if (r_loadfog && skinframe->hasalpha)
3303                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3304                 //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]);
3305         }
3306         else
3307         {
3308                 basepixels_width = image_width;
3309                 basepixels_height = image_height;
3310                 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);
3311                 if (textureflags & TEXF_ALPHA)
3312                 {
3313                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3314                         {
3315                                 if (basepixels[j] < 255)
3316                                 {
3317                                         skinframe->hasalpha = true;
3318                                         break;
3319                                 }
3320                         }
3321                         if (r_loadfog && skinframe->hasalpha)
3322                         {
3323                                 // has transparent pixels
3324                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3325                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3326                                 {
3327                                         pixels[j+0] = 255;
3328                                         pixels[j+1] = 255;
3329                                         pixels[j+2] = 255;
3330                                         pixels[j+3] = basepixels[j+3];
3331                                 }
3332                                 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);
3333                                 Mem_Free(pixels);
3334                         }
3335                 }
3336                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3337                 //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]);
3338                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3339                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3340                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3341                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3342         }
3343
3344         if (r_loaddds)
3345         {
3346                 mymiplevel = savemiplevel;
3347                 if (r_loadnormalmap)
3348                         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);
3349                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3350                 if (r_loadgloss)
3351                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3352                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3353                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3354                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3355         }
3356
3357         // _norm is the name used by tenebrae and has been adopted as standard
3358         if (r_loadnormalmap && skinframe->nmap == NULL)
3359         {
3360                 mymiplevel = savemiplevel;
3361                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3362                 {
3363                         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);
3364                         Mem_Free(pixels);
3365                         pixels = NULL;
3366                 }
3367                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3368                 {
3369                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3370                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3371                         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);
3372                         Mem_Free(pixels);
3373                         Mem_Free(bumppixels);
3374                 }
3375                 else if (r_shadow_bumpscale_basetexture.value > 0)
3376                 {
3377                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3378                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3379                         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);
3380                         Mem_Free(pixels);
3381                 }
3382                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3383                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3384         }
3385
3386         // _luma is supported only for tenebrae compatibility
3387         // _glow is the preferred name
3388         mymiplevel = savemiplevel;
3389         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))))
3390         {
3391                 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);
3392                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3393                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3394                 Mem_Free(pixels);pixels = NULL;
3395         }
3396
3397         mymiplevel = savemiplevel;
3398         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3399         {
3400                 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);
3401                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3402                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3403                 Mem_Free(pixels);
3404                 pixels = NULL;
3405         }
3406
3407         mymiplevel = savemiplevel;
3408         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3409         {
3410                 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);
3411                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3412                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3413                 Mem_Free(pixels);
3414                 pixels = NULL;
3415         }
3416
3417         mymiplevel = savemiplevel;
3418         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3419         {
3420                 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);
3421                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3422                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3423                 Mem_Free(pixels);
3424                 pixels = NULL;
3425         }
3426
3427         mymiplevel = savemiplevel;
3428         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3429         {
3430                 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);
3431                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3432                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3433                 Mem_Free(pixels);
3434                 pixels = NULL;
3435         }
3436
3437         if (basepixels)
3438                 Mem_Free(basepixels);
3439
3440         return skinframe;
3441 }
3442
3443 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3444 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3445 {
3446         int i;
3447         unsigned char *temp1, *temp2;
3448         skinframe_t *skinframe;
3449
3450         if (cls.state == ca_dedicated)
3451                 return NULL;
3452
3453         // if already loaded just return it, otherwise make a new skinframe
3454         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3455         if (skinframe && skinframe->base)
3456                 return skinframe;
3457
3458         skinframe->stain = NULL;
3459         skinframe->merged = NULL;
3460         skinframe->base = NULL;
3461         skinframe->pants = NULL;
3462         skinframe->shirt = NULL;
3463         skinframe->nmap = NULL;
3464         skinframe->gloss = NULL;
3465         skinframe->glow = NULL;
3466         skinframe->fog = NULL;
3467         skinframe->reflect = NULL;
3468         skinframe->hasalpha = false;
3469
3470         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3471         if (!skindata)
3472                 return NULL;
3473
3474         if (developer_loading.integer)
3475                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3476
3477         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3478         {
3479                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3480                 temp2 = temp1 + width * height * 4;
3481                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3482                 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);
3483                 Mem_Free(temp1);
3484         }
3485         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3486         if (textureflags & TEXF_ALPHA)
3487         {
3488                 for (i = 3;i < width * height * 4;i += 4)
3489                 {
3490                         if (skindata[i] < 255)
3491                         {
3492                                 skinframe->hasalpha = true;
3493                                 break;
3494                         }
3495                 }
3496                 if (r_loadfog && skinframe->hasalpha)
3497                 {
3498                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3499                         memcpy(fogpixels, skindata, width * height * 4);
3500                         for (i = 0;i < width * height * 4;i += 4)
3501                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3502                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3503                         Mem_Free(fogpixels);
3504                 }
3505         }
3506
3507         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3508         //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]);
3509
3510         return skinframe;
3511 }
3512
3513 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3514 {
3515         int i;
3516         int featuresmask;
3517         skinframe_t *skinframe;
3518
3519         if (cls.state == ca_dedicated)
3520                 return NULL;
3521
3522         // if already loaded just return it, otherwise make a new skinframe
3523         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3524         if (skinframe && skinframe->base)
3525                 return skinframe;
3526
3527         skinframe->stain = NULL;
3528         skinframe->merged = NULL;
3529         skinframe->base = NULL;
3530         skinframe->pants = NULL;
3531         skinframe->shirt = NULL;
3532         skinframe->nmap = NULL;
3533         skinframe->gloss = NULL;
3534         skinframe->glow = NULL;
3535         skinframe->fog = NULL;
3536         skinframe->reflect = NULL;
3537         skinframe->hasalpha = false;
3538
3539         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3540         if (!skindata)
3541                 return NULL;
3542
3543         if (developer_loading.integer)
3544                 Con_Printf("loading quake skin \"%s\"\n", name);
3545
3546         // 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)
3547         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3548         memcpy(skinframe->qpixels, skindata, width*height);
3549         skinframe->qwidth = width;
3550         skinframe->qheight = height;
3551
3552         featuresmask = 0;
3553         for (i = 0;i < width * height;i++)
3554                 featuresmask |= palette_featureflags[skindata[i]];
3555
3556         skinframe->hasalpha = false;
3557         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3558         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3559         skinframe->qgeneratemerged = true;
3560         skinframe->qgeneratebase = skinframe->qhascolormapping;
3561         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3562
3563         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3564         //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]);
3565
3566         return skinframe;
3567 }
3568
3569 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3570 {
3571         int width;
3572         int height;
3573         unsigned char *skindata;
3574
3575         if (!skinframe->qpixels)
3576                 return;
3577
3578         if (!skinframe->qhascolormapping)
3579                 colormapped = false;
3580
3581         if (colormapped)
3582         {
3583                 if (!skinframe->qgeneratebase)
3584                         return;
3585         }
3586         else
3587         {
3588                 if (!skinframe->qgeneratemerged)
3589                         return;
3590         }
3591
3592         width = skinframe->qwidth;
3593         height = skinframe->qheight;
3594         skindata = skinframe->qpixels;
3595
3596         if (skinframe->qgeneratenmap)
3597         {
3598                 unsigned char *temp1, *temp2;
3599                 skinframe->qgeneratenmap = false;
3600                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3601                 temp2 = temp1 + width * height * 4;
3602                 // use either a custom palette or the quake palette
3603                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3604                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3605                 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);
3606                 Mem_Free(temp1);
3607         }
3608
3609         if (skinframe->qgenerateglow)
3610         {
3611                 skinframe->qgenerateglow = false;
3612                 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
3613         }
3614
3615         if (colormapped)
3616         {
3617                 skinframe->qgeneratebase = false;
3618                 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);
3619                 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);
3620                 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);
3621         }
3622         else
3623         {
3624                 skinframe->qgeneratemerged = false;
3625                 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);
3626         }
3627
3628         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3629         {
3630                 Mem_Free(skinframe->qpixels);
3631                 skinframe->qpixels = NULL;
3632         }
3633 }
3634
3635 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)
3636 {
3637         int i;
3638         skinframe_t *skinframe;
3639
3640         if (cls.state == ca_dedicated)
3641                 return NULL;
3642
3643         // if already loaded just return it, otherwise make a new skinframe
3644         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3645         if (skinframe && skinframe->base)
3646                 return skinframe;
3647
3648         skinframe->stain = NULL;
3649         skinframe->merged = NULL;
3650         skinframe->base = NULL;
3651         skinframe->pants = NULL;
3652         skinframe->shirt = NULL;
3653         skinframe->nmap = NULL;
3654         skinframe->gloss = NULL;
3655         skinframe->glow = NULL;
3656         skinframe->fog = NULL;
3657         skinframe->reflect = NULL;
3658         skinframe->hasalpha = false;
3659
3660         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3661         if (!skindata)
3662                 return NULL;
3663
3664         if (developer_loading.integer)
3665                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3666
3667         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3668         if (textureflags & TEXF_ALPHA)
3669         {
3670                 for (i = 0;i < width * height;i++)
3671                 {
3672                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3673                         {
3674                                 skinframe->hasalpha = true;
3675                                 break;
3676                         }
3677                 }
3678                 if (r_loadfog && skinframe->hasalpha)
3679                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3680         }
3681
3682         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3683         //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]);
3684
3685         return skinframe;
3686 }
3687
3688 skinframe_t *R_SkinFrame_LoadMissing(void)
3689 {
3690         skinframe_t *skinframe;
3691
3692         if (cls.state == ca_dedicated)
3693                 return NULL;
3694
3695         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3696         skinframe->stain = NULL;
3697         skinframe->merged = NULL;
3698         skinframe->base = NULL;
3699         skinframe->pants = NULL;
3700         skinframe->shirt = NULL;
3701         skinframe->nmap = NULL;
3702         skinframe->gloss = NULL;
3703         skinframe->glow = NULL;
3704         skinframe->fog = NULL;
3705         skinframe->reflect = NULL;
3706         skinframe->hasalpha = false;
3707
3708         skinframe->avgcolor[0] = rand() / RAND_MAX;
3709         skinframe->avgcolor[1] = rand() / RAND_MAX;
3710         skinframe->avgcolor[2] = rand() / RAND_MAX;
3711         skinframe->avgcolor[3] = 1;
3712
3713         return skinframe;
3714 }
3715
3716 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3717 typedef struct suffixinfo_s
3718 {
3719         const char *suffix;
3720         qboolean flipx, flipy, flipdiagonal;
3721 }
3722 suffixinfo_t;
3723 static suffixinfo_t suffix[3][6] =
3724 {
3725         {
3726                 {"px",   false, false, false},
3727                 {"nx",   false, false, false},
3728                 {"py",   false, false, false},
3729                 {"ny",   false, false, false},
3730                 {"pz",   false, false, false},
3731                 {"nz",   false, false, false}
3732         },
3733         {
3734                 {"posx", false, false, false},
3735                 {"negx", false, false, false},
3736                 {"posy", false, false, false},
3737                 {"negy", false, false, false},
3738                 {"posz", false, false, false},
3739                 {"negz", false, false, false}
3740         },
3741         {
3742                 {"rt",    true, false,  true},
3743                 {"lf",   false,  true,  true},
3744                 {"ft",    true,  true, false},
3745                 {"bk",   false, false, false},
3746                 {"up",    true, false,  true},
3747                 {"dn",    true, false,  true}
3748         }
3749 };
3750
3751 static int componentorder[4] = {0, 1, 2, 3};
3752
3753 rtexture_t *R_LoadCubemap(const char *basename)
3754 {
3755         int i, j, cubemapsize;
3756         unsigned char *cubemappixels, *image_buffer;
3757         rtexture_t *cubemaptexture;
3758         char name[256];
3759         // must start 0 so the first loadimagepixels has no requested width/height
3760         cubemapsize = 0;
3761         cubemappixels = NULL;
3762         cubemaptexture = NULL;
3763         // keep trying different suffix groups (posx, px, rt) until one loads
3764         for (j = 0;j < 3 && !cubemappixels;j++)
3765         {
3766                 // load the 6 images in the suffix group
3767                 for (i = 0;i < 6;i++)
3768                 {
3769                         // generate an image name based on the base and and suffix
3770                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3771                         // load it
3772                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3773                         {
3774                                 // an image loaded, make sure width and height are equal
3775                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3776                                 {
3777                                         // if this is the first image to load successfully, allocate the cubemap memory
3778                                         if (!cubemappixels && image_width >= 1)
3779                                         {
3780                                                 cubemapsize = image_width;
3781                                                 // note this clears to black, so unavailable sides are black
3782                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3783                                         }
3784                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3785                                         if (cubemappixels)
3786                                                 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);
3787                                 }
3788                                 else
3789                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3790                                 // free the image
3791                                 Mem_Free(image_buffer);
3792                         }
3793                 }
3794         }
3795         // if a cubemap loaded, upload it
3796         if (cubemappixels)
3797         {
3798                 if (developer_loading.integer)
3799                         Con_Printf("loading cubemap \"%s\"\n", basename);
3800
3801                 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);
3802                 Mem_Free(cubemappixels);
3803         }
3804         else
3805         {
3806                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3807                 if (developer_loading.integer)
3808                 {
3809                         Con_Printf("(tried tried images ");
3810                         for (j = 0;j < 3;j++)
3811                                 for (i = 0;i < 6;i++)
3812                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3813                         Con_Print(" and was unable to find any of them).\n");
3814                 }
3815         }
3816         return cubemaptexture;
3817 }
3818
3819 rtexture_t *R_GetCubemap(const char *basename)
3820 {
3821         int i;
3822         for (i = 0;i < r_texture_numcubemaps;i++)
3823                 if (r_texture_cubemaps[i] != NULL)
3824                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3825                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3826         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3827                 return r_texture_whitecube;
3828         r_texture_numcubemaps++;
3829         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3830         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3831         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3832         return r_texture_cubemaps[i]->texture;
3833 }
3834
3835 void R_FreeCubemap(const char *basename)
3836 {
3837         int i;
3838
3839         for (i = 0;i < r_texture_numcubemaps;i++)
3840         {
3841                 if (r_texture_cubemaps[i] != NULL)
3842                 {
3843                         if (r_texture_cubemaps[i]->texture)
3844                         {
3845                                 if (developer_loading.integer)
3846                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3847                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3848                                 Mem_Free(r_texture_cubemaps[i]);
3849                                 r_texture_cubemaps[i] = NULL;
3850                         }
3851                 }
3852         }
3853 }
3854
3855 void R_FreeCubemaps(void)
3856 {
3857         int i;
3858         for (i = 0;i < r_texture_numcubemaps;i++)
3859         {
3860                 if (developer_loading.integer)
3861                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3862                 if (r_texture_cubemaps[i] != NULL)
3863                 {
3864                         if (r_texture_cubemaps[i]->texture)
3865                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3866                         Mem_Free(r_texture_cubemaps[i]);
3867                 }
3868         }
3869         r_texture_numcubemaps = 0;
3870 }
3871
3872 void R_Main_FreeViewCache(void)
3873 {
3874         if (r_refdef.viewcache.entityvisible)
3875                 Mem_Free(r_refdef.viewcache.entityvisible);
3876         if (r_refdef.viewcache.world_pvsbits)
3877                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3878         if (r_refdef.viewcache.world_leafvisible)
3879                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3880         if (r_refdef.viewcache.world_surfacevisible)
3881                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3882         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3883 }
3884
3885 void R_Main_ResizeViewCache(void)
3886 {
3887         int numentities = r_refdef.scene.numentities;
3888         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3889         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3890         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3891         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3892         if (r_refdef.viewcache.maxentities < numentities)
3893         {
3894                 r_refdef.viewcache.maxentities = numentities;
3895                 if (r_refdef.viewcache.entityvisible)
3896                         Mem_Free(r_refdef.viewcache.entityvisible);
3897                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3898         }
3899         if (r_refdef.viewcache.world_numclusters != numclusters)
3900         {
3901                 r_refdef.viewcache.world_numclusters = numclusters;
3902                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3903                 if (r_refdef.viewcache.world_pvsbits)
3904                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3905                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3906         }
3907         if (r_refdef.viewcache.world_numleafs != numleafs)
3908         {
3909                 r_refdef.viewcache.world_numleafs = numleafs;
3910                 if (r_refdef.viewcache.world_leafvisible)
3911                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3912                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3913         }
3914         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3915         {
3916                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3917                 if (r_refdef.viewcache.world_surfacevisible)
3918                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3919                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3920         }
3921 }
3922
3923 extern rtexture_t *loadingscreentexture;
3924 void gl_main_start(void)
3925 {
3926         loadingscreentexture = NULL;
3927         r_texture_blanknormalmap = NULL;
3928         r_texture_white = NULL;
3929         r_texture_grey128 = NULL;
3930         r_texture_black = NULL;
3931         r_texture_whitecube = NULL;
3932         r_texture_normalizationcube = NULL;
3933         r_texture_fogattenuation = NULL;
3934         r_texture_fogheighttexture = NULL;
3935         r_texture_gammaramps = NULL;
3936         r_texture_numcubemaps = 0;
3937
3938         r_loaddds = r_texture_dds_load.integer != 0;
3939         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3940
3941         switch(vid.renderpath)
3942         {
3943         case RENDERPATH_GL20:
3944         case RENDERPATH_D3D9:
3945         case RENDERPATH_D3D10:
3946         case RENDERPATH_D3D11:
3947         case RENDERPATH_SOFT:
3948         case RENDERPATH_GLES2:
3949                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3950                 Cvar_SetValueQuick(&gl_combine, 1);
3951                 Cvar_SetValueQuick(&r_glsl, 1);
3952                 r_loadnormalmap = true;
3953                 r_loadgloss = true;
3954                 r_loadfog = false;
3955                 break;
3956         case RENDERPATH_GL13:
3957         case RENDERPATH_GLES1:
3958                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3959                 Cvar_SetValueQuick(&gl_combine, 1);
3960                 Cvar_SetValueQuick(&r_glsl, 0);
3961                 r_loadnormalmap = false;
3962                 r_loadgloss = false;
3963                 r_loadfog = true;
3964                 break;
3965         case RENDERPATH_GL11:
3966                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3967                 Cvar_SetValueQuick(&gl_combine, 0);
3968                 Cvar_SetValueQuick(&r_glsl, 0);
3969                 r_loadnormalmap = false;
3970                 r_loadgloss = false;
3971                 r_loadfog = true;
3972                 break;
3973         }
3974
3975         R_AnimCache_Free();
3976         R_FrameData_Reset();
3977
3978         r_numqueries = 0;
3979         r_maxqueries = 0;
3980         memset(r_queries, 0, sizeof(r_queries));
3981
3982         r_qwskincache = NULL;
3983         r_qwskincache_size = 0;
3984
3985         // due to caching of texture_t references, the collision cache must be reset
3986         Collision_Cache_Reset(true);
3987
3988         // set up r_skinframe loading system for textures
3989         memset(&r_skinframe, 0, sizeof(r_skinframe));
3990         r_skinframe.loadsequence = 1;
3991         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
3992
3993         r_main_texturepool = R_AllocTexturePool();
3994         R_BuildBlankTextures();
3995         R_BuildNoTexture();
3996         if (vid.support.arb_texture_cube_map)
3997         {
3998                 R_BuildWhiteCube();
3999                 R_BuildNormalizationCube();
4000         }
4001         r_texture_fogattenuation = NULL;
4002         r_texture_fogheighttexture = NULL;
4003         r_texture_gammaramps = NULL;
4004         //r_texture_fogintensity = NULL;
4005         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4006         memset(&r_waterstate, 0, sizeof(r_waterstate));
4007         r_glsl_permutation = NULL;
4008         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4009         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4010         glslshaderstring = NULL;
4011 #ifdef SUPPORTD3D
4012         r_hlsl_permutation = NULL;
4013         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4014         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4015 #endif
4016         hlslshaderstring = NULL;
4017         memset(&r_svbsp, 0, sizeof (r_svbsp));
4018
4019         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4020         r_texture_numcubemaps = 0;
4021
4022         r_refdef.fogmasktable_density = 0;
4023 }
4024
4025 void gl_main_shutdown(void)
4026 {
4027         R_AnimCache_Free();
4028         R_FrameData_Reset();
4029
4030         R_Main_FreeViewCache();
4031
4032         switch(vid.renderpath)
4033         {
4034         case RENDERPATH_GL11:
4035         case RENDERPATH_GL13:
4036         case RENDERPATH_GL20:
4037         case RENDERPATH_GLES1:
4038         case RENDERPATH_GLES2:
4039                 if (r_maxqueries)
4040                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4041                 break;
4042         case RENDERPATH_D3D9:
4043                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4044                 break;
4045         case RENDERPATH_D3D10:
4046                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4047                 break;
4048         case RENDERPATH_D3D11:
4049                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4050                 break;
4051         case RENDERPATH_SOFT:
4052                 break;
4053         }
4054
4055         r_numqueries = 0;
4056         r_maxqueries = 0;
4057         memset(r_queries, 0, sizeof(r_queries));
4058
4059         r_qwskincache = NULL;
4060         r_qwskincache_size = 0;
4061
4062         // clear out the r_skinframe state
4063         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4064         memset(&r_skinframe, 0, sizeof(r_skinframe));
4065
4066         if (r_svbsp.nodes)
4067                 Mem_Free(r_svbsp.nodes);
4068         memset(&r_svbsp, 0, sizeof (r_svbsp));
4069         R_FreeTexturePool(&r_main_texturepool);
4070         loadingscreentexture = NULL;
4071         r_texture_blanknormalmap = NULL;
4072         r_texture_white = NULL;
4073         r_texture_grey128 = NULL;
4074         r_texture_black = NULL;
4075         r_texture_whitecube = NULL;
4076         r_texture_normalizationcube = NULL;
4077         r_texture_fogattenuation = NULL;
4078         r_texture_fogheighttexture = NULL;
4079         r_texture_gammaramps = NULL;
4080         r_texture_numcubemaps = 0;
4081         //r_texture_fogintensity = NULL;
4082         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4083         memset(&r_waterstate, 0, sizeof(r_waterstate));
4084         R_GLSL_Restart_f();
4085
4086         r_glsl_permutation = NULL;
4087         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4088         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4089         glslshaderstring = NULL;
4090 #ifdef SUPPORTD3D
4091         r_hlsl_permutation = NULL;
4092         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4093         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4094 #endif
4095         hlslshaderstring = NULL;
4096 }
4097
4098 extern void CL_ParseEntityLump(char *entitystring);
4099 void gl_main_newmap(void)
4100 {
4101         // FIXME: move this code to client
4102         char *entities, entname[MAX_QPATH];
4103         if (r_qwskincache)
4104                 Mem_Free(r_qwskincache);
4105         r_qwskincache = NULL;
4106         r_qwskincache_size = 0;
4107         if (cl.worldmodel)
4108         {
4109                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4110                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4111                 {
4112                         CL_ParseEntityLump(entities);
4113                         Mem_Free(entities);
4114                         return;
4115                 }
4116                 if (cl.worldmodel->brush.entities)
4117                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4118         }
4119         R_Main_FreeViewCache();
4120
4121         R_FrameData_Reset();
4122 }
4123
4124 void GL_Main_Init(void)
4125 {
4126         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4127
4128         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4129         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4130         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4131         if (gamemode == GAME_NEHAHRA)
4132         {
4133                 Cvar_RegisterVariable (&gl_fogenable);
4134                 Cvar_RegisterVariable (&gl_fogdensity);
4135                 Cvar_RegisterVariable (&gl_fogred);
4136                 Cvar_RegisterVariable (&gl_foggreen);
4137                 Cvar_RegisterVariable (&gl_fogblue);
4138                 Cvar_RegisterVariable (&gl_fogstart);
4139                 Cvar_RegisterVariable (&gl_fogend);
4140                 Cvar_RegisterVariable (&gl_skyclip);
4141         }
4142         Cvar_RegisterVariable(&r_motionblur);
4143         Cvar_RegisterVariable(&r_damageblur);
4144         Cvar_RegisterVariable(&r_motionblur_averaging);
4145         Cvar_RegisterVariable(&r_motionblur_randomize);
4146         Cvar_RegisterVariable(&r_motionblur_minblur);
4147         Cvar_RegisterVariable(&r_motionblur_maxblur);
4148         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4149         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4150         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4151         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4152         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4153         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4154         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4155         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4156         Cvar_RegisterVariable(&r_equalize_entities_by);
4157         Cvar_RegisterVariable(&r_equalize_entities_to);
4158         Cvar_RegisterVariable(&r_depthfirst);
4159         Cvar_RegisterVariable(&r_useinfinitefarclip);
4160         Cvar_RegisterVariable(&r_farclip_base);
4161         Cvar_RegisterVariable(&r_farclip_world);
4162         Cvar_RegisterVariable(&r_nearclip);
4163         Cvar_RegisterVariable(&r_deformvertexes);
4164         Cvar_RegisterVariable(&r_transparent);
4165         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4166         Cvar_RegisterVariable(&r_showoverdraw);
4167         Cvar_RegisterVariable(&r_showbboxes);
4168         Cvar_RegisterVariable(&r_showsurfaces);
4169         Cvar_RegisterVariable(&r_showtris);
4170         Cvar_RegisterVariable(&r_shownormals);
4171         Cvar_RegisterVariable(&r_showlighting);
4172         Cvar_RegisterVariable(&r_showshadowvolumes);
4173         Cvar_RegisterVariable(&r_showcollisionbrushes);
4174         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4175         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4176         Cvar_RegisterVariable(&r_showdisabledepthtest);
4177         Cvar_RegisterVariable(&r_drawportals);
4178         Cvar_RegisterVariable(&r_drawentities);
4179         Cvar_RegisterVariable(&r_draw2d);
4180         Cvar_RegisterVariable(&r_drawworld);
4181         Cvar_RegisterVariable(&r_cullentities_trace);
4182         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4183         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4184         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4185         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4186         Cvar_RegisterVariable(&r_drawviewmodel);
4187         Cvar_RegisterVariable(&r_drawexteriormodel);
4188         Cvar_RegisterVariable(&r_speeds);
4189         Cvar_RegisterVariable(&r_fullbrights);
4190         Cvar_RegisterVariable(&r_wateralpha);
4191         Cvar_RegisterVariable(&r_dynamic);
4192         Cvar_RegisterVariable(&r_fakelight);
4193         Cvar_RegisterVariable(&r_fakelight_intensity);
4194         Cvar_RegisterVariable(&r_fullbright);
4195         Cvar_RegisterVariable(&r_shadows);
4196         Cvar_RegisterVariable(&r_shadows_darken);
4197         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4198         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4199         Cvar_RegisterVariable(&r_shadows_throwdistance);
4200         Cvar_RegisterVariable(&r_shadows_throwdirection);
4201         Cvar_RegisterVariable(&r_shadows_focus);
4202         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4203         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4204         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4205         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4206         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4207         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4208         Cvar_RegisterVariable(&r_fog_exp2);
4209         Cvar_RegisterVariable(&r_fog_clear);
4210         Cvar_RegisterVariable(&r_drawfog);
4211         Cvar_RegisterVariable(&r_transparentdepthmasking);
4212         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4213         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4214         Cvar_RegisterVariable(&r_texture_dds_load);
4215         Cvar_RegisterVariable(&r_texture_dds_save);
4216         Cvar_RegisterVariable(&r_textureunits);
4217         Cvar_RegisterVariable(&gl_combine);
4218         Cvar_RegisterVariable(&r_viewfbo);
4219         Cvar_RegisterVariable(&r_viewscale);
4220         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4221         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4222         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4223         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4224         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4225         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4226         Cvar_RegisterVariable(&r_glsl);
4227         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4228         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4229         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4230         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4231         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4232         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4233         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4234         Cvar_RegisterVariable(&r_glsl_postprocess);
4235         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4236         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4237         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4238         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4239         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4240         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4241         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4242         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4243
4244         Cvar_RegisterVariable(&r_water);
4245         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4246         Cvar_RegisterVariable(&r_water_clippingplanebias);
4247         Cvar_RegisterVariable(&r_water_refractdistort);
4248         Cvar_RegisterVariable(&r_water_reflectdistort);
4249         Cvar_RegisterVariable(&r_water_scissormode);
4250         Cvar_RegisterVariable(&r_water_lowquality);
4251
4252         Cvar_RegisterVariable(&r_lerpsprites);
4253         Cvar_RegisterVariable(&r_lerpmodels);
4254         Cvar_RegisterVariable(&r_lerplightstyles);
4255         Cvar_RegisterVariable(&r_waterscroll);
4256         Cvar_RegisterVariable(&r_bloom);
4257         Cvar_RegisterVariable(&r_bloom_colorscale);
4258         Cvar_RegisterVariable(&r_bloom_brighten);
4259         Cvar_RegisterVariable(&r_bloom_blur);
4260         Cvar_RegisterVariable(&r_bloom_resolution);
4261         Cvar_RegisterVariable(&r_bloom_colorexponent);
4262         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4263         Cvar_RegisterVariable(&r_hdr);
4264         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4265         Cvar_RegisterVariable(&r_hdr_glowintensity);
4266         Cvar_RegisterVariable(&r_hdr_range);
4267         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4268         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4269         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4270         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4271         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4272         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4273         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4274         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4275         Cvar_RegisterVariable(&developer_texturelogging);
4276         Cvar_RegisterVariable(&gl_lightmaps);
4277         Cvar_RegisterVariable(&r_test);
4278         Cvar_RegisterVariable(&r_glsl_saturation);
4279         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4280         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4281         Cvar_RegisterVariable(&r_framedatasize);
4282         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4283                 Cvar_SetValue("r_fullbrights", 0);
4284         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4285 }
4286
4287 extern void R_Textures_Init(void);
4288 extern void GL_Draw_Init(void);
4289 extern void GL_Main_Init(void);
4290 extern void R_Shadow_Init(void);
4291 extern void R_Sky_Init(void);
4292 extern void GL_Surf_Init(void);
4293 extern void R_Particles_Init(void);
4294 extern void R_Explosion_Init(void);
4295 extern void gl_backend_init(void);
4296 extern void Sbar_Init(void);
4297 extern void R_LightningBeams_Init(void);
4298 extern void Mod_RenderInit(void);
4299 extern void Font_Init(void);
4300
4301 void Render_Init(void)
4302 {
4303         gl_backend_init();
4304         R_Textures_Init();
4305         GL_Main_Init();
4306         Font_Init();
4307         GL_Draw_Init();
4308         R_Shadow_Init();
4309         R_Sky_Init();
4310         GL_Surf_Init();
4311         Sbar_Init();
4312         R_Particles_Init();
4313         R_Explosion_Init();
4314         R_LightningBeams_Init();
4315         Mod_RenderInit();
4316 }
4317
4318 /*
4319 ===============
4320 GL_Init
4321 ===============
4322 */
4323 extern char *ENGINE_EXTENSIONS;
4324 void GL_Init (void)
4325 {
4326         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4327         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4328         gl_version = (const char *)qglGetString(GL_VERSION);
4329         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4330
4331         if (!gl_extensions)
4332                 gl_extensions = "";
4333         if (!gl_platformextensions)
4334                 gl_platformextensions = "";
4335
4336         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4337         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4338         Con_Printf("GL_VERSION: %s\n", gl_version);
4339         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4340         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4341
4342         VID_CheckExtensions();
4343
4344         // LordHavoc: report supported extensions
4345         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4346
4347         // clear to black (loading plaque will be seen over this)
4348         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4349 }
4350
4351 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4352 {
4353         int i;
4354         mplane_t *p;
4355         if (r_trippy.integer)
4356                 return false;
4357         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4358         {
4359                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4360                 if (i == 4)
4361                         continue;
4362                 p = r_refdef.view.frustum + i;
4363                 switch(p->signbits)
4364                 {
4365                 default:
4366                 case 0:
4367                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4368                                 return true;
4369                         break;
4370                 case 1:
4371                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4372                                 return true;
4373                         break;
4374                 case 2:
4375                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4376                                 return true;
4377                         break;
4378                 case 3:
4379                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4380                                 return true;
4381                         break;
4382                 case 4:
4383                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4384                                 return true;
4385                         break;
4386                 case 5:
4387                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4388                                 return true;
4389                         break;
4390                 case 6:
4391                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4392                                 return true;
4393                         break;
4394                 case 7:
4395                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 }
4399         }
4400         return false;
4401 }
4402
4403 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4404 {
4405         int i;
4406         const mplane_t *p;
4407         if (r_trippy.integer)
4408                 return false;
4409         for (i = 0;i < numplanes;i++)
4410         {
4411                 p = planes + i;
4412                 switch(p->signbits)
4413                 {
4414                 default:
4415                 case 0:
4416                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4417                                 return true;
4418                         break;
4419                 case 1:
4420                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4421                                 return true;
4422                         break;
4423                 case 2:
4424                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4425                                 return true;
4426                         break;
4427                 case 3:
4428                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 4:
4432                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 5:
4436                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 case 6:
4440                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 7:
4444                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 }
4448         }
4449         return false;
4450 }
4451
4452 //==================================================================================
4453
4454 // LordHavoc: this stores temporary data used within the same frame
4455
4456 typedef struct r_framedata_mem_s
4457 {
4458         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4459         size_t size; // how much usable space
4460         size_t current; // how much space in use
4461         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4462         size_t wantedsize; // how much space was allocated
4463         unsigned char *data; // start of real data (16byte aligned)
4464 }
4465 r_framedata_mem_t;
4466
4467 static r_framedata_mem_t *r_framedata_mem;
4468
4469 void R_FrameData_Reset(void)
4470 {
4471         while (r_framedata_mem)
4472         {
4473                 r_framedata_mem_t *next = r_framedata_mem->purge;
4474                 Mem_Free(r_framedata_mem);
4475                 r_framedata_mem = next;
4476         }
4477 }
4478
4479 void R_FrameData_Resize(void)
4480 {
4481         size_t wantedsize;
4482         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4483         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4484         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4485         {
4486                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4487                 newmem->wantedsize = wantedsize;
4488                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4489                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4490                 newmem->current = 0;
4491                 newmem->mark = 0;
4492                 newmem->purge = r_framedata_mem;
4493                 r_framedata_mem = newmem;
4494         }
4495 }
4496
4497 void R_FrameData_NewFrame(void)
4498 {
4499         R_FrameData_Resize();
4500         if (!r_framedata_mem)
4501                 return;
4502         // if we ran out of space on the last frame, free the old memory now
4503         while (r_framedata_mem->purge)
4504         {
4505                 // repeatedly remove the second item in the list, leaving only head
4506                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4507                 Mem_Free(r_framedata_mem->purge);
4508                 r_framedata_mem->purge = next;
4509         }
4510         // reset the current mem pointer
4511         r_framedata_mem->current = 0;
4512         r_framedata_mem->mark = 0;
4513 }
4514
4515 void *R_FrameData_Alloc(size_t size)
4516 {
4517         void *data;
4518
4519         // align to 16 byte boundary - the data pointer is already aligned, so we
4520         // only need to ensure the size of every allocation is also aligned
4521         size = (size + 15) & ~15;
4522
4523         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4524         {
4525                 // emergency - we ran out of space, allocate more memory
4526                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4527                 R_FrameData_Resize();
4528         }
4529
4530         data = r_framedata_mem->data + r_framedata_mem->current;
4531         r_framedata_mem->current += size;
4532
4533         // count the usage for stats
4534         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4535         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4536
4537         return (void *)data;
4538 }
4539
4540 void *R_FrameData_Store(size_t size, void *data)
4541 {
4542         void *d = R_FrameData_Alloc(size);
4543         if (d && data)
4544                 memcpy(d, data, size);
4545         return d;
4546 }
4547
4548 void R_FrameData_SetMark(void)
4549 {
4550         if (!r_framedata_mem)
4551                 return;
4552         r_framedata_mem->mark = r_framedata_mem->current;
4553 }
4554
4555 void R_FrameData_ReturnToMark(void)
4556 {
4557         if (!r_framedata_mem)
4558                 return;
4559         r_framedata_mem->current = r_framedata_mem->mark;
4560 }
4561
4562 //==================================================================================
4563
4564 // LordHavoc: animcache originally written by Echon, rewritten since then
4565
4566 /**
4567  * Animation cache prevents re-generating mesh data for an animated model
4568  * multiple times in one frame for lighting, shadowing, reflections, etc.
4569  */
4570
4571 void R_AnimCache_Free(void)
4572 {
4573 }
4574
4575 void R_AnimCache_ClearCache(void)
4576 {
4577         int i;
4578         entity_render_t *ent;
4579
4580         for (i = 0;i < r_refdef.scene.numentities;i++)
4581         {
4582                 ent = r_refdef.scene.entities[i];
4583                 ent->animcache_vertex3f = NULL;
4584                 ent->animcache_normal3f = NULL;
4585                 ent->animcache_svector3f = NULL;
4586                 ent->animcache_tvector3f = NULL;
4587                 ent->animcache_vertexmesh = NULL;
4588                 ent->animcache_vertex3fbuffer = NULL;
4589                 ent->animcache_vertexmeshbuffer = NULL;
4590         }
4591 }
4592
4593 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4594 {
4595         int i;
4596
4597         // check if we need the meshbuffers
4598         if (!vid.useinterleavedarrays)
4599                 return;
4600
4601         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4602                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4603         // TODO: upload vertex3f buffer?
4604         if (ent->animcache_vertexmesh)
4605         {
4606                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4607                 for (i = 0;i < numvertices;i++)
4608                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4609                 if (ent->animcache_svector3f)
4610                         for (i = 0;i < numvertices;i++)
4611                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4612                 if (ent->animcache_tvector3f)
4613                         for (i = 0;i < numvertices;i++)
4614                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4615                 if (ent->animcache_normal3f)
4616                         for (i = 0;i < numvertices;i++)
4617                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4618                 // TODO: upload vertexmeshbuffer?
4619         }
4620 }
4621
4622 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4623 {
4624         dp_model_t *model = ent->model;
4625         int numvertices;
4626         // see if it's already cached this frame
4627         if (ent->animcache_vertex3f)
4628         {
4629                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4630                 if (wantnormals || wanttangents)
4631                 {
4632                         if (ent->animcache_normal3f)
4633                                 wantnormals = false;
4634                         if (ent->animcache_svector3f)
4635                                 wanttangents = false;
4636                         if (wantnormals || wanttangents)
4637                         {
4638                                 numvertices = model->surfmesh.num_vertices;
4639                                 if (wantnormals)
4640                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4641                                 if (wanttangents)
4642                                 {
4643                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4644                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4645                                 }
4646                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4647                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4648                         }
4649                 }
4650         }
4651         else
4652         {
4653                 // see if this ent is worth caching
4654                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4655                         return false;
4656                 // get some memory for this entity and generate mesh data
4657                 numvertices = model->surfmesh.num_vertices;
4658                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4659                 if (wantnormals)
4660                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4661                 if (wanttangents)
4662                 {
4663                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4664                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4665                 }
4666                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4667                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4668         }
4669         return true;
4670 }
4671
4672 void R_AnimCache_CacheVisibleEntities(void)
4673 {
4674         int i;
4675         qboolean wantnormals = true;
4676         qboolean wanttangents = !r_showsurfaces.integer;
4677
4678         switch(vid.renderpath)
4679         {
4680         case RENDERPATH_GL20:
4681         case RENDERPATH_D3D9:
4682         case RENDERPATH_D3D10:
4683         case RENDERPATH_D3D11:
4684         case RENDERPATH_GLES2:
4685                 break;
4686         case RENDERPATH_GL11:
4687         case RENDERPATH_GL13:
4688         case RENDERPATH_GLES1:
4689                 wanttangents = false;
4690                 break;
4691         case RENDERPATH_SOFT:
4692                 break;
4693         }
4694
4695         if (r_shownormals.integer)
4696                 wanttangents = wantnormals = true;
4697
4698         // TODO: thread this
4699         // NOTE: R_PrepareRTLights() also caches entities
4700
4701         for (i = 0;i < r_refdef.scene.numentities;i++)
4702                 if (r_refdef.viewcache.entityvisible[i])
4703                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4704 }
4705
4706 //==================================================================================
4707
4708 extern cvar_t r_overheadsprites_pushback;
4709
4710 static void R_View_UpdateEntityLighting (void)
4711 {
4712         int i;
4713         entity_render_t *ent;
4714         vec3_t tempdiffusenormal, avg;
4715         vec_t f, fa, fd, fdd;
4716         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4717
4718         for (i = 0;i < r_refdef.scene.numentities;i++)
4719         {
4720                 ent = r_refdef.scene.entities[i];
4721
4722                 // skip unseen models
4723                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4724                         continue;
4725
4726                 // skip bsp models
4727                 if (ent->model && ent->model->brush.num_leafs)
4728                 {
4729                         // TODO: use modellight for r_ambient settings on world?
4730                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4731                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4732                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4733                         continue;
4734                 }
4735
4736                 // fetch the lighting from the worldmodel data
4737                 VectorClear(ent->modellight_ambient);
4738                 VectorClear(ent->modellight_diffuse);
4739                 VectorClear(tempdiffusenormal);
4740                 if (ent->flags & RENDER_LIGHT)
4741                 {
4742                         vec3_t org;
4743                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4744
4745                         // complete lightning for lit sprites
4746                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4747                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4748                         {
4749                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4750                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4751                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4752                         }
4753                         else
4754                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4755
4756                         if(ent->flags & RENDER_EQUALIZE)
4757                         {
4758                                 // first fix up ambient lighting...
4759                                 if(r_equalize_entities_minambient.value > 0)
4760                                 {
4761                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4762                                         if(fd > 0)
4763                                         {
4764                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4765                                                 if(fa < r_equalize_entities_minambient.value * fd)
4766                                                 {
4767                                                         // solve:
4768                                                         //   fa'/fd' = minambient
4769                                                         //   fa'+0.25*fd' = fa+0.25*fd
4770                                                         //   ...
4771                                                         //   fa' = fd' * minambient
4772                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4773                                                         //   ...
4774                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4775                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4776                                                         //   ...
4777                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4778                                                         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
4779                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4780                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4781                                                 }
4782                                         }
4783                                 }
4784
4785                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4786                                 {
4787                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4788                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4789                                         f = fa + 0.25 * fd;
4790                                         if(f > 0)
4791                                         {
4792                                                 // adjust brightness and saturation to target
4793                                                 avg[0] = avg[1] = avg[2] = fa / f;
4794                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4795                                                 avg[0] = avg[1] = avg[2] = fd / f;
4796                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4797                                         }
4798                                 }
4799                         }
4800                 }
4801                 else // highly rare
4802                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4803
4804                 // move the light direction into modelspace coordinates for lighting code
4805                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4806                 if(VectorLength2(ent->modellight_lightdir) == 0)
4807                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4808                 VectorNormalize(ent->modellight_lightdir);
4809         }
4810 }
4811
4812 #define MAX_LINEOFSIGHTTRACES 64
4813
4814 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4815 {
4816         int i;
4817         vec3_t boxmins, boxmaxs;
4818         vec3_t start;
4819         vec3_t end;
4820         dp_model_t *model = r_refdef.scene.worldmodel;
4821
4822         if (!model || !model->brush.TraceLineOfSight)
4823                 return true;
4824
4825         // expand the box a little
4826         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4827         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4828         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4829         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4830         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4831         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4832
4833         // return true if eye is inside enlarged box
4834         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4835                 return true;
4836
4837         // try center
4838         VectorCopy(eye, start);
4839         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4840         if (model->brush.TraceLineOfSight(model, start, end))
4841                 return true;
4842
4843         // try various random positions
4844         for (i = 0;i < numsamples;i++)
4845         {
4846                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4847                 if (model->brush.TraceLineOfSight(model, start, end))
4848                         return true;
4849         }
4850
4851         return false;
4852 }
4853
4854
4855 static void R_View_UpdateEntityVisible (void)
4856 {
4857         int i;
4858         int renderimask;
4859         int samples;
4860         entity_render_t *ent;
4861
4862         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4863                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4864                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4865                 :                                                          RENDER_EXTERIORMODEL;
4866         if (!r_drawviewmodel.integer)
4867                 renderimask |= RENDER_VIEWMODEL;
4868         if (!r_drawexteriormodel.integer)
4869                 renderimask |= RENDER_EXTERIORMODEL;
4870         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4871         {
4872                 // worldmodel can check visibility
4873                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4874                 for (i = 0;i < r_refdef.scene.numentities;i++)
4875                 {
4876                         ent = r_refdef.scene.entities[i];
4877                         if (!(ent->flags & renderimask))
4878                         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)))
4879                         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))
4880                                 r_refdef.viewcache.entityvisible[i] = true;
4881                 }
4882         }
4883         else
4884         {
4885                 // no worldmodel or it can't check visibility
4886                 for (i = 0;i < r_refdef.scene.numentities;i++)
4887                 {
4888                         ent = r_refdef.scene.entities[i];
4889                         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));
4890                 }
4891         }
4892         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4893                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4894         {
4895                 for (i = 0;i < r_refdef.scene.numentities;i++)
4896                 {
4897                         if (!r_refdef.viewcache.entityvisible[i])
4898                                 continue;
4899                         ent = r_refdef.scene.entities[i];
4900                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4901                         {
4902                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4903                                 if (samples < 0)
4904                                         continue; // temp entities do pvs only
4905                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4906                                         ent->last_trace_visibility = realtime;
4907                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4908                                         r_refdef.viewcache.entityvisible[i] = 0;
4909                         }
4910                 }
4911         }
4912 }
4913
4914 /// only used if skyrendermasked, and normally returns false
4915 int R_DrawBrushModelsSky (void)
4916 {
4917         int i, sky;
4918         entity_render_t *ent;
4919
4920         sky = false;
4921         for (i = 0;i < r_refdef.scene.numentities;i++)
4922         {
4923                 if (!r_refdef.viewcache.entityvisible[i])
4924                         continue;
4925                 ent = r_refdef.scene.entities[i];
4926                 if (!ent->model || !ent->model->DrawSky)
4927                         continue;
4928                 ent->model->DrawSky(ent);
4929                 sky = true;
4930         }
4931         return sky;
4932 }
4933
4934 static void R_DrawNoModel(entity_render_t *ent);
4935 static void R_DrawModels(void)
4936 {
4937         int i;
4938         entity_render_t *ent;
4939
4940         for (i = 0;i < r_refdef.scene.numentities;i++)
4941         {
4942                 if (!r_refdef.viewcache.entityvisible[i])
4943                         continue;
4944                 ent = r_refdef.scene.entities[i];
4945                 r_refdef.stats.entities++;
4946                 /*
4947                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4948                 {
4949                         vec3_t f, l, u, o;
4950                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4951                         Con_Printf("R_DrawModels\n");
4952                         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]);
4953                         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);
4954                         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);
4955                 }
4956                 */
4957                 if (ent->model && ent->model->Draw != NULL)
4958                         ent->model->Draw(ent);
4959                 else
4960                         R_DrawNoModel(ent);
4961         }
4962 }
4963
4964 static void R_DrawModelsDepth(void)
4965 {
4966         int i;
4967         entity_render_t *ent;
4968
4969         for (i = 0;i < r_refdef.scene.numentities;i++)
4970         {
4971                 if (!r_refdef.viewcache.entityvisible[i])
4972                         continue;
4973                 ent = r_refdef.scene.entities[i];
4974                 if (ent->model && ent->model->DrawDepth != NULL)
4975                         ent->model->DrawDepth(ent);
4976         }
4977 }
4978
4979 static void R_DrawModelsDebug(void)
4980 {
4981         int i;
4982         entity_render_t *ent;
4983
4984         for (i = 0;i < r_refdef.scene.numentities;i++)
4985         {
4986                 if (!r_refdef.viewcache.entityvisible[i])
4987                         continue;
4988                 ent = r_refdef.scene.entities[i];
4989                 if (ent->model && ent->model->DrawDebug != NULL)
4990                         ent->model->DrawDebug(ent);
4991         }
4992 }
4993
4994 static void R_DrawModelsAddWaterPlanes(void)
4995 {
4996         int i;
4997         entity_render_t *ent;
4998
4999         for (i = 0;i < r_refdef.scene.numentities;i++)
5000         {
5001                 if (!r_refdef.viewcache.entityvisible[i])
5002                         continue;
5003                 ent = r_refdef.scene.entities[i];
5004                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5005                         ent->model->DrawAddWaterPlanes(ent);
5006         }
5007 }
5008
5009 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5010 {
5011         if (r_hdr_irisadaptation.integer)
5012         {
5013                 vec3_t ambient;
5014                 vec3_t diffuse;
5015                 vec3_t diffusenormal;
5016                 vec_t brightness;
5017                 vec_t goal;
5018                 vec_t current;
5019                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5020                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5021                 brightness = max(0.0000001f, brightness);
5022                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5023                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5024                 current = r_hdr_irisadaptation_value.value;
5025                 if (current < goal)
5026                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5027                 else if (current > goal)
5028                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5029                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5030                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5031         }
5032         else if (r_hdr_irisadaptation_value.value != 1.0f)
5033                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5034 }
5035
5036 static void R_View_SetFrustum(const int *scissor)
5037 {
5038         int i;
5039         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5040         vec3_t forward, left, up, origin, v;
5041
5042         if(scissor)
5043         {
5044                 // flipped x coordinates (because x points left here)
5045                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5046                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5047
5048                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5049                 switch(vid.renderpath)
5050                 {
5051                         case RENDERPATH_D3D9:
5052                         case RENDERPATH_D3D10:
5053                         case RENDERPATH_D3D11:
5054                                 // non-flipped y coordinates
5055                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5056                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5057                                 break;
5058                         case RENDERPATH_SOFT:
5059                         case RENDERPATH_GL11:
5060                         case RENDERPATH_GL13:
5061                         case RENDERPATH_GL20:
5062                         case RENDERPATH_GLES1:
5063                         case RENDERPATH_GLES2:
5064                                 // non-flipped y coordinates
5065                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5066                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5067                                 break;
5068                 }
5069         }
5070
5071         // we can't trust r_refdef.view.forward and friends in reflected scenes
5072         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5073
5074 #if 0
5075         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5076         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5077         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5078         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5079         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5080         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5081         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5082         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5083         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5084         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5085         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5086         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5087 #endif
5088
5089 #if 0
5090         zNear = r_refdef.nearclip;
5091         nudge = 1.0 - 1.0 / (1<<23);
5092         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5093         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5094         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5095         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5096         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5097         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5098         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5099         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5100 #endif
5101
5102
5103
5104 #if 0
5105         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5106         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5107         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5108         r_refdef.view.frustum[0].dist = m[15] - m[12];
5109
5110         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5111         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5112         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5113         r_refdef.view.frustum[1].dist = m[15] + m[12];
5114
5115         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5116         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5117         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5118         r_refdef.view.frustum[2].dist = m[15] - m[13];
5119
5120         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5121         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5122         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5123         r_refdef.view.frustum[3].dist = m[15] + m[13];
5124
5125         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5126         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5127         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5128         r_refdef.view.frustum[4].dist = m[15] - m[14];
5129
5130         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5131         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5132         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5133         r_refdef.view.frustum[5].dist = m[15] + m[14];
5134 #endif
5135
5136         if (r_refdef.view.useperspective)
5137         {
5138                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5139                 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]);
5140                 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]);
5141                 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]);
5142                 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]);
5143
5144                 // then the normals from the corners relative to origin
5145                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5146                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5147                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5148                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5149
5150                 // in a NORMAL view, forward cross left == up
5151                 // in a REFLECTED view, forward cross left == down
5152                 // so our cross products above need to be adjusted for a left handed coordinate system
5153                 CrossProduct(forward, left, v);
5154                 if(DotProduct(v, up) < 0)
5155                 {
5156                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5157                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5158                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5159                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5160                 }
5161
5162                 // Leaving those out was a mistake, those were in the old code, and they
5163                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5164                 // I couldn't reproduce it after adding those normalizations. --blub
5165                 VectorNormalize(r_refdef.view.frustum[0].normal);
5166                 VectorNormalize(r_refdef.view.frustum[1].normal);
5167                 VectorNormalize(r_refdef.view.frustum[2].normal);
5168                 VectorNormalize(r_refdef.view.frustum[3].normal);
5169
5170                 // make the corners absolute
5171                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5172                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5173                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5174                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5175
5176                 // one more normal
5177                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5178
5179                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5180                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5181                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5182                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5183                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5184         }
5185         else
5186         {
5187                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5188                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5189                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5190                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5191                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5192                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5193                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5194                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5195                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5196                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5197         }
5198         r_refdef.view.numfrustumplanes = 5;
5199
5200         if (r_refdef.view.useclipplane)
5201         {
5202                 r_refdef.view.numfrustumplanes = 6;
5203                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5204         }
5205
5206         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5207                 PlaneClassify(r_refdef.view.frustum + i);
5208
5209         // LordHavoc: note to all quake engine coders, Quake had a special case
5210         // for 90 degrees which assumed a square view (wrong), so I removed it,
5211         // Quake2 has it disabled as well.
5212
5213         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5214         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5215         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5216         //PlaneClassify(&frustum[0]);
5217
5218         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5219         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5220         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5221         //PlaneClassify(&frustum[1]);
5222
5223         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5224         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5225         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5226         //PlaneClassify(&frustum[2]);
5227
5228         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5229         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5230         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5231         //PlaneClassify(&frustum[3]);
5232
5233         // nearclip plane
5234         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5235         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5236         //PlaneClassify(&frustum[4]);
5237 }
5238
5239 void R_View_UpdateWithScissor(const int *myscissor)
5240 {
5241         R_Main_ResizeViewCache();
5242         R_View_SetFrustum(myscissor);
5243         R_View_WorldVisibility(r_refdef.view.useclipplane);
5244         R_View_UpdateEntityVisible();
5245         R_View_UpdateEntityLighting();
5246 }
5247
5248 void R_View_Update(void)
5249 {
5250         R_Main_ResizeViewCache();
5251         R_View_SetFrustum(NULL);
5252         R_View_WorldVisibility(r_refdef.view.useclipplane);
5253         R_View_UpdateEntityVisible();
5254         R_View_UpdateEntityLighting();
5255 }
5256
5257 float viewscalefpsadjusted = 1.0f;
5258
5259 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5260 {
5261         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5262         scale = bound(0.03125f, scale, 1.0f);
5263         *outwidth = (int)ceil(width * scale);
5264         *outheight = (int)ceil(height * scale);
5265 }
5266
5267 void R_Mesh_SetMainRenderTargets(void)
5268 {
5269         if (r_bloomstate.fbo_framebuffer)
5270                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5271         else
5272                 R_Mesh_ResetRenderTargets();
5273 }
5274
5275 void R_SetupView(qboolean allowwaterclippingplane)
5276 {
5277         const float *customclipplane = NULL;
5278         float plane[4];
5279         int scaledwidth, scaledheight;
5280         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5281         {
5282                 // LordHavoc: couldn't figure out how to make this approach the
5283                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5284                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5285                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5286                         dist = r_refdef.view.clipplane.dist;
5287                 plane[0] = r_refdef.view.clipplane.normal[0];
5288                 plane[1] = r_refdef.view.clipplane.normal[1];
5289                 plane[2] = r_refdef.view.clipplane.normal[2];
5290                 plane[3] = -dist;
5291                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5292         }
5293
5294         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5295         if (!r_refdef.view.useperspective)
5296                 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);
5297         else if (vid.stencil && r_useinfinitefarclip.integer)
5298                 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);
5299         else
5300                 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);
5301         R_Mesh_SetMainRenderTargets();
5302         R_SetViewport(&r_refdef.view.viewport);
5303         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5304         {
5305                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5306                 float screenplane[4];
5307                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5308                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5309                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5310                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5311                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5312         }
5313 }
5314
5315 void R_EntityMatrix(const matrix4x4_t *matrix)
5316 {
5317         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5318         {
5319                 gl_modelmatrixchanged = false;
5320                 gl_modelmatrix = *matrix;
5321                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5322                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5323                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5324                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5325                 CHECKGLERROR
5326                 switch(vid.renderpath)
5327                 {
5328                 case RENDERPATH_D3D9:
5329 #ifdef SUPPORTD3D
5330                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5331                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5332 #endif
5333                         break;
5334                 case RENDERPATH_D3D10:
5335                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5336                         break;
5337                 case RENDERPATH_D3D11:
5338                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5339                         break;
5340                 case RENDERPATH_GL11:
5341                 case RENDERPATH_GL13:
5342                 case RENDERPATH_GLES1:
5343                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5344                         break;
5345                 case RENDERPATH_SOFT:
5346                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5347                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5348                         break;
5349                 case RENDERPATH_GL20:
5350                 case RENDERPATH_GLES2:
5351                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5352                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5353                         break;
5354                 }
5355         }
5356 }
5357
5358 void R_ResetViewRendering2D(void)
5359 {
5360         r_viewport_t viewport;
5361         DrawQ_Finish();
5362
5363         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5364         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);
5365         R_Mesh_ResetRenderTargets();
5366         R_SetViewport(&viewport);
5367         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5368         GL_Color(1, 1, 1, 1);
5369         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5370         GL_BlendFunc(GL_ONE, GL_ZERO);
5371         GL_ScissorTest(false);
5372         GL_DepthMask(false);
5373         GL_DepthRange(0, 1);
5374         GL_DepthTest(false);
5375         GL_DepthFunc(GL_LEQUAL);
5376         R_EntityMatrix(&identitymatrix);
5377         R_Mesh_ResetTextureState();
5378         GL_PolygonOffset(0, 0);
5379         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5380         switch(vid.renderpath)
5381         {
5382         case RENDERPATH_GL11:
5383         case RENDERPATH_GL13:
5384         case RENDERPATH_GL20:
5385         case RENDERPATH_GLES1:
5386         case RENDERPATH_GLES2:
5387                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5388                 break;
5389         case RENDERPATH_D3D9:
5390         case RENDERPATH_D3D10:
5391         case RENDERPATH_D3D11:
5392         case RENDERPATH_SOFT:
5393                 break;
5394         }
5395         GL_CullFace(GL_NONE);
5396 }
5397
5398 void R_ResetViewRendering3D(void)
5399 {
5400         DrawQ_Finish();
5401
5402         R_SetupView(true);
5403         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5404         GL_Color(1, 1, 1, 1);
5405         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5406         GL_BlendFunc(GL_ONE, GL_ZERO);
5407         GL_ScissorTest(true);
5408         GL_DepthMask(true);
5409         GL_DepthRange(0, 1);
5410         GL_DepthTest(true);
5411         GL_DepthFunc(GL_LEQUAL);
5412         R_EntityMatrix(&identitymatrix);
5413         R_Mesh_ResetTextureState();
5414         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5415         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5416         switch(vid.renderpath)
5417         {
5418         case RENDERPATH_GL11:
5419         case RENDERPATH_GL13:
5420         case RENDERPATH_GL20:
5421         case RENDERPATH_GLES1:
5422         case RENDERPATH_GLES2:
5423                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5424                 break;
5425         case RENDERPATH_D3D9:
5426         case RENDERPATH_D3D10:
5427         case RENDERPATH_D3D11:
5428         case RENDERPATH_SOFT:
5429                 break;
5430         }
5431         GL_CullFace(r_refdef.view.cullface_back);
5432 }
5433
5434 /*
5435 ================
5436 R_RenderView_UpdateViewVectors
5437 ================
5438 */
5439 static void R_RenderView_UpdateViewVectors(void)
5440 {
5441         // break apart the view matrix into vectors for various purposes
5442         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5443         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5444         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5445         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5446         // make an inverted copy of the view matrix for tracking sprites
5447         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5448 }
5449
5450 void R_RenderScene(void);
5451 void R_RenderWaterPlanes(void);
5452
5453 static void R_Water_StartFrame(void)
5454 {
5455         int i;
5456         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5457         r_waterstate_waterplane_t *p;
5458
5459         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5460                 return;
5461
5462         switch(vid.renderpath)
5463         {
5464         case RENDERPATH_GL20:
5465         case RENDERPATH_D3D9:
5466         case RENDERPATH_D3D10:
5467         case RENDERPATH_D3D11:
5468         case RENDERPATH_SOFT:
5469         case RENDERPATH_GLES2:
5470                 break;
5471         case RENDERPATH_GL11:
5472         case RENDERPATH_GL13:
5473         case RENDERPATH_GLES1:
5474                 return;
5475         }
5476
5477         // set waterwidth and waterheight to the water resolution that will be
5478         // used (often less than the screen resolution for faster rendering)
5479         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5480
5481         // calculate desired texture sizes
5482         // can't use water if the card does not support the texture size
5483         if (!r_water.integer || r_showsurfaces.integer)
5484                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5485         else if (vid.support.arb_texture_non_power_of_two)
5486         {
5487                 texturewidth = waterwidth;
5488                 textureheight = waterheight;
5489                 camerawidth = waterwidth;
5490                 cameraheight = waterheight;
5491         }
5492         else
5493         {
5494                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5495                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5496                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5497                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5498         }
5499
5500         // allocate textures as needed
5501         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5502         {
5503                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5504                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5505                 {
5506                         if (p->texture_refraction)
5507                                 R_FreeTexture(p->texture_refraction);
5508                         p->texture_refraction = NULL;
5509                         if (p->texture_reflection)
5510                                 R_FreeTexture(p->texture_reflection);
5511                         p->texture_reflection = NULL;
5512                         if (p->texture_camera)
5513                                 R_FreeTexture(p->texture_camera);
5514                         p->texture_camera = NULL;
5515                 }
5516                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5517                 r_waterstate.texturewidth = texturewidth;
5518                 r_waterstate.textureheight = textureheight;
5519                 r_waterstate.camerawidth = camerawidth;
5520                 r_waterstate.cameraheight = cameraheight;
5521         }
5522
5523         if (r_waterstate.texturewidth)
5524         {
5525                 int scaledwidth, scaledheight;
5526
5527                 r_waterstate.enabled = true;
5528
5529                 // when doing a reduced render (HDR) we want to use a smaller area
5530                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5531                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5532                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5533
5534                 // set up variables that will be used in shader setup
5535                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5536                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5537                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5538                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5539         }
5540
5541         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5542         r_waterstate.numwaterplanes = 0;
5543 }
5544
5545 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5546 {
5547         int triangleindex, planeindex;
5548         const int *e;
5549         vec3_t vert[3];
5550         vec3_t normal;
5551         vec3_t center;
5552         mplane_t plane;
5553         r_waterstate_waterplane_t *p;
5554         texture_t *t = R_GetCurrentTexture(surface->texture);
5555
5556         // just use the first triangle with a valid normal for any decisions
5557         VectorClear(normal);
5558         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5559         {
5560                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5561                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5562                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5563                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5564                 if (VectorLength2(normal) >= 0.001)
5565                         break;
5566         }
5567
5568         VectorCopy(normal, plane.normal);
5569         VectorNormalize(plane.normal);
5570         plane.dist = DotProduct(vert[0], plane.normal);
5571         PlaneClassify(&plane);
5572         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5573         {
5574                 // skip backfaces (except if nocullface is set)
5575                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5576                         return;
5577                 VectorNegate(plane.normal, plane.normal);
5578                 plane.dist *= -1;
5579                 PlaneClassify(&plane);
5580         }
5581
5582
5583         // find a matching plane if there is one
5584         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5585                 if(p->camera_entity == t->camera_entity)
5586                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5587                                 break;
5588         if (planeindex >= r_waterstate.maxwaterplanes)
5589                 return; // nothing we can do, out of planes
5590
5591         // if this triangle does not fit any known plane rendered this frame, add one
5592         if (planeindex >= r_waterstate.numwaterplanes)
5593         {
5594                 // store the new plane
5595                 r_waterstate.numwaterplanes++;
5596                 p->plane = plane;
5597                 // clear materialflags and pvs
5598                 p->materialflags = 0;
5599                 p->pvsvalid = false;
5600                 p->camera_entity = t->camera_entity;
5601                 VectorCopy(surface->mins, p->mins);
5602                 VectorCopy(surface->maxs, p->maxs);
5603         }
5604         else
5605         {
5606                 // merge mins/maxs
5607                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5608                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5609                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5610                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5611                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5612                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5613         }
5614         // merge this surface's materialflags into the waterplane
5615         p->materialflags |= t->currentmaterialflags;
5616         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5617         {
5618                 // merge this surface's PVS into the waterplane
5619                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5620                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5621                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5622                 {
5623                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5624                         p->pvsvalid = true;
5625                 }
5626         }
5627 }
5628
5629 extern cvar_t r_drawparticles;
5630 extern cvar_t r_drawdecals;
5631
5632 static void R_Water_ProcessPlanes(void)
5633 {
5634         int myscissor[4];
5635         r_refdef_view_t originalview;
5636         r_refdef_view_t myview;
5637         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;
5638         r_waterstate_waterplane_t *p;
5639         vec3_t visorigin;
5640
5641         originalview = r_refdef.view;
5642
5643         // lowquality hack, temporarily shut down some cvars and restore afterwards
5644         qualityreduction = r_water_lowquality.integer;
5645         if (qualityreduction > 0)
5646         {
5647                 if (qualityreduction >= 1)
5648                 {
5649                         old_r_shadows = r_shadows.integer;
5650                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5651                         old_r_dlight = r_shadow_realtime_dlight.integer;
5652                         Cvar_SetValueQuick(&r_shadows, 0);
5653                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5654                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5655                 }
5656                 if (qualityreduction >= 2)
5657                 {
5658                         old_r_dynamic = r_dynamic.integer;
5659                         old_r_particles = r_drawparticles.integer;
5660                         old_r_decals = r_drawdecals.integer;
5661                         Cvar_SetValueQuick(&r_dynamic, 0);
5662                         Cvar_SetValueQuick(&r_drawparticles, 0);
5663                         Cvar_SetValueQuick(&r_drawdecals, 0);
5664                 }
5665         }
5666
5667         // make sure enough textures are allocated
5668         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5669         {
5670                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5671                 {
5672                         if (!p->texture_refraction)
5673                                 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);
5674                         if (!p->texture_refraction)
5675                                 goto error;
5676                 }
5677                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5678                 {
5679                         if (!p->texture_camera)
5680                                 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);
5681                         if (!p->texture_camera)
5682                                 goto error;
5683                 }
5684
5685                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5686                 {
5687                         if (!p->texture_reflection)
5688                                 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);
5689                         if (!p->texture_reflection)
5690                                 goto error;
5691                 }
5692         }
5693
5694         // render views
5695         r_refdef.view = originalview;
5696         r_refdef.view.showdebug = false;
5697         r_refdef.view.width = r_waterstate.waterwidth;
5698         r_refdef.view.height = r_waterstate.waterheight;
5699         r_refdef.view.useclipplane = true;
5700         myview = r_refdef.view;
5701         r_waterstate.renderingscene = true;
5702         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5703         {
5704                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5705                 {
5706                         r_refdef.view = myview;
5707                         if(r_water_scissormode.integer)
5708                         {
5709                                 R_SetupView(true);
5710                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5711                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5712                         }
5713
5714                         // render reflected scene and copy into texture
5715                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5716                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5717                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5718                         r_refdef.view.clipplane = p->plane;
5719                         // reverse the cullface settings for this render
5720                         r_refdef.view.cullface_front = GL_FRONT;
5721                         r_refdef.view.cullface_back = GL_BACK;
5722                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5723                         {
5724                                 r_refdef.view.usecustompvs = true;
5725                                 if (p->pvsvalid)
5726                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5727                                 else
5728                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5729                         }
5730
5731                         R_ResetViewRendering3D();
5732                         R_ClearScreen(r_refdef.fogenabled);
5733                         if(r_water_scissormode.integer & 2)
5734                                 R_View_UpdateWithScissor(myscissor);
5735                         else
5736                                 R_View_Update();
5737                         if(r_water_scissormode.integer & 1)
5738                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5739                         R_RenderScene();
5740
5741                         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);
5742                 }
5743
5744                 // render the normal view scene and copy into texture
5745                 // (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)
5746                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5747                 {
5748                         r_refdef.view = myview;
5749                         if(r_water_scissormode.integer)
5750                         {
5751                                 R_SetupView(true);
5752                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5753                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5754                         }
5755
5756                         r_waterstate.renderingrefraction = true;
5757
5758                         r_refdef.view.clipplane = p->plane;
5759                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5760                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5761
5762                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5763                         {
5764                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5765                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5766                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5767                                 R_RenderView_UpdateViewVectors();
5768                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5769                                 {
5770                                         r_refdef.view.usecustompvs = true;
5771                                         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);
5772                                 }
5773                         }
5774
5775                         PlaneClassify(&r_refdef.view.clipplane);
5776
5777                         R_ResetViewRendering3D();
5778                         R_ClearScreen(r_refdef.fogenabled);
5779                         if(r_water_scissormode.integer & 2)
5780                                 R_View_UpdateWithScissor(myscissor);
5781                         else
5782                                 R_View_Update();
5783                         if(r_water_scissormode.integer & 1)
5784                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5785                         R_RenderScene();
5786
5787                         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);
5788                         r_waterstate.renderingrefraction = false;
5789                 }
5790                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5791                 {
5792                         r_refdef.view = myview;
5793
5794                         r_refdef.view.clipplane = p->plane;
5795                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5796                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5797
5798                         r_refdef.view.width = r_waterstate.camerawidth;
5799                         r_refdef.view.height = r_waterstate.cameraheight;
5800                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5801                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5802
5803                         if(p->camera_entity)
5804                         {
5805                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5806                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5807                         }
5808
5809                         // note: all of the view is used for displaying... so
5810                         // there is no use in scissoring
5811
5812                         // reverse the cullface settings for this render
5813                         r_refdef.view.cullface_front = GL_FRONT;
5814                         r_refdef.view.cullface_back = GL_BACK;
5815                         // also reverse the view matrix
5816                         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
5817                         R_RenderView_UpdateViewVectors();
5818                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5819                         {
5820                                 r_refdef.view.usecustompvs = true;
5821                                 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);
5822                         }
5823                         
5824                         // camera needs no clipplane
5825                         r_refdef.view.useclipplane = false;
5826
5827                         PlaneClassify(&r_refdef.view.clipplane);
5828
5829                         R_ResetViewRendering3D();
5830                         R_ClearScreen(r_refdef.fogenabled);
5831                         R_View_Update();
5832                         R_RenderScene();
5833
5834                         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);
5835                         r_waterstate.renderingrefraction = false;
5836                 }
5837
5838         }
5839         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5840         r_waterstate.renderingscene = false;
5841         r_refdef.view = originalview;
5842         R_ResetViewRendering3D();
5843         R_ClearScreen(r_refdef.fogenabled);
5844         R_View_Update();
5845         goto finish;
5846 error:
5847         r_refdef.view = originalview;
5848         r_waterstate.renderingscene = false;
5849         Cvar_SetValueQuick(&r_water, 0);
5850         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5851 finish:
5852         // lowquality hack, restore cvars
5853         if (qualityreduction > 0)
5854         {
5855                 if (qualityreduction >= 1)
5856                 {
5857                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5858                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5859                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5860                 }
5861                 if (qualityreduction >= 2)
5862                 {
5863                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5864                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5865                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5866                 }
5867         }
5868 }
5869
5870 void R_Bloom_StartFrame(void)
5871 {
5872         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5873         int viewwidth, viewheight;
5874         textype_t textype;
5875
5876         if (r_viewscale_fpsscaling.integer)
5877         {
5878                 double actualframetime;
5879                 double targetframetime;
5880                 double adjust;
5881                 actualframetime = r_refdef.lastdrawscreentime;
5882                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5883                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5884                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5885                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5886                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5887                 viewscalefpsadjusted += adjust;
5888                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5889         }
5890         else
5891                 viewscalefpsadjusted = 1.0f;
5892
5893         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5894
5895         switch(vid.renderpath)
5896         {
5897         case RENDERPATH_GL20:
5898         case RENDERPATH_D3D9:
5899         case RENDERPATH_D3D10:
5900         case RENDERPATH_D3D11:
5901         case RENDERPATH_SOFT:
5902         case RENDERPATH_GLES2:
5903                 break;
5904         case RENDERPATH_GL11:
5905         case RENDERPATH_GL13:
5906         case RENDERPATH_GLES1:
5907                 return;
5908         }
5909
5910         // set bloomwidth and bloomheight to the bloom resolution that will be
5911         // used (often less than the screen resolution for faster rendering)
5912         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5913         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5914         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5915         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5916         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5917
5918         // calculate desired texture sizes
5919         if (vid.support.arb_texture_non_power_of_two)
5920         {
5921                 screentexturewidth = vid.width;
5922                 screentextureheight = vid.height;
5923                 bloomtexturewidth = r_bloomstate.bloomwidth;
5924                 bloomtextureheight = r_bloomstate.bloomheight;
5925         }
5926         else
5927         {
5928                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5929                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5930                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5931                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5932         }
5933
5934         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))
5935         {
5936                 Cvar_SetValueQuick(&r_hdr, 0);
5937                 Cvar_SetValueQuick(&r_bloom, 0);
5938                 Cvar_SetValueQuick(&r_motionblur, 0);
5939                 Cvar_SetValueQuick(&r_damageblur, 0);
5940         }
5941
5942         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)
5943                 screentexturewidth = screentextureheight = 0;
5944         if (!r_hdr.integer && !r_bloom.integer)
5945                 bloomtexturewidth = bloomtextureheight = 0;
5946
5947         textype = TEXTYPE_COLORBUFFER;
5948         switch (vid.renderpath)
5949         {
5950         case RENDERPATH_GL20:
5951         case RENDERPATH_GLES2:
5952                 if (vid.support.ext_framebuffer_object)
5953                 {
5954                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5955                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5956                 }
5957                 break;
5958         case RENDERPATH_GL11:
5959         case RENDERPATH_GL13:
5960         case RENDERPATH_GLES1:
5961         case RENDERPATH_D3D9:
5962         case RENDERPATH_D3D10:
5963         case RENDERPATH_D3D11:
5964         case RENDERPATH_SOFT:
5965                 break;
5966         }
5967
5968         // allocate textures as needed
5969         if (r_bloomstate.screentexturewidth != screentexturewidth
5970          || r_bloomstate.screentextureheight != screentextureheight
5971          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
5972          || r_bloomstate.bloomtextureheight != bloomtextureheight
5973          || r_bloomstate.texturetype != textype
5974          || r_bloomstate.viewfbo != r_viewfbo.integer)
5975         {
5976                 if (r_bloomstate.texture_bloom)
5977                         R_FreeTexture(r_bloomstate.texture_bloom);
5978                 r_bloomstate.texture_bloom = NULL;
5979                 if (r_bloomstate.texture_screen)
5980                         R_FreeTexture(r_bloomstate.texture_screen);
5981                 r_bloomstate.texture_screen = NULL;
5982                 if (r_bloomstate.fbo_framebuffer)
5983                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
5984                 r_bloomstate.fbo_framebuffer = 0;
5985                 if (r_bloomstate.texture_framebuffercolor)
5986                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
5987                 r_bloomstate.texture_framebuffercolor = NULL;
5988                 if (r_bloomstate.texture_framebufferdepth)
5989                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
5990                 r_bloomstate.texture_framebufferdepth = NULL;
5991                 r_bloomstate.screentexturewidth = screentexturewidth;
5992                 r_bloomstate.screentextureheight = screentextureheight;
5993                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
5994                         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);
5995                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
5996                 {
5997                         // FIXME: choose depth bits based on a cvar
5998                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
5999                         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);
6000                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6001                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6002                         // render depth into one texture and normalmap into the other
6003                         if (qglDrawBuffer)
6004                         {
6005                                 int status;
6006                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6007                                 qglReadBuffer(GL_COLOR_ATTACHMENT0_EXT);CHECKGLERROR
6008                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
6009                                 if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
6010                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6011                         }
6012                 }
6013                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6014                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6015                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6016                         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);
6017                 r_bloomstate.viewfbo = r_viewfbo.integer;
6018                 r_bloomstate.texturetype = textype;
6019         }
6020
6021         // when doing a reduced render (HDR) we want to use a smaller area
6022         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6023         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6024         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6025         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6026         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6027
6028         // set up a texcoord array for the full resolution screen image
6029         // (we have to keep this around to copy back during final render)
6030         r_bloomstate.screentexcoord2f[0] = 0;
6031         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6032         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6033         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6034         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6035         r_bloomstate.screentexcoord2f[5] = 0;
6036         r_bloomstate.screentexcoord2f[6] = 0;
6037         r_bloomstate.screentexcoord2f[7] = 0;
6038
6039         // set up a texcoord array for the reduced resolution bloom image
6040         // (which will be additive blended over the screen image)
6041         r_bloomstate.bloomtexcoord2f[0] = 0;
6042         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6043         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6044         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6045         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6046         r_bloomstate.bloomtexcoord2f[5] = 0;
6047         r_bloomstate.bloomtexcoord2f[6] = 0;
6048         r_bloomstate.bloomtexcoord2f[7] = 0;
6049
6050         switch(vid.renderpath)
6051         {
6052         case RENDERPATH_GL11:
6053         case RENDERPATH_GL13:
6054         case RENDERPATH_GL20:
6055         case RENDERPATH_SOFT:
6056         case RENDERPATH_GLES1:
6057         case RENDERPATH_GLES2:
6058                 break;
6059         case RENDERPATH_D3D9:
6060         case RENDERPATH_D3D10:
6061         case RENDERPATH_D3D11:
6062                 {
6063                         int i;
6064                         for (i = 0;i < 4;i++)
6065                         {
6066                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6067                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6068                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6069                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6070                         }
6071                 }
6072                 break;
6073         }
6074
6075         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6076         {
6077                 r_bloomstate.enabled = true;
6078                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6079         }
6080
6081         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);
6082
6083         if (r_bloomstate.fbo_framebuffer)
6084                 r_refdef.view.clear = true;
6085 }
6086
6087 void R_Bloom_CopyBloomTexture(float colorscale)
6088 {
6089         r_refdef.stats.bloom++;
6090
6091         // scale down screen texture to the bloom texture size
6092         CHECKGLERROR
6093         R_Mesh_SetMainRenderTargets();
6094         R_SetViewport(&r_bloomstate.viewport);
6095         GL_BlendFunc(GL_ONE, GL_ZERO);
6096         GL_Color(colorscale, colorscale, colorscale, 1);
6097         // 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...
6098         switch(vid.renderpath)
6099         {
6100         case RENDERPATH_GL11:
6101         case RENDERPATH_GL13:
6102         case RENDERPATH_GL20:
6103         case RENDERPATH_GLES1:
6104         case RENDERPATH_GLES2:
6105         case RENDERPATH_SOFT:
6106                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6107                 break;
6108         case RENDERPATH_D3D9:
6109         case RENDERPATH_D3D10:
6110         case RENDERPATH_D3D11:
6111                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6112                 break;
6113         }
6114         // TODO: do boxfilter scale-down in shader?
6115         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6116         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6117         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6118
6119         // we now have a bloom image in the framebuffer
6120         // copy it into the bloom image texture for later processing
6121         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);
6122         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6123 }
6124
6125 void R_Bloom_CopyHDRTexture(void)
6126 {
6127         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);
6128         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6129 }
6130
6131 void R_Bloom_MakeTexture(void)
6132 {
6133         int x, range, dir;
6134         float xoffset, yoffset, r, brighten;
6135
6136         r_refdef.stats.bloom++;
6137
6138         R_ResetViewRendering2D();
6139
6140         // we have a bloom image in the framebuffer
6141         CHECKGLERROR
6142         R_SetViewport(&r_bloomstate.viewport);
6143
6144         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6145         {
6146                 x *= 2;
6147                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6148                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6149                 GL_Color(r,r,r,1);
6150                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6151                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6152                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6153                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6154
6155                 // copy the vertically blurred bloom view to a texture
6156                 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);
6157                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6158         }
6159
6160         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6161         brighten = r_bloom_brighten.value;
6162         if (r_bloomstate.hdr)
6163                 brighten *= r_hdr_range.value;
6164         brighten = sqrt(brighten);
6165         if(range >= 1)
6166                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6167         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, true);
6168
6169         for (dir = 0;dir < 2;dir++)
6170         {
6171                 // blend on at multiple vertical offsets to achieve a vertical blur
6172                 // TODO: do offset blends using GLSL
6173                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6174                 GL_BlendFunc(GL_ONE, GL_ZERO);
6175                 for (x = -range;x <= range;x++)
6176                 {
6177                         if (!dir){xoffset = 0;yoffset = x;}
6178                         else {xoffset = x;yoffset = 0;}
6179                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6180                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6181                         // compute a texcoord array with the specified x and y offset
6182                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6183                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6184                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6185                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6186                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6187                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6188                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6189                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6190                         // this r value looks like a 'dot' particle, fading sharply to
6191                         // black at the edges
6192                         // (probably not realistic but looks good enough)
6193                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6194                         //r = brighten/(range*2+1);
6195                         r = brighten / (range * 2 + 1);
6196                         if(range >= 1)
6197                                 r *= (1 - x*x/(float)(range*range));
6198                         GL_Color(r, r, r, 1);
6199                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6200                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6201                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6202                         GL_BlendFunc(GL_ONE, GL_ONE);
6203                 }
6204
6205                 // copy the vertically blurred bloom view to a texture
6206                 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);
6207                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6208         }
6209 }
6210
6211 void R_HDR_RenderBloomTexture(void)
6212 {
6213         int oldwidth, oldheight;
6214         float oldcolorscale;
6215         qboolean oldwaterstate;
6216
6217         oldwaterstate = r_waterstate.enabled;
6218         oldcolorscale = r_refdef.view.colorscale;
6219         oldwidth = r_refdef.view.width;
6220         oldheight = r_refdef.view.height;
6221         r_refdef.view.width = r_bloomstate.bloomwidth;
6222         r_refdef.view.height = r_bloomstate.bloomheight;
6223
6224         if(r_hdr.integer < 2)
6225                 r_waterstate.enabled = false;
6226
6227         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6228         // TODO: add exposure compensation features
6229         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6230
6231         r_refdef.view.showdebug = false;
6232         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6233
6234         R_ResetViewRendering3D();
6235
6236         R_ClearScreen(r_refdef.fogenabled);
6237         if (r_timereport_active)
6238                 R_TimeReport("HDRclear");
6239
6240         R_View_Update();
6241         if (r_timereport_active)
6242                 R_TimeReport("visibility");
6243
6244         // only do secondary renders with HDR if r_hdr is 2 or higher
6245         r_waterstate.numwaterplanes = 0;
6246         if (r_waterstate.enabled)
6247                 R_RenderWaterPlanes();
6248
6249         r_refdef.view.showdebug = true;
6250         R_RenderScene();
6251         r_waterstate.numwaterplanes = 0;
6252
6253         R_ResetViewRendering2D();
6254
6255         R_Bloom_CopyHDRTexture();
6256         R_Bloom_MakeTexture();
6257
6258         // restore the view settings
6259         r_waterstate.enabled = oldwaterstate;
6260         r_refdef.view.width = oldwidth;
6261         r_refdef.view.height = oldheight;
6262         r_refdef.view.colorscale = oldcolorscale;
6263
6264         R_ResetViewRendering3D();
6265
6266         R_ClearScreen(r_refdef.fogenabled);
6267         if (r_timereport_active)
6268                 R_TimeReport("viewclear");
6269 }
6270
6271 static void R_BlendView(void)
6272 {
6273         unsigned int permutation;
6274         float uservecs[4][4];
6275
6276         switch (vid.renderpath)
6277         {
6278         case RENDERPATH_GL20:
6279         case RENDERPATH_D3D9:
6280         case RENDERPATH_D3D10:
6281         case RENDERPATH_D3D11:
6282         case RENDERPATH_SOFT:
6283         case RENDERPATH_GLES2:
6284                 permutation =
6285                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6286                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6287                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6288                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6289                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6290
6291                 if (r_bloomstate.texture_screen)
6292                 {
6293                         // make sure the buffer is available
6294                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6295
6296                         R_ResetViewRendering2D();
6297                         R_Mesh_SetMainRenderTargets();
6298
6299                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6300                         {
6301                                 // declare variables
6302                                 float blur_factor, blur_mouseaccel, blur_velocity;
6303                                 static float blur_average; 
6304                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6305
6306                                 // set a goal for the factoring
6307                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6308                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6309                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6310                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6311                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6312                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6313
6314                                 // from the goal, pick an averaged value between goal and last value
6315                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6316                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6317                                 
6318                                 // enforce minimum amount of blur 
6319                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6320                                 
6321                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6322
6323                                 // calculate values into a standard alpha
6324                                 cl.motionbluralpha = 1 - exp(-
6325                                                 (
6326                                                  (r_motionblur.value * blur_factor / 80)
6327                                                  +
6328                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6329                                                 )
6330                                                 /
6331                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6332                                           );
6333                                 
6334                                 // randomization for the blur value to combat persistent ghosting
6335                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6336                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6337                                 
6338                                 // apply the blur
6339                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6340                                 {
6341                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6342                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6343                                         switch(vid.renderpath)
6344                                         {
6345                                         case RENDERPATH_GL11:
6346                                         case RENDERPATH_GL13:
6347                                         case RENDERPATH_GL20:
6348                                         case RENDERPATH_GLES1:
6349                                         case RENDERPATH_GLES2:
6350                                         case RENDERPATH_SOFT:
6351                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6352                                                 break;
6353                                         case RENDERPATH_D3D9:
6354                                         case RENDERPATH_D3D10:
6355                                         case RENDERPATH_D3D11:
6356                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6357                                                 break;
6358                                         }
6359                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, true);
6360                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6361                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6362                                 }
6363                                 
6364                                 // updates old view angles for next pass 
6365                                 VectorCopy(cl.viewangles, blur_oldangles);
6366                         }
6367
6368                         // copy view into the screen texture
6369                         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);
6370                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6371                 }
6372                 else if (!r_bloomstate.texture_bloom)
6373                 {
6374                         // we may still have to do view tint...
6375                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6376                         {
6377                                 // apply a color tint to the whole view
6378                                 R_ResetViewRendering2D();
6379                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6380                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6381                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6382                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6383                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6384                         }
6385                         break; // no screen processing, no bloom, skip it
6386                 }
6387
6388                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6389                 {
6390                         // render simple bloom effect
6391                         // copy the screen and shrink it and darken it for the bloom process
6392                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6393                         // make the bloom texture
6394                         R_Bloom_MakeTexture();
6395                 }
6396
6397 #if _MSC_VER >= 1400
6398 #define sscanf sscanf_s
6399 #endif
6400                 memset(uservecs, 0, sizeof(uservecs));
6401                 if (r_glsl_postprocess_uservec1_enable.integer)
6402                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6403                 if (r_glsl_postprocess_uservec2_enable.integer)
6404                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6405                 if (r_glsl_postprocess_uservec3_enable.integer)
6406                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6407                 if (r_glsl_postprocess_uservec4_enable.integer)
6408                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6409
6410                 R_ResetViewRendering2D();
6411                 GL_Color(1, 1, 1, 1);
6412                 GL_BlendFunc(GL_ONE, GL_ZERO);
6413
6414                 switch(vid.renderpath)
6415                 {
6416                 case RENDERPATH_GL20:
6417                 case RENDERPATH_GLES2:
6418                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6419                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6420                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6421                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6422                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6423                         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]);
6424                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6425                         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]);
6426                         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]);
6427                         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]);
6428                         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]);
6429                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6430                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6431                         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);
6432                         break;
6433                 case RENDERPATH_D3D9:
6434 #ifdef SUPPORTD3D
6435                         // 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...
6436                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6437                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6438                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6439                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6440                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6441                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6442                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6443                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6444                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6445                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6446                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6447                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6448                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6449                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6450 #endif
6451                         break;
6452                 case RENDERPATH_D3D10:
6453                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6454                         break;
6455                 case RENDERPATH_D3D11:
6456                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6457                         break;
6458                 case RENDERPATH_SOFT:
6459                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6460                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6461                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6462                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6463                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6464                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6465                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6466                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6467                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6468                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6469                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6470                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6471                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6472                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6473                         break;
6474                 default:
6475                         break;
6476                 }
6477                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6478                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6479                 break;
6480         case RENDERPATH_GL11:
6481         case RENDERPATH_GL13:
6482         case RENDERPATH_GLES1:
6483                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6484                 {
6485                         // apply a color tint to the whole view
6486                         R_ResetViewRendering2D();
6487                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6488                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6489                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, true);
6490                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6491                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6492                 }
6493                 break;
6494         }
6495 }
6496
6497 matrix4x4_t r_waterscrollmatrix;
6498
6499 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6500 {
6501         if (r_refdef.fog_density)
6502         {
6503                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6504                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6505                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6506
6507                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6508                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6509                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6510                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6511
6512                 {
6513                         vec3_t fogvec;
6514                         VectorCopy(r_refdef.fogcolor, fogvec);
6515                         //   color.rgb *= ContrastBoost * SceneBrightness;
6516                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6517                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6518                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6519                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6520                 }
6521         }
6522 }
6523
6524 void R_UpdateVariables(void)
6525 {
6526         R_Textures_Frame();
6527
6528         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6529
6530         r_refdef.farclip = r_farclip_base.value;
6531         if (r_refdef.scene.worldmodel)
6532                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6533         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6534
6535         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6536                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6537         r_refdef.polygonfactor = 0;
6538         r_refdef.polygonoffset = 0;
6539         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6540         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6541
6542         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6543         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6544         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6545         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6546         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6547         if (FAKELIGHT_ENABLED)
6548         {
6549                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6550         }
6551         if (r_showsurfaces.integer)
6552         {
6553                 r_refdef.scene.rtworld = false;
6554                 r_refdef.scene.rtworldshadows = false;
6555                 r_refdef.scene.rtdlight = false;
6556                 r_refdef.scene.rtdlightshadows = false;
6557                 r_refdef.lightmapintensity = 0;
6558         }
6559
6560         if (gamemode == GAME_NEHAHRA)
6561         {
6562                 if (gl_fogenable.integer)
6563                 {
6564                         r_refdef.oldgl_fogenable = true;
6565                         r_refdef.fog_density = gl_fogdensity.value;
6566                         r_refdef.fog_red = gl_fogred.value;
6567                         r_refdef.fog_green = gl_foggreen.value;
6568                         r_refdef.fog_blue = gl_fogblue.value;
6569                         r_refdef.fog_alpha = 1;
6570                         r_refdef.fog_start = 0;
6571                         r_refdef.fog_end = gl_skyclip.value;
6572                         r_refdef.fog_height = 1<<30;
6573                         r_refdef.fog_fadedepth = 128;
6574                 }
6575                 else if (r_refdef.oldgl_fogenable)
6576                 {
6577                         r_refdef.oldgl_fogenable = false;
6578                         r_refdef.fog_density = 0;
6579                         r_refdef.fog_red = 0;
6580                         r_refdef.fog_green = 0;
6581                         r_refdef.fog_blue = 0;
6582                         r_refdef.fog_alpha = 0;
6583                         r_refdef.fog_start = 0;
6584                         r_refdef.fog_end = 0;
6585                         r_refdef.fog_height = 1<<30;
6586                         r_refdef.fog_fadedepth = 128;
6587                 }
6588         }
6589
6590         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6591         r_refdef.fog_start = max(0, r_refdef.fog_start);
6592         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6593
6594         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6595
6596         if (r_refdef.fog_density && r_drawfog.integer)
6597         {
6598                 r_refdef.fogenabled = true;
6599                 // this is the point where the fog reaches 0.9986 alpha, which we
6600                 // consider a good enough cutoff point for the texture
6601                 // (0.9986 * 256 == 255.6)
6602                 if (r_fog_exp2.integer)
6603                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6604                 else
6605                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6606                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6607                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6608                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6609                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6610                         R_BuildFogHeightTexture();
6611                 // fog color was already set
6612                 // update the fog texture
6613                 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)
6614                         R_BuildFogTexture();
6615                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6616                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6617         }
6618         else
6619                 r_refdef.fogenabled = false;
6620
6621         switch(vid.renderpath)
6622         {
6623         case RENDERPATH_GL20:
6624         case RENDERPATH_D3D9:
6625         case RENDERPATH_D3D10:
6626         case RENDERPATH_D3D11:
6627         case RENDERPATH_SOFT:
6628         case RENDERPATH_GLES2:
6629                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6630                 {
6631                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6632                         {
6633                                 // build GLSL gamma texture
6634 #define RAMPWIDTH 256
6635                                 unsigned short ramp[RAMPWIDTH * 3];
6636                                 unsigned char rampbgr[RAMPWIDTH][4];
6637                                 int i;
6638
6639                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6640
6641                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6642                                 for(i = 0; i < RAMPWIDTH; ++i)
6643                                 {
6644                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6645                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6646                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6647                                         rampbgr[i][3] = 0;
6648                                 }
6649                                 if (r_texture_gammaramps)
6650                                 {
6651                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6652                                 }
6653                                 else
6654                                 {
6655                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6656                                 }
6657                         }
6658                 }
6659                 else
6660                 {
6661                         // remove GLSL gamma texture
6662                 }
6663                 break;
6664         case RENDERPATH_GL11:
6665         case RENDERPATH_GL13:
6666         case RENDERPATH_GLES1:
6667                 break;
6668         }
6669 }
6670
6671 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6672 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6673 /*
6674 ================
6675 R_SelectScene
6676 ================
6677 */
6678 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6679         if( scenetype != r_currentscenetype ) {
6680                 // store the old scenetype
6681                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6682                 r_currentscenetype = scenetype;
6683                 // move in the new scene
6684                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6685         }
6686 }
6687
6688 /*
6689 ================
6690 R_GetScenePointer
6691 ================
6692 */
6693 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6694 {
6695         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6696         if( scenetype == r_currentscenetype ) {
6697                 return &r_refdef.scene;
6698         } else {
6699                 return &r_scenes_store[ scenetype ];
6700         }
6701 }
6702
6703 /*
6704 ================
6705 R_RenderView
6706 ================
6707 */
6708 int dpsoftrast_test;
6709 extern void R_Shadow_UpdateBounceGridTexture(void);
6710 extern cvar_t r_shadow_bouncegrid;
6711 void R_RenderView(void)
6712 {
6713         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6714
6715         dpsoftrast_test = r_test.integer;
6716
6717         if (r_timereport_active)
6718                 R_TimeReport("start");
6719         r_textureframe++; // used only by R_GetCurrentTexture
6720         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6721
6722         if(R_CompileShader_CheckStaticParms())
6723                 R_GLSL_Restart_f();
6724
6725         if (!r_drawentities.integer)
6726                 r_refdef.scene.numentities = 0;
6727
6728         R_AnimCache_ClearCache();
6729         R_FrameData_NewFrame();
6730
6731         /* adjust for stereo display */
6732         if(R_Stereo_Active())
6733         {
6734                 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);
6735                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6736         }
6737
6738         if (r_refdef.view.isoverlay)
6739         {
6740                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6741                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6742                 R_TimeReport("depthclear");
6743
6744                 r_refdef.view.showdebug = false;
6745
6746                 r_waterstate.enabled = false;
6747                 r_waterstate.numwaterplanes = 0;
6748
6749                 R_RenderScene();
6750
6751                 r_refdef.view.matrix = originalmatrix;
6752
6753                 CHECKGLERROR
6754                 return;
6755         }
6756
6757         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6758         {
6759                 r_refdef.view.matrix = originalmatrix;
6760                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6761         }
6762
6763         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6764
6765         R_RenderView_UpdateViewVectors();
6766
6767         R_Shadow_UpdateWorldLightSelection();
6768
6769         R_Bloom_StartFrame();
6770         R_Water_StartFrame();
6771
6772         CHECKGLERROR
6773         if (r_timereport_active)
6774                 R_TimeReport("viewsetup");
6775
6776         R_ResetViewRendering3D();
6777
6778         if (r_refdef.view.clear || r_refdef.fogenabled)
6779         {
6780                 R_ClearScreen(r_refdef.fogenabled);
6781                 if (r_timereport_active)
6782                         R_TimeReport("viewclear");
6783         }
6784         r_refdef.view.clear = true;
6785
6786         // this produces a bloom texture to be used in R_BlendView() later
6787         if (r_bloomstate.hdr)
6788         {
6789                 R_HDR_RenderBloomTexture();
6790                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6791                 r_textureframe++; // used only by R_GetCurrentTexture
6792         }
6793
6794         r_refdef.view.showdebug = true;
6795
6796         R_View_Update();
6797         if (r_timereport_active)
6798                 R_TimeReport("visibility");
6799
6800         R_Shadow_UpdateBounceGridTexture();
6801         if (r_timereport_active && r_shadow_bouncegrid.integer)
6802                 R_TimeReport("bouncegrid");
6803
6804         r_waterstate.numwaterplanes = 0;
6805         if (r_waterstate.enabled)
6806                 R_RenderWaterPlanes();
6807
6808         R_RenderScene();
6809         r_waterstate.numwaterplanes = 0;
6810
6811         R_BlendView();
6812         if (r_timereport_active)
6813                 R_TimeReport("blendview");
6814
6815         GL_Scissor(0, 0, vid.width, vid.height);
6816         GL_ScissorTest(false);
6817
6818         r_refdef.view.matrix = originalmatrix;
6819
6820         CHECKGLERROR
6821 }
6822
6823 void R_RenderWaterPlanes(void)
6824 {
6825         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6826         {
6827                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6828                 if (r_timereport_active)
6829                         R_TimeReport("waterworld");
6830         }
6831
6832         // don't let sound skip if going slow
6833         if (r_refdef.scene.extraupdate)
6834                 S_ExtraUpdate ();
6835
6836         R_DrawModelsAddWaterPlanes();
6837         if (r_timereport_active)
6838                 R_TimeReport("watermodels");
6839
6840         if (r_waterstate.numwaterplanes)
6841         {
6842                 R_Water_ProcessPlanes();
6843                 if (r_timereport_active)
6844                         R_TimeReport("waterscenes");
6845         }
6846 }
6847
6848 extern void R_DrawLightningBeams (void);
6849 extern void VM_CL_AddPolygonsToMeshQueue (void);
6850 extern void R_DrawPortals (void);
6851 extern cvar_t cl_locs_show;
6852 static void R_DrawLocs(void);
6853 static void R_DrawEntityBBoxes(void);
6854 static void R_DrawModelDecals(void);
6855 extern void R_DrawModelShadows(void);
6856 extern void R_DrawModelShadowMaps(void);
6857 extern cvar_t cl_decals_newsystem;
6858 extern qboolean r_shadow_usingdeferredprepass;
6859 void R_RenderScene(void)
6860 {
6861         qboolean shadowmapping = false;
6862
6863         if (r_timereport_active)
6864                 R_TimeReport("beginscene");
6865
6866         r_refdef.stats.renders++;
6867
6868         R_UpdateFogColor();
6869
6870         // don't let sound skip if going slow
6871         if (r_refdef.scene.extraupdate)
6872                 S_ExtraUpdate ();
6873
6874         R_MeshQueue_BeginScene();
6875
6876         R_SkyStartFrame();
6877
6878         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);
6879
6880         if (r_timereport_active)
6881                 R_TimeReport("skystartframe");
6882
6883         if (cl.csqc_vidvars.drawworld)
6884         {
6885                 // don't let sound skip if going slow
6886                 if (r_refdef.scene.extraupdate)
6887                         S_ExtraUpdate ();
6888
6889                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6890                 {
6891                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6892                         if (r_timereport_active)
6893                                 R_TimeReport("worldsky");
6894                 }
6895
6896                 if (R_DrawBrushModelsSky() && r_timereport_active)
6897                         R_TimeReport("bmodelsky");
6898
6899                 if (skyrendermasked && skyrenderlater)
6900                 {
6901                         // we have to force off the water clipping plane while rendering sky
6902                         R_SetupView(false);
6903                         R_Sky();
6904                         R_SetupView(true);
6905                         if (r_timereport_active)
6906                                 R_TimeReport("sky");
6907                 }
6908         }
6909
6910         R_AnimCache_CacheVisibleEntities();
6911         if (r_timereport_active)
6912                 R_TimeReport("animation");
6913
6914         R_Shadow_PrepareLights();
6915         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
6916                 R_Shadow_PrepareModelShadows();
6917         if (r_timereport_active)
6918                 R_TimeReport("preparelights");
6919
6920         if (R_Shadow_ShadowMappingEnabled())
6921                 shadowmapping = true;
6922
6923         if (r_shadow_usingdeferredprepass)
6924                 R_Shadow_DrawPrepass();
6925
6926         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
6927         {
6928                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
6929                 if (r_timereport_active)
6930                         R_TimeReport("worlddepth");
6931         }
6932         if (r_depthfirst.integer >= 2)
6933         {
6934                 R_DrawModelsDepth();
6935                 if (r_timereport_active)
6936                         R_TimeReport("modeldepth");
6937         }
6938
6939         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
6940         {
6941                 R_DrawModelShadowMaps();
6942                 R_ResetViewRendering3D();
6943                 // don't let sound skip if going slow
6944                 if (r_refdef.scene.extraupdate)
6945                         S_ExtraUpdate ();
6946         }
6947
6948         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
6949         {
6950                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
6951                 if (r_timereport_active)
6952                         R_TimeReport("world");
6953         }
6954
6955         // don't let sound skip if going slow
6956         if (r_refdef.scene.extraupdate)
6957                 S_ExtraUpdate ();
6958
6959         R_DrawModels();
6960         if (r_timereport_active)
6961                 R_TimeReport("models");
6962
6963         // don't let sound skip if going slow
6964         if (r_refdef.scene.extraupdate)
6965                 S_ExtraUpdate ();
6966
6967         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6968         {
6969                 R_DrawModelShadows();
6970                 R_ResetViewRendering3D();
6971                 // don't let sound skip if going slow
6972                 if (r_refdef.scene.extraupdate)
6973                         S_ExtraUpdate ();
6974         }
6975
6976         if (!r_shadow_usingdeferredprepass)
6977         {
6978                 R_Shadow_DrawLights();
6979                 if (r_timereport_active)
6980                         R_TimeReport("rtlights");
6981         }
6982
6983         // don't let sound skip if going slow
6984         if (r_refdef.scene.extraupdate)
6985                 S_ExtraUpdate ();
6986
6987         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
6988         {
6989                 R_DrawModelShadows();
6990                 R_ResetViewRendering3D();
6991                 // don't let sound skip if going slow
6992                 if (r_refdef.scene.extraupdate)
6993                         S_ExtraUpdate ();
6994         }
6995
6996         if (cl.csqc_vidvars.drawworld)
6997         {
6998                 if (cl_decals_newsystem.integer)
6999                 {
7000                         R_DrawModelDecals();
7001                         if (r_timereport_active)
7002                                 R_TimeReport("modeldecals");
7003                 }
7004                 else
7005                 {
7006                         R_DrawDecals();
7007                         if (r_timereport_active)
7008                                 R_TimeReport("decals");
7009                 }
7010
7011                 R_DrawParticles();
7012                 if (r_timereport_active)
7013                         R_TimeReport("particles");
7014
7015                 R_DrawExplosions();
7016                 if (r_timereport_active)
7017                         R_TimeReport("explosions");
7018
7019                 R_DrawLightningBeams();
7020                 if (r_timereport_active)
7021                         R_TimeReport("lightning");
7022         }
7023
7024         VM_CL_AddPolygonsToMeshQueue();
7025
7026         if (r_refdef.view.showdebug)
7027         {
7028                 if (cl_locs_show.integer)
7029                 {
7030                         R_DrawLocs();
7031                         if (r_timereport_active)
7032                                 R_TimeReport("showlocs");
7033                 }
7034
7035                 if (r_drawportals.integer)
7036                 {
7037                         R_DrawPortals();
7038                         if (r_timereport_active)
7039                                 R_TimeReport("portals");
7040                 }
7041
7042                 if (r_showbboxes.value > 0)
7043                 {
7044                         R_DrawEntityBBoxes();
7045                         if (r_timereport_active)
7046                                 R_TimeReport("bboxes");
7047                 }
7048         }
7049
7050         if (r_transparent.integer)
7051         {
7052                 R_MeshQueue_RenderTransparent();
7053                 if (r_timereport_active)
7054                         R_TimeReport("drawtrans");
7055         }
7056
7057         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))
7058         {
7059                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7060                 if (r_timereport_active)
7061                         R_TimeReport("worlddebug");
7062                 R_DrawModelsDebug();
7063                 if (r_timereport_active)
7064                         R_TimeReport("modeldebug");
7065         }
7066
7067         if (cl.csqc_vidvars.drawworld)
7068         {
7069                 R_Shadow_DrawCoronas();
7070                 if (r_timereport_active)
7071                         R_TimeReport("coronas");
7072         }
7073
7074 #if 0
7075         {
7076                 GL_DepthTest(false);
7077                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7078                 GL_Color(1, 1, 1, 1);
7079                 qglBegin(GL_POLYGON);
7080                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7081                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7082                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7083                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7084                 qglEnd();
7085                 qglBegin(GL_POLYGON);
7086                 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]);
7087                 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]);
7088                 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]);
7089                 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]);
7090                 qglEnd();
7091                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7092         }
7093 #endif
7094
7095         // don't let sound skip if going slow
7096         if (r_refdef.scene.extraupdate)
7097                 S_ExtraUpdate ();
7098
7099         R_ResetViewRendering2D();
7100 }
7101
7102 static const unsigned short bboxelements[36] =
7103 {
7104         5, 1, 3, 5, 3, 7,
7105         6, 2, 0, 6, 0, 4,
7106         7, 3, 2, 7, 2, 6,
7107         4, 0, 1, 4, 1, 5,
7108         4, 5, 7, 4, 7, 6,
7109         1, 0, 2, 1, 2, 3,
7110 };
7111
7112 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7113 {
7114         int i;
7115         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7116
7117         RSurf_ActiveWorldEntity();
7118
7119         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7120         GL_DepthMask(false);
7121         GL_DepthRange(0, 1);
7122         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7123 //      R_Mesh_ResetTextureState();
7124
7125         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7126         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7127         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7128         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7129         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7130         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7131         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7132         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7133         R_FillColors(color4f, 8, cr, cg, cb, ca);
7134         if (r_refdef.fogenabled)
7135         {
7136                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7137                 {
7138                         f1 = RSurf_FogVertex(v);
7139                         f2 = 1 - f1;
7140                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7141                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7142                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7143                 }
7144         }
7145         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7146         R_Mesh_ResetTextureState();
7147         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7148         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7149 }
7150
7151 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7152 {
7153         int i;
7154         float color[4];
7155         prvm_edict_t *edict;
7156         prvm_prog_t *prog_save = prog;
7157
7158         // this function draws bounding boxes of server entities
7159         if (!sv.active)
7160                 return;
7161
7162         GL_CullFace(GL_NONE);
7163         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7164
7165         prog = 0;
7166         SV_VM_Begin();
7167         for (i = 0;i < numsurfaces;i++)
7168         {
7169                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7170                 switch ((int)PRVM_serveredictfloat(edict, solid))
7171                 {
7172                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7173                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7174                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7175                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7176                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7177                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7178                 }
7179                 color[3] *= r_showbboxes.value;
7180                 color[3] = bound(0, color[3], 1);
7181                 GL_DepthTest(!r_showdisabledepthtest.integer);
7182                 GL_CullFace(r_refdef.view.cullface_front);
7183                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7184         }
7185         SV_VM_End();
7186         prog = prog_save;
7187 }
7188
7189 static void R_DrawEntityBBoxes(void)
7190 {
7191         int i;
7192         prvm_edict_t *edict;
7193         vec3_t center;
7194         prvm_prog_t *prog_save = prog;
7195
7196         // this function draws bounding boxes of server entities
7197         if (!sv.active)
7198                 return;
7199
7200         prog = 0;
7201         SV_VM_Begin();
7202         for (i = 0;i < prog->num_edicts;i++)
7203         {
7204                 edict = PRVM_EDICT_NUM(i);
7205                 if (edict->priv.server->free)
7206                         continue;
7207                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7208                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7209                         continue;
7210                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7211                         continue;
7212                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7213                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7214         }
7215         SV_VM_End();
7216         prog = prog_save;
7217 }
7218
7219 static const int nomodelelement3i[24] =
7220 {
7221         5, 2, 0,
7222         5, 1, 2,
7223         5, 0, 3,
7224         5, 3, 1,
7225         0, 2, 4,
7226         2, 1, 4,
7227         3, 0, 4,
7228         1, 3, 4
7229 };
7230
7231 static const unsigned short nomodelelement3s[24] =
7232 {
7233         5, 2, 0,
7234         5, 1, 2,
7235         5, 0, 3,
7236         5, 3, 1,
7237         0, 2, 4,
7238         2, 1, 4,
7239         3, 0, 4,
7240         1, 3, 4
7241 };
7242
7243 static const float nomodelvertex3f[6*3] =
7244 {
7245         -16,   0,   0,
7246          16,   0,   0,
7247           0, -16,   0,
7248           0,  16,   0,
7249           0,   0, -16,
7250           0,   0,  16
7251 };
7252
7253 static const float nomodelcolor4f[6*4] =
7254 {
7255         0.0f, 0.0f, 0.5f, 1.0f,
7256         0.0f, 0.0f, 0.5f, 1.0f,
7257         0.0f, 0.5f, 0.0f, 1.0f,
7258         0.0f, 0.5f, 0.0f, 1.0f,
7259         0.5f, 0.0f, 0.0f, 1.0f,
7260         0.5f, 0.0f, 0.0f, 1.0f
7261 };
7262
7263 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7264 {
7265         int i;
7266         float f1, f2, *c;
7267         float color4f[6*4];
7268
7269         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);
7270
7271         // this is only called once per entity so numsurfaces is always 1, and
7272         // surfacelist is always {0}, so this code does not handle batches
7273
7274         if (rsurface.ent_flags & RENDER_ADDITIVE)
7275         {
7276                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7277                 GL_DepthMask(false);
7278         }
7279         else if (rsurface.colormod[3] < 1)
7280         {
7281                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7282                 GL_DepthMask(false);
7283         }
7284         else
7285         {
7286                 GL_BlendFunc(GL_ONE, GL_ZERO);
7287                 GL_DepthMask(true);
7288         }
7289         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7290         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7291         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7292         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7293         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7294         for (i = 0, c = color4f;i < 6;i++, c += 4)
7295         {
7296                 c[0] *= rsurface.colormod[0];
7297                 c[1] *= rsurface.colormod[1];
7298                 c[2] *= rsurface.colormod[2];
7299                 c[3] *= rsurface.colormod[3];
7300         }
7301         if (r_refdef.fogenabled)
7302         {
7303                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7304                 {
7305                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7306                         f2 = 1 - f1;
7307                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7308                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7309                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7310                 }
7311         }
7312 //      R_Mesh_ResetTextureState();
7313         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
7314         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7315         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7316 }
7317
7318 void R_DrawNoModel(entity_render_t *ent)
7319 {
7320         vec3_t org;
7321         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7322         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7323                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7324         else
7325                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7326 }
7327
7328 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7329 {
7330         vec3_t right1, right2, diff, normal;
7331
7332         VectorSubtract (org2, org1, normal);
7333
7334         // calculate 'right' vector for start
7335         VectorSubtract (r_refdef.view.origin, org1, diff);
7336         CrossProduct (normal, diff, right1);
7337         VectorNormalize (right1);
7338
7339         // calculate 'right' vector for end
7340         VectorSubtract (r_refdef.view.origin, org2, diff);
7341         CrossProduct (normal, diff, right2);
7342         VectorNormalize (right2);
7343
7344         vert[ 0] = org1[0] + width * right1[0];
7345         vert[ 1] = org1[1] + width * right1[1];
7346         vert[ 2] = org1[2] + width * right1[2];
7347         vert[ 3] = org1[0] - width * right1[0];
7348         vert[ 4] = org1[1] - width * right1[1];
7349         vert[ 5] = org1[2] - width * right1[2];
7350         vert[ 6] = org2[0] - width * right2[0];
7351         vert[ 7] = org2[1] - width * right2[1];
7352         vert[ 8] = org2[2] - width * right2[2];
7353         vert[ 9] = org2[0] + width * right2[0];
7354         vert[10] = org2[1] + width * right2[1];
7355         vert[11] = org2[2] + width * right2[2];
7356 }
7357
7358 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)
7359 {
7360         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7361         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7362         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7363         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7364         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7365         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7366         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7367         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7368         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7369         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7370         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7371         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7372 }
7373
7374 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7375 {
7376         int i;
7377         float *vertex3f;
7378         float v[3];
7379         VectorSet(v, x, y, z);
7380         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7381                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7382                         break;
7383         if (i == mesh->numvertices)
7384         {
7385                 if (mesh->numvertices < mesh->maxvertices)
7386                 {
7387                         VectorCopy(v, vertex3f);
7388                         mesh->numvertices++;
7389                 }
7390                 return mesh->numvertices;
7391         }
7392         else
7393                 return i;
7394 }
7395
7396 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7397 {
7398         int i;
7399         int *e, element[3];
7400         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7401         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7402         e = mesh->element3i + mesh->numtriangles * 3;
7403         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7404         {
7405                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7406                 if (mesh->numtriangles < mesh->maxtriangles)
7407                 {
7408                         *e++ = element[0];
7409                         *e++ = element[1];
7410                         *e++ = element[2];
7411                         mesh->numtriangles++;
7412                 }
7413                 element[1] = element[2];
7414         }
7415 }
7416
7417 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7418 {
7419         int i;
7420         int *e, element[3];
7421         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7422         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7423         e = mesh->element3i + mesh->numtriangles * 3;
7424         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7425         {
7426                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7427                 if (mesh->numtriangles < mesh->maxtriangles)
7428                 {
7429                         *e++ = element[0];
7430                         *e++ = element[1];
7431                         *e++ = element[2];
7432                         mesh->numtriangles++;
7433                 }
7434                 element[1] = element[2];
7435         }
7436 }
7437
7438 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7439 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7440 {
7441         int planenum, planenum2;
7442         int w;
7443         int tempnumpoints;
7444         mplane_t *plane, *plane2;
7445         double maxdist;
7446         double temppoints[2][256*3];
7447         // figure out how large a bounding box we need to properly compute this brush
7448         maxdist = 0;
7449         for (w = 0;w < numplanes;w++)
7450                 maxdist = max(maxdist, fabs(planes[w].dist));
7451         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7452         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7453         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7454         {
7455                 w = 0;
7456                 tempnumpoints = 4;
7457                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7458                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7459                 {
7460                         if (planenum2 == planenum)
7461                                 continue;
7462                         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);
7463                         w = !w;
7464                 }
7465                 if (tempnumpoints < 3)
7466                         continue;
7467                 // generate elements forming a triangle fan for this polygon
7468                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7469         }
7470 }
7471
7472 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)
7473 {
7474         texturelayer_t *layer;
7475         layer = t->currentlayers + t->currentnumlayers++;
7476         layer->type = type;
7477         layer->depthmask = depthmask;
7478         layer->blendfunc1 = blendfunc1;
7479         layer->blendfunc2 = blendfunc2;
7480         layer->texture = texture;
7481         layer->texmatrix = *matrix;
7482         layer->color[0] = r;
7483         layer->color[1] = g;
7484         layer->color[2] = b;
7485         layer->color[3] = a;
7486 }
7487
7488 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7489 {
7490         if(parms[0] == 0 && parms[1] == 0)
7491                 return false;
7492         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7493                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)] == 0)
7494                         return false;
7495         return true;
7496 }
7497
7498 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7499 {
7500         double index, f;
7501         index = parms[2] + rsurface.shadertime * parms[3];
7502         index -= floor(index);
7503         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7504         {
7505         default:
7506         case Q3WAVEFUNC_NONE:
7507         case Q3WAVEFUNC_NOISE:
7508         case Q3WAVEFUNC_COUNT:
7509                 f = 0;
7510                 break;
7511         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7512         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7513         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7514         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7515         case Q3WAVEFUNC_TRIANGLE:
7516                 index *= 4;
7517                 f = index - floor(index);
7518                 if (index < 1)
7519                 {
7520                         // f = f;
7521                 }
7522                 else if (index < 2)
7523                         f = 1 - f;
7524                 else if (index < 3)
7525                         f = -f;
7526                 else
7527                         f = -(1 - f);
7528                 break;
7529         }
7530         f = parms[0] + parms[1] * f;
7531         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7532                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT)];
7533         return (float) f;
7534 }
7535
7536 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7537 {
7538         int w, h, idx;
7539         double f;
7540         double offsetd[2];
7541         float tcmat[12];
7542         matrix4x4_t matrix, temp;
7543         switch(tcmod->tcmod)
7544         {
7545                 case Q3TCMOD_COUNT:
7546                 case Q3TCMOD_NONE:
7547                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7548                                 matrix = r_waterscrollmatrix;
7549                         else
7550                                 matrix = identitymatrix;
7551                         break;
7552                 case Q3TCMOD_ENTITYTRANSLATE:
7553                         // this is used in Q3 to allow the gamecode to control texcoord
7554                         // scrolling on the entity, which is not supported in darkplaces yet.
7555                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7556                         break;
7557                 case Q3TCMOD_ROTATE:
7558                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7559                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7560                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7561                         break;
7562                 case Q3TCMOD_SCALE:
7563                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7564                         break;
7565                 case Q3TCMOD_SCROLL:
7566                         // extra care is needed because of precision breakdown with large values of time
7567                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7568                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7569                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7570                         break;
7571                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7572                         w = (int) tcmod->parms[0];
7573                         h = (int) tcmod->parms[1];
7574                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7575                         f = f - floor(f);
7576                         idx = (int) floor(f * w * h);
7577                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7578                         break;
7579                 case Q3TCMOD_STRETCH:
7580                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7581                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7582                         break;
7583                 case Q3TCMOD_TRANSFORM:
7584                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7585                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7586                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7587                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7588                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7589                         break;
7590                 case Q3TCMOD_TURBULENT:
7591                         // this is handled in the RSurf_PrepareVertices function
7592                         matrix = identitymatrix;
7593                         break;
7594         }
7595         temp = *texmatrix;
7596         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7597 }
7598
7599 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7600 {
7601         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7602         char name[MAX_QPATH];
7603         skinframe_t *skinframe;
7604         unsigned char pixels[296*194];
7605         strlcpy(cache->name, skinname, sizeof(cache->name));
7606         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7607         if (developer_loading.integer)
7608                 Con_Printf("loading %s\n", name);
7609         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7610         if (!skinframe || !skinframe->base)
7611         {
7612                 unsigned char *f;
7613                 fs_offset_t filesize;
7614                 skinframe = NULL;
7615                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7616                 if (f)
7617                 {
7618                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7619                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7620                         Mem_Free(f);
7621                 }
7622         }
7623         cache->skinframe = skinframe;
7624 }
7625
7626 texture_t *R_GetCurrentTexture(texture_t *t)
7627 {
7628         int i;
7629         const entity_render_t *ent = rsurface.entity;
7630         dp_model_t *model = ent->model;
7631         q3shaderinfo_layer_tcmod_t *tcmod;
7632
7633         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7634                 return t->currentframe;
7635         t->update_lastrenderframe = r_textureframe;
7636         t->update_lastrenderentity = (void *)ent;
7637
7638         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7639                 t->camera_entity = ent->entitynumber;
7640         else
7641                 t->camera_entity = 0;
7642
7643         // switch to an alternate material if this is a q1bsp animated material
7644         {
7645                 texture_t *texture = t;
7646                 int s = rsurface.ent_skinnum;
7647                 if ((unsigned int)s >= (unsigned int)model->numskins)
7648                         s = 0;
7649                 if (model->skinscenes)
7650                 {
7651                         if (model->skinscenes[s].framecount > 1)
7652                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7653                         else
7654                                 s = model->skinscenes[s].firstframe;
7655                 }
7656                 if (s > 0)
7657                         t = t + s * model->num_surfaces;
7658                 if (t->animated)
7659                 {
7660                         // use an alternate animation if the entity's frame is not 0,
7661                         // and only if the texture has an alternate animation
7662                         if (rsurface.ent_alttextures && t->anim_total[1])
7663                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7664                         else
7665                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7666                 }
7667                 texture->currentframe = t;
7668         }
7669
7670         // update currentskinframe to be a qw skin or animation frame
7671         if (rsurface.ent_qwskin >= 0)
7672         {
7673                 i = rsurface.ent_qwskin;
7674                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7675                 {
7676                         r_qwskincache_size = cl.maxclients;
7677                         if (r_qwskincache)
7678                                 Mem_Free(r_qwskincache);
7679                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7680                 }
7681                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7682                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7683                 t->currentskinframe = r_qwskincache[i].skinframe;
7684                 if (t->currentskinframe == NULL)
7685                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7686         }
7687         else if (t->numskinframes >= 2)
7688                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7689         if (t->backgroundnumskinframes >= 2)
7690                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7691
7692         t->currentmaterialflags = t->basematerialflags;
7693         t->currentalpha = rsurface.colormod[3];
7694         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7695                 t->currentalpha *= r_wateralpha.value;
7696         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7697                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7698         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7699                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7700         if (!(rsurface.ent_flags & RENDER_LIGHT))
7701                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7702         else if (FAKELIGHT_ENABLED)
7703         {
7704                 // no modellight if using fakelight for the map
7705         }
7706         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7707         {
7708                 // pick a model lighting mode
7709                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7710                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7711                 else
7712                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7713         }
7714         if (rsurface.ent_flags & RENDER_ADDITIVE)
7715                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7716         else if (t->currentalpha < 1)
7717                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7718         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7719                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7720         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7721                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7722         if (t->backgroundnumskinframes)
7723                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7724         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7725         {
7726                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7727                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7728         }
7729         else
7730                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7731         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7732         {
7733                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7734                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7735         }
7736         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7737                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7738
7739         // there is no tcmod
7740         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7741         {
7742                 t->currenttexmatrix = r_waterscrollmatrix;
7743                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7744         }
7745         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7746         {
7747                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7748                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7749         }
7750
7751         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7752                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7753         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7754                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7755
7756         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7757         if (t->currentskinframe->qpixels)
7758                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7759         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7760         if (!t->basetexture)
7761                 t->basetexture = r_texture_notexture;
7762         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7763         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7764         t->nmaptexture = t->currentskinframe->nmap;
7765         if (!t->nmaptexture)
7766                 t->nmaptexture = r_texture_blanknormalmap;
7767         t->glosstexture = r_texture_black;
7768         t->glowtexture = t->currentskinframe->glow;
7769         t->fogtexture = t->currentskinframe->fog;
7770         t->reflectmasktexture = t->currentskinframe->reflect;
7771         if (t->backgroundnumskinframes)
7772         {
7773                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7774                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7775                 t->backgroundglosstexture = r_texture_black;
7776                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7777                 if (!t->backgroundnmaptexture)
7778                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7779         }
7780         else
7781         {
7782                 t->backgroundbasetexture = r_texture_white;
7783                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7784                 t->backgroundglosstexture = r_texture_black;
7785                 t->backgroundglowtexture = NULL;
7786         }
7787         t->specularpower = r_shadow_glossexponent.value;
7788         // TODO: store reference values for these in the texture?
7789         t->specularscale = 0;
7790         if (r_shadow_gloss.integer > 0)
7791         {
7792                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7793                 {
7794                         if (r_shadow_glossintensity.value > 0)
7795                         {
7796                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7797                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7798                                 t->specularscale = r_shadow_glossintensity.value;
7799                         }
7800                 }
7801                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7802                 {
7803                         t->glosstexture = r_texture_white;
7804                         t->backgroundglosstexture = r_texture_white;
7805                         t->specularscale = r_shadow_gloss2intensity.value;
7806                         t->specularpower = r_shadow_gloss2exponent.value;
7807                 }
7808         }
7809         t->specularscale *= t->specularscalemod;
7810         t->specularpower *= t->specularpowermod;
7811
7812         // lightmaps mode looks bad with dlights using actual texturing, so turn
7813         // off the colormap and glossmap, but leave the normalmap on as it still
7814         // accurately represents the shading involved
7815         if (gl_lightmaps.integer)
7816         {
7817                 t->basetexture = r_texture_grey128;
7818                 t->pantstexture = r_texture_black;
7819                 t->shirttexture = r_texture_black;
7820                 t->nmaptexture = r_texture_blanknormalmap;
7821                 t->glosstexture = r_texture_black;
7822                 t->glowtexture = NULL;
7823                 t->fogtexture = NULL;
7824                 t->reflectmasktexture = NULL;
7825                 t->backgroundbasetexture = NULL;
7826                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7827                 t->backgroundglosstexture = r_texture_black;
7828                 t->backgroundglowtexture = NULL;
7829                 t->specularscale = 0;
7830                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7831         }
7832
7833         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7834         VectorClear(t->dlightcolor);
7835         t->currentnumlayers = 0;
7836         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7837         {
7838                 int blendfunc1, blendfunc2;
7839                 qboolean depthmask;
7840                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7841                 {
7842                         blendfunc1 = GL_SRC_ALPHA;
7843                         blendfunc2 = GL_ONE;
7844                 }
7845                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7846                 {
7847                         blendfunc1 = GL_SRC_ALPHA;
7848                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7849                 }
7850                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7851                 {
7852                         blendfunc1 = t->customblendfunc[0];
7853                         blendfunc2 = t->customblendfunc[1];
7854                 }
7855                 else
7856                 {
7857                         blendfunc1 = GL_ONE;
7858                         blendfunc2 = GL_ZERO;
7859                 }
7860                 // don't colormod evilblend textures
7861                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7862                         VectorSet(t->lightmapcolor, 1, 1, 1);
7863                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7864                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7865                 {
7866                         // fullbright is not affected by r_refdef.lightmapintensity
7867                         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]);
7868                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7869                                 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]);
7870                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7871                                 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]);
7872                 }
7873                 else
7874                 {
7875                         vec3_t ambientcolor;
7876                         float colorscale;
7877                         // set the color tint used for lights affecting this surface
7878                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7879                         colorscale = 2;
7880                         // q3bsp has no lightmap updates, so the lightstylevalue that
7881                         // would normally be baked into the lightmap must be
7882                         // applied to the color
7883                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7884                         if (model->type == mod_brushq3)
7885                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7886                         colorscale *= r_refdef.lightmapintensity;
7887                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7888                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7889                         // basic lit geometry
7890                         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]);
7891                         // add pants/shirt if needed
7892                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7893                                 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]);
7894                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7895                                 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]);
7896                         // now add ambient passes if needed
7897                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7898                         {
7899                                 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]);
7900                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7901                                         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]);
7902                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7903                                         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]);
7904                         }
7905                 }
7906                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
7907                         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]);
7908                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
7909                 {
7910                         // if this is opaque use alpha blend which will darken the earlier
7911                         // passes cheaply.
7912                         //
7913                         // if this is an alpha blended material, all the earlier passes
7914                         // were darkened by fog already, so we only need to add the fog
7915                         // color ontop through the fog mask texture
7916                         //
7917                         // if this is an additive blended material, all the earlier passes
7918                         // were darkened by fog already, and we should not add fog color
7919                         // (because the background was not darkened, there is no fog color
7920                         // that was lost behind it).
7921                         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]);
7922                 }
7923         }
7924
7925         return t->currentframe;
7926 }
7927
7928 rsurfacestate_t rsurface;
7929
7930 void RSurf_ActiveWorldEntity(void)
7931 {
7932         dp_model_t *model = r_refdef.scene.worldmodel;
7933         //if (rsurface.entity == r_refdef.scene.worldentity)
7934         //      return;
7935         rsurface.entity = r_refdef.scene.worldentity;
7936         rsurface.skeleton = NULL;
7937         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
7938         rsurface.ent_skinnum = 0;
7939         rsurface.ent_qwskin = -1;
7940         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
7941         rsurface.shadertime = r_refdef.scene.time;
7942         rsurface.matrix = identitymatrix;
7943         rsurface.inversematrix = identitymatrix;
7944         rsurface.matrixscale = 1;
7945         rsurface.inversematrixscale = 1;
7946         R_EntityMatrix(&identitymatrix);
7947         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
7948         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
7949         rsurface.fograngerecip = r_refdef.fograngerecip;
7950         rsurface.fogheightfade = r_refdef.fogheightfade;
7951         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
7952         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
7953         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
7954         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
7955         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
7956         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
7957         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
7958         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
7959         rsurface.colormod[3] = 1;
7960         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);
7961         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
7962         rsurface.frameblend[0].lerp = 1;
7963         rsurface.ent_alttextures = false;
7964         rsurface.basepolygonfactor = r_refdef.polygonfactor;
7965         rsurface.basepolygonoffset = r_refdef.polygonoffset;
7966         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
7967         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7968         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
7969         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
7970         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7971         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
7972         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
7973         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7974         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
7975         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
7976         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7977         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
7978         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
7979         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7980         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
7981         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
7982         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7983         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
7984         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
7985         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
7986         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
7987         rsurface.modelelement3i = model->surfmesh.data_element3i;
7988         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
7989         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
7990         rsurface.modelelement3s = model->surfmesh.data_element3s;
7991         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
7992         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
7993         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
7994         rsurface.modelnumvertices = model->surfmesh.num_vertices;
7995         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
7996         rsurface.modelsurfaces = model->data_surfaces;
7997         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
7998         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
7999         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8000         rsurface.modelgeneratedvertex = false;
8001         rsurface.batchgeneratedvertex = false;
8002         rsurface.batchfirstvertex = 0;
8003         rsurface.batchnumvertices = 0;
8004         rsurface.batchfirsttriangle = 0;
8005         rsurface.batchnumtriangles = 0;
8006         rsurface.batchvertex3f  = NULL;
8007         rsurface.batchvertex3f_vertexbuffer = NULL;
8008         rsurface.batchvertex3f_bufferoffset = 0;
8009         rsurface.batchsvector3f = NULL;
8010         rsurface.batchsvector3f_vertexbuffer = NULL;
8011         rsurface.batchsvector3f_bufferoffset = 0;
8012         rsurface.batchtvector3f = NULL;
8013         rsurface.batchtvector3f_vertexbuffer = NULL;
8014         rsurface.batchtvector3f_bufferoffset = 0;
8015         rsurface.batchnormal3f  = NULL;
8016         rsurface.batchnormal3f_vertexbuffer = NULL;
8017         rsurface.batchnormal3f_bufferoffset = 0;
8018         rsurface.batchlightmapcolor4f = NULL;
8019         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8020         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8021         rsurface.batchtexcoordtexture2f = NULL;
8022         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8023         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8024         rsurface.batchtexcoordlightmap2f = NULL;
8025         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8026         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8027         rsurface.batchvertexmesh = NULL;
8028         rsurface.batchvertexmeshbuffer = NULL;
8029         rsurface.batchvertex3fbuffer = NULL;
8030         rsurface.batchelement3i = NULL;
8031         rsurface.batchelement3i_indexbuffer = NULL;
8032         rsurface.batchelement3i_bufferoffset = 0;
8033         rsurface.batchelement3s = NULL;
8034         rsurface.batchelement3s_indexbuffer = NULL;
8035         rsurface.batchelement3s_bufferoffset = 0;
8036         rsurface.passcolor4f = NULL;
8037         rsurface.passcolor4f_vertexbuffer = NULL;
8038         rsurface.passcolor4f_bufferoffset = 0;
8039 }
8040
8041 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8042 {
8043         dp_model_t *model = ent->model;
8044         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8045         //      return;
8046         rsurface.entity = (entity_render_t *)ent;
8047         rsurface.skeleton = ent->skeleton;
8048         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8049         rsurface.ent_skinnum = ent->skinnum;
8050         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;
8051         rsurface.ent_flags = ent->flags;
8052         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8053         rsurface.matrix = ent->matrix;
8054         rsurface.inversematrix = ent->inversematrix;
8055         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8056         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8057         R_EntityMatrix(&rsurface.matrix);
8058         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8059         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8060         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8061         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8062         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8063         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8064         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8065         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8066         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8067         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8068         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8069         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8070         rsurface.colormod[3] = ent->alpha;
8071         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8072         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8073         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8074         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8075         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8076         if (ent->model->brush.submodel && !prepass)
8077         {
8078                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8079                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8080         }
8081         if (model->surfmesh.isanimated && model->AnimateVertices)
8082         {
8083                 if (ent->animcache_vertex3f)
8084                 {
8085                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8086                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8087                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8088                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8089                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8090                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8091                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8092                 }
8093                 else if (wanttangents)
8094                 {
8095                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8096                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8097                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8098                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8099                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8100                         rsurface.modelvertexmesh = NULL;
8101                         rsurface.modelvertexmeshbuffer = NULL;
8102                         rsurface.modelvertex3fbuffer = NULL;
8103                 }
8104                 else if (wantnormals)
8105                 {
8106                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8107                         rsurface.modelsvector3f = NULL;
8108                         rsurface.modeltvector3f = NULL;
8109                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8110                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8111                         rsurface.modelvertexmesh = NULL;
8112                         rsurface.modelvertexmeshbuffer = NULL;
8113                         rsurface.modelvertex3fbuffer = NULL;
8114                 }
8115                 else
8116                 {
8117                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8118                         rsurface.modelsvector3f = NULL;
8119                         rsurface.modeltvector3f = NULL;
8120                         rsurface.modelnormal3f = NULL;
8121                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8122                         rsurface.modelvertexmesh = NULL;
8123                         rsurface.modelvertexmeshbuffer = NULL;
8124                         rsurface.modelvertex3fbuffer = NULL;
8125                 }
8126                 rsurface.modelvertex3f_vertexbuffer = 0;
8127                 rsurface.modelvertex3f_bufferoffset = 0;
8128                 rsurface.modelsvector3f_vertexbuffer = 0;
8129                 rsurface.modelsvector3f_bufferoffset = 0;
8130                 rsurface.modeltvector3f_vertexbuffer = 0;
8131                 rsurface.modeltvector3f_bufferoffset = 0;
8132                 rsurface.modelnormal3f_vertexbuffer = 0;
8133                 rsurface.modelnormal3f_bufferoffset = 0;
8134                 rsurface.modelgeneratedvertex = true;
8135         }
8136         else
8137         {
8138                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8139                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8140                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8141                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8142                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8143                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8144                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8145                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8146                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8147                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8148                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8149                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8150                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8151                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8152                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8153                 rsurface.modelgeneratedvertex = false;
8154         }
8155         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8156         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8157         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8158         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8159         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8160         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8161         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8162         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8163         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8164         rsurface.modelelement3i = model->surfmesh.data_element3i;
8165         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8166         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8167         rsurface.modelelement3s = model->surfmesh.data_element3s;
8168         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8169         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8170         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8171         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8172         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8173         rsurface.modelsurfaces = model->data_surfaces;
8174         rsurface.batchgeneratedvertex = false;
8175         rsurface.batchfirstvertex = 0;
8176         rsurface.batchnumvertices = 0;
8177         rsurface.batchfirsttriangle = 0;
8178         rsurface.batchnumtriangles = 0;
8179         rsurface.batchvertex3f  = NULL;
8180         rsurface.batchvertex3f_vertexbuffer = NULL;
8181         rsurface.batchvertex3f_bufferoffset = 0;
8182         rsurface.batchsvector3f = NULL;
8183         rsurface.batchsvector3f_vertexbuffer = NULL;
8184         rsurface.batchsvector3f_bufferoffset = 0;
8185         rsurface.batchtvector3f = NULL;
8186         rsurface.batchtvector3f_vertexbuffer = NULL;
8187         rsurface.batchtvector3f_bufferoffset = 0;
8188         rsurface.batchnormal3f  = NULL;
8189         rsurface.batchnormal3f_vertexbuffer = NULL;
8190         rsurface.batchnormal3f_bufferoffset = 0;
8191         rsurface.batchlightmapcolor4f = NULL;
8192         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8193         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8194         rsurface.batchtexcoordtexture2f = NULL;
8195         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8196         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8197         rsurface.batchtexcoordlightmap2f = NULL;
8198         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8199         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8200         rsurface.batchvertexmesh = NULL;
8201         rsurface.batchvertexmeshbuffer = NULL;
8202         rsurface.batchvertex3fbuffer = NULL;
8203         rsurface.batchelement3i = NULL;
8204         rsurface.batchelement3i_indexbuffer = NULL;
8205         rsurface.batchelement3i_bufferoffset = 0;
8206         rsurface.batchelement3s = NULL;
8207         rsurface.batchelement3s_indexbuffer = NULL;
8208         rsurface.batchelement3s_bufferoffset = 0;
8209         rsurface.passcolor4f = NULL;
8210         rsurface.passcolor4f_vertexbuffer = NULL;
8211         rsurface.passcolor4f_bufferoffset = 0;
8212 }
8213
8214 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)
8215 {
8216         rsurface.entity = r_refdef.scene.worldentity;
8217         rsurface.skeleton = NULL;
8218         rsurface.ent_skinnum = 0;
8219         rsurface.ent_qwskin = -1;
8220         rsurface.ent_flags = entflags;
8221         rsurface.shadertime = r_refdef.scene.time - shadertime;
8222         rsurface.modelnumvertices = numvertices;
8223         rsurface.modelnumtriangles = numtriangles;
8224         rsurface.matrix = *matrix;
8225         rsurface.inversematrix = *inversematrix;
8226         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8227         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8228         R_EntityMatrix(&rsurface.matrix);
8229         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8230         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8231         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8232         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8233         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8234         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8235         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8236         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8237         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8238         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8239         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8240         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8241         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);
8242         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8243         rsurface.frameblend[0].lerp = 1;
8244         rsurface.ent_alttextures = false;
8245         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8246         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8247         if (wanttangents)
8248         {
8249                 rsurface.modelvertex3f = (float *)vertex3f;
8250                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8251                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8252                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8253         }
8254         else if (wantnormals)
8255         {
8256                 rsurface.modelvertex3f = (float *)vertex3f;
8257                 rsurface.modelsvector3f = NULL;
8258                 rsurface.modeltvector3f = NULL;
8259                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8260         }
8261         else
8262         {
8263                 rsurface.modelvertex3f = (float *)vertex3f;
8264                 rsurface.modelsvector3f = NULL;
8265                 rsurface.modeltvector3f = NULL;
8266                 rsurface.modelnormal3f = NULL;
8267         }
8268         rsurface.modelvertexmesh = NULL;
8269         rsurface.modelvertexmeshbuffer = NULL;
8270         rsurface.modelvertex3fbuffer = NULL;
8271         rsurface.modelvertex3f_vertexbuffer = 0;
8272         rsurface.modelvertex3f_bufferoffset = 0;
8273         rsurface.modelsvector3f_vertexbuffer = 0;
8274         rsurface.modelsvector3f_bufferoffset = 0;
8275         rsurface.modeltvector3f_vertexbuffer = 0;
8276         rsurface.modeltvector3f_bufferoffset = 0;
8277         rsurface.modelnormal3f_vertexbuffer = 0;
8278         rsurface.modelnormal3f_bufferoffset = 0;
8279         rsurface.modelgeneratedvertex = true;
8280         rsurface.modellightmapcolor4f  = (float *)color4f;
8281         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8282         rsurface.modellightmapcolor4f_bufferoffset = 0;
8283         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8284         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8285         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8286         rsurface.modeltexcoordlightmap2f  = NULL;
8287         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8288         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8289         rsurface.modelelement3i = (int *)element3i;
8290         rsurface.modelelement3i_indexbuffer = NULL;
8291         rsurface.modelelement3i_bufferoffset = 0;
8292         rsurface.modelelement3s = (unsigned short *)element3s;
8293         rsurface.modelelement3s_indexbuffer = NULL;
8294         rsurface.modelelement3s_bufferoffset = 0;
8295         rsurface.modellightmapoffsets = NULL;
8296         rsurface.modelsurfaces = NULL;
8297         rsurface.batchgeneratedvertex = false;
8298         rsurface.batchfirstvertex = 0;
8299         rsurface.batchnumvertices = 0;
8300         rsurface.batchfirsttriangle = 0;
8301         rsurface.batchnumtriangles = 0;
8302         rsurface.batchvertex3f  = NULL;
8303         rsurface.batchvertex3f_vertexbuffer = NULL;
8304         rsurface.batchvertex3f_bufferoffset = 0;
8305         rsurface.batchsvector3f = NULL;
8306         rsurface.batchsvector3f_vertexbuffer = NULL;
8307         rsurface.batchsvector3f_bufferoffset = 0;
8308         rsurface.batchtvector3f = NULL;
8309         rsurface.batchtvector3f_vertexbuffer = NULL;
8310         rsurface.batchtvector3f_bufferoffset = 0;
8311         rsurface.batchnormal3f  = NULL;
8312         rsurface.batchnormal3f_vertexbuffer = NULL;
8313         rsurface.batchnormal3f_bufferoffset = 0;
8314         rsurface.batchlightmapcolor4f = NULL;
8315         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8316         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8317         rsurface.batchtexcoordtexture2f = NULL;
8318         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8319         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8320         rsurface.batchtexcoordlightmap2f = NULL;
8321         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8322         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8323         rsurface.batchvertexmesh = NULL;
8324         rsurface.batchvertexmeshbuffer = NULL;
8325         rsurface.batchvertex3fbuffer = NULL;
8326         rsurface.batchelement3i = NULL;
8327         rsurface.batchelement3i_indexbuffer = NULL;
8328         rsurface.batchelement3i_bufferoffset = 0;
8329         rsurface.batchelement3s = NULL;
8330         rsurface.batchelement3s_indexbuffer = NULL;
8331         rsurface.batchelement3s_bufferoffset = 0;
8332         rsurface.passcolor4f = NULL;
8333         rsurface.passcolor4f_vertexbuffer = NULL;
8334         rsurface.passcolor4f_bufferoffset = 0;
8335
8336         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8337         {
8338                 if ((wantnormals || wanttangents) && !normal3f)
8339                 {
8340                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8341                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8342                 }
8343                 if (wanttangents && !svector3f)
8344                 {
8345                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8346                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8347                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8348                 }
8349         }
8350 }
8351
8352 float RSurf_FogPoint(const float *v)
8353 {
8354         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8355         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8356         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8357         float FogHeightFade = r_refdef.fogheightfade;
8358         float fogfrac;
8359         unsigned int fogmasktableindex;
8360         if (r_refdef.fogplaneviewabove)
8361                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8362         else
8363                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8364         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8365         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8366 }
8367
8368 float RSurf_FogVertex(const float *v)
8369 {
8370         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8371         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8372         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8373         float FogHeightFade = rsurface.fogheightfade;
8374         float fogfrac;
8375         unsigned int fogmasktableindex;
8376         if (r_refdef.fogplaneviewabove)
8377                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8378         else
8379                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8380         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8381         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8382 }
8383
8384 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8385 {
8386         int i;
8387         for (i = 0;i < numelements;i++)
8388                 outelement3i[i] = inelement3i[i] + adjust;
8389 }
8390
8391 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8392 extern cvar_t gl_vbo;
8393 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8394 {
8395         int deformindex;
8396         int firsttriangle;
8397         int numtriangles;
8398         int firstvertex;
8399         int endvertex;
8400         int numvertices;
8401         int surfacefirsttriangle;
8402         int surfacenumtriangles;
8403         int surfacefirstvertex;
8404         int surfaceendvertex;
8405         int surfacenumvertices;
8406         int batchnumvertices;
8407         int batchnumtriangles;
8408         int needsupdate;
8409         int i, j;
8410         qboolean gaps;
8411         qboolean dynamicvertex;
8412         float amplitude;
8413         float animpos;
8414         float scale;
8415         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8416         float waveparms[4];
8417         q3shaderinfo_deform_t *deform;
8418         const msurface_t *surface, *firstsurface;
8419         r_vertexmesh_t *vertexmesh;
8420         if (!texturenumsurfaces)
8421                 return;
8422         // find vertex range of this surface batch
8423         gaps = false;
8424         firstsurface = texturesurfacelist[0];
8425         firsttriangle = firstsurface->num_firsttriangle;
8426         batchnumvertices = 0;
8427         batchnumtriangles = 0;
8428         firstvertex = endvertex = firstsurface->num_firstvertex;
8429         for (i = 0;i < texturenumsurfaces;i++)
8430         {
8431                 surface = texturesurfacelist[i];
8432                 if (surface != firstsurface + i)
8433                         gaps = true;
8434                 surfacefirstvertex = surface->num_firstvertex;
8435                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8436                 surfacenumvertices = surface->num_vertices;
8437                 surfacenumtriangles = surface->num_triangles;
8438                 if (firstvertex > surfacefirstvertex)
8439                         firstvertex = surfacefirstvertex;
8440                 if (endvertex < surfaceendvertex)
8441                         endvertex = surfaceendvertex;
8442                 batchnumvertices += surfacenumvertices;
8443                 batchnumtriangles += surfacenumtriangles;
8444         }
8445
8446         // we now know the vertex range used, and if there are any gaps in it
8447         rsurface.batchfirstvertex = firstvertex;
8448         rsurface.batchnumvertices = endvertex - firstvertex;
8449         rsurface.batchfirsttriangle = firsttriangle;
8450         rsurface.batchnumtriangles = batchnumtriangles;
8451
8452         // this variable holds flags for which properties have been updated that
8453         // may require regenerating vertexmesh array...
8454         needsupdate = 0;
8455
8456         // check if any dynamic vertex processing must occur
8457         dynamicvertex = false;
8458
8459         // if there is a chance of animated vertex colors, it's a dynamic batch
8460         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8461         {
8462                 dynamicvertex = true;
8463                 batchneed |= BATCHNEED_NOGAPS;
8464                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8465         }
8466
8467         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8468         {
8469                 switch (deform->deform)
8470                 {
8471                 default:
8472                 case Q3DEFORM_PROJECTIONSHADOW:
8473                 case Q3DEFORM_TEXT0:
8474                 case Q3DEFORM_TEXT1:
8475                 case Q3DEFORM_TEXT2:
8476                 case Q3DEFORM_TEXT3:
8477                 case Q3DEFORM_TEXT4:
8478                 case Q3DEFORM_TEXT5:
8479                 case Q3DEFORM_TEXT6:
8480                 case Q3DEFORM_TEXT7:
8481                 case Q3DEFORM_NONE:
8482                         break;
8483                 case Q3DEFORM_AUTOSPRITE:
8484                         dynamicvertex = true;
8485                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8486                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8487                         break;
8488                 case Q3DEFORM_AUTOSPRITE2:
8489                         dynamicvertex = true;
8490                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8491                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8492                         break;
8493                 case Q3DEFORM_NORMAL:
8494                         dynamicvertex = true;
8495                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8496                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8497                         break;
8498                 case Q3DEFORM_WAVE:
8499                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8500                                 break; // if wavefunc is a nop, ignore this transform
8501                         dynamicvertex = true;
8502                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8503                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8504                         break;
8505                 case Q3DEFORM_BULGE:
8506                         dynamicvertex = true;
8507                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8508                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8509                         break;
8510                 case Q3DEFORM_MOVE:
8511                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8512                                 break; // if wavefunc is a nop, ignore this transform
8513                         dynamicvertex = true;
8514                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8515                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8516                         break;
8517                 }
8518         }
8519         switch(rsurface.texture->tcgen.tcgen)
8520         {
8521         default:
8522         case Q3TCGEN_TEXTURE:
8523                 break;
8524         case Q3TCGEN_LIGHTMAP:
8525                 dynamicvertex = true;
8526                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8527                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8528                 break;
8529         case Q3TCGEN_VECTOR:
8530                 dynamicvertex = true;
8531                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8532                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8533                 break;
8534         case Q3TCGEN_ENVIRONMENT:
8535                 dynamicvertex = true;
8536                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8537                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8538                 break;
8539         }
8540         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8541         {
8542                 dynamicvertex = true;
8543                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8544                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8545         }
8546
8547         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8548         {
8549                 dynamicvertex = true;
8550                 batchneed |= BATCHNEED_NOGAPS;
8551                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8552         }
8553
8554         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8555         {
8556                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8557                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8558                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8559                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8560                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8561                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8562                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8563         }
8564
8565         // when the model data has no vertex buffer (dynamic mesh), we need to
8566         // eliminate gaps
8567         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8568                 batchneed |= BATCHNEED_NOGAPS;
8569
8570         // if needsupdate, we have to do a dynamic vertex batch for sure
8571         if (needsupdate & batchneed)
8572                 dynamicvertex = true;
8573
8574         // see if we need to build vertexmesh from arrays
8575         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8576                 dynamicvertex = true;
8577
8578         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8579         // also some drivers strongly dislike firstvertex
8580         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8581                 dynamicvertex = true;
8582
8583         rsurface.batchvertex3f = rsurface.modelvertex3f;
8584         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8585         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8586         rsurface.batchsvector3f = rsurface.modelsvector3f;
8587         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8588         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8589         rsurface.batchtvector3f = rsurface.modeltvector3f;
8590         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8591         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8592         rsurface.batchnormal3f = rsurface.modelnormal3f;
8593         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8594         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8595         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8596         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8597         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8598         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8599         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8600         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8601         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8602         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8603         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8604         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8605         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8606         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8607         rsurface.batchelement3i = rsurface.modelelement3i;
8608         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8609         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8610         rsurface.batchelement3s = rsurface.modelelement3s;
8611         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8612         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8613
8614         // if any dynamic vertex processing has to occur in software, we copy the
8615         // entire surface list together before processing to rebase the vertices
8616         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8617         //
8618         // if any gaps exist and we do not have a static vertex buffer, we have to
8619         // copy the surface list together to avoid wasting upload bandwidth on the
8620         // vertices in the gaps.
8621         //
8622         // if gaps exist and we have a static vertex buffer, we still have to
8623         // combine the index buffer ranges into one dynamic index buffer.
8624         //
8625         // in all cases we end up with data that can be drawn in one call.
8626
8627         if (!dynamicvertex)
8628         {
8629                 // static vertex data, just set pointers...
8630                 rsurface.batchgeneratedvertex = false;
8631                 // if there are gaps, we want to build a combined index buffer,
8632                 // otherwise use the original static buffer with an appropriate offset
8633                 if (gaps)
8634                 {
8635                         // build a new triangle elements array for this batch
8636                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8637                         rsurface.batchfirsttriangle = 0;
8638                         numtriangles = 0;
8639                         for (i = 0;i < texturenumsurfaces;i++)
8640                         {
8641                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8642                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8643                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8644                                 numtriangles += surfacenumtriangles;
8645                         }
8646                         rsurface.batchelement3i_indexbuffer = NULL;
8647                         rsurface.batchelement3i_bufferoffset = 0;
8648                         rsurface.batchelement3s = NULL;
8649                         rsurface.batchelement3s_indexbuffer = NULL;
8650                         rsurface.batchelement3s_bufferoffset = 0;
8651                         if (endvertex <= 65536)
8652                         {
8653                                 // make a 16bit (unsigned short) index array if possible
8654                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8655                                 for (i = 0;i < numtriangles*3;i++)
8656                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8657                         }
8658                 }
8659                 return;
8660         }
8661
8662         // something needs software processing, do it for real...
8663         // we only directly handle separate array data in this case and then
8664         // generate interleaved data if needed...
8665         rsurface.batchgeneratedvertex = true;
8666
8667         // now copy the vertex data into a combined array and make an index array
8668         // (this is what Quake3 does all the time)
8669         //if (gaps || rsurface.batchfirstvertex)
8670         {
8671                 rsurface.batchvertex3fbuffer = NULL;
8672                 rsurface.batchvertexmesh = NULL;
8673                 rsurface.batchvertexmeshbuffer = NULL;
8674                 rsurface.batchvertex3f = NULL;
8675                 rsurface.batchvertex3f_vertexbuffer = NULL;
8676                 rsurface.batchvertex3f_bufferoffset = 0;
8677                 rsurface.batchsvector3f = NULL;
8678                 rsurface.batchsvector3f_vertexbuffer = NULL;
8679                 rsurface.batchsvector3f_bufferoffset = 0;
8680                 rsurface.batchtvector3f = NULL;
8681                 rsurface.batchtvector3f_vertexbuffer = NULL;
8682                 rsurface.batchtvector3f_bufferoffset = 0;
8683                 rsurface.batchnormal3f = NULL;
8684                 rsurface.batchnormal3f_vertexbuffer = NULL;
8685                 rsurface.batchnormal3f_bufferoffset = 0;
8686                 rsurface.batchlightmapcolor4f = NULL;
8687                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8688                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8689                 rsurface.batchtexcoordtexture2f = NULL;
8690                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8691                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8692                 rsurface.batchtexcoordlightmap2f = NULL;
8693                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8694                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8695                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8696                 rsurface.batchelement3i_indexbuffer = NULL;
8697                 rsurface.batchelement3i_bufferoffset = 0;
8698                 rsurface.batchelement3s = NULL;
8699                 rsurface.batchelement3s_indexbuffer = NULL;
8700                 rsurface.batchelement3s_bufferoffset = 0;
8701                 // we'll only be setting up certain arrays as needed
8702                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8703                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8704                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8705                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8706                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8707                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8708                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8709                 {
8710                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8711                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8712                 }
8713                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8714                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8715                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8716                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8717                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8718                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8719                 numvertices = 0;
8720                 numtriangles = 0;
8721                 for (i = 0;i < texturenumsurfaces;i++)
8722                 {
8723                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8724                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8725                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8726                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8727                         // copy only the data requested
8728                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8729                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8730                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8731                         {
8732                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8733                                 {
8734                                         if (rsurface.batchvertex3f)
8735                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8736                                         else
8737                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8738                                 }
8739                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8740                                 {
8741                                         if (rsurface.modelnormal3f)
8742                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8743                                         else
8744                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8745                                 }
8746                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8747                                 {
8748                                         if (rsurface.modelsvector3f)
8749                                         {
8750                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8751                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8752                                         }
8753                                         else
8754                                         {
8755                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8756                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8757                                         }
8758                                 }
8759                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8760                                 {
8761                                         if (rsurface.modellightmapcolor4f)
8762                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8763                                         else
8764                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8765                                 }
8766                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8767                                 {
8768                                         if (rsurface.modeltexcoordtexture2f)
8769                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8770                                         else
8771                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8772                                 }
8773                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8774                                 {
8775                                         if (rsurface.modeltexcoordlightmap2f)
8776                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8777                                         else
8778                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8779                                 }
8780                         }
8781                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8782                         numvertices += surfacenumvertices;
8783                         numtriangles += surfacenumtriangles;
8784                 }
8785
8786                 // generate a 16bit index array as well if possible
8787                 // (in general, dynamic batches fit)
8788                 if (numvertices <= 65536)
8789                 {
8790                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8791                         for (i = 0;i < numtriangles*3;i++)
8792                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8793                 }
8794
8795                 // since we've copied everything, the batch now starts at 0
8796                 rsurface.batchfirstvertex = 0;
8797                 rsurface.batchnumvertices = batchnumvertices;
8798                 rsurface.batchfirsttriangle = 0;
8799                 rsurface.batchnumtriangles = batchnumtriangles;
8800         }
8801
8802         // q1bsp surfaces rendered in vertex color mode have to have colors
8803         // calculated based on lightstyles
8804         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8805         {
8806                 // generate color arrays for the surfaces in this list
8807                 int c[4];
8808                 int scale;
8809                 int size3;
8810                 const int *offsets;
8811                 const unsigned char *lm;
8812                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8813                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8814                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8815                 numvertices = 0;
8816                 for (i = 0;i < texturenumsurfaces;i++)
8817                 {
8818                         surface = texturesurfacelist[i];
8819                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8820                         surfacenumvertices = surface->num_vertices;
8821                         if (surface->lightmapinfo->samples)
8822                         {
8823                                 for (j = 0;j < surfacenumvertices;j++)
8824                                 {
8825                                         lm = surface->lightmapinfo->samples + offsets[j];
8826                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8827                                         VectorScale(lm, scale, c);
8828                                         if (surface->lightmapinfo->styles[1] != 255)
8829                                         {
8830                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8831                                                 lm += size3;
8832                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8833                                                 VectorMA(c, scale, lm, c);
8834                                                 if (surface->lightmapinfo->styles[2] != 255)
8835                                                 {
8836                                                         lm += size3;
8837                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8838                                                         VectorMA(c, scale, lm, c);
8839                                                         if (surface->lightmapinfo->styles[3] != 255)
8840                                                         {
8841                                                                 lm += size3;
8842                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8843                                                                 VectorMA(c, scale, lm, c);
8844                                                         }
8845                                                 }
8846                                         }
8847                                         c[0] >>= 7;
8848                                         c[1] >>= 7;
8849                                         c[2] >>= 7;
8850                                         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);
8851                                         numvertices++;
8852                                 }
8853                         }
8854                         else
8855                         {
8856                                 for (j = 0;j < surfacenumvertices;j++)
8857                                 {
8858                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8859                                         numvertices++;
8860                                 }
8861                         }
8862                 }
8863         }
8864
8865         // if vertices are deformed (sprite flares and things in maps, possibly
8866         // water waves, bulges and other deformations), modify the copied vertices
8867         // in place
8868         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8869         {
8870                 switch (deform->deform)
8871                 {
8872                 default:
8873                 case Q3DEFORM_PROJECTIONSHADOW:
8874                 case Q3DEFORM_TEXT0:
8875                 case Q3DEFORM_TEXT1:
8876                 case Q3DEFORM_TEXT2:
8877                 case Q3DEFORM_TEXT3:
8878                 case Q3DEFORM_TEXT4:
8879                 case Q3DEFORM_TEXT5:
8880                 case Q3DEFORM_TEXT6:
8881                 case Q3DEFORM_TEXT7:
8882                 case Q3DEFORM_NONE:
8883                         break;
8884                 case Q3DEFORM_AUTOSPRITE:
8885                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8886                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8887                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8888                         VectorNormalize(newforward);
8889                         VectorNormalize(newright);
8890                         VectorNormalize(newup);
8891 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8892 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8893 //                      rsurface.batchvertex3f_bufferoffset = 0;
8894 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8895 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8896 //                      rsurface.batchsvector3f_bufferoffset = 0;
8897 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8898 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8899 //                      rsurface.batchtvector3f_bufferoffset = 0;
8900 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8901 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8902 //                      rsurface.batchnormal3f_bufferoffset = 0;
8903                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
8904                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
8905                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8906                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
8907                                 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);
8908                         // a single autosprite surface can contain multiple sprites...
8909                         for (j = 0;j < batchnumvertices - 3;j += 4)
8910                         {
8911                                 VectorClear(center);
8912                                 for (i = 0;i < 4;i++)
8913                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8914                                 VectorScale(center, 0.25f, center);
8915                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
8916                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
8917                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
8918                                 for (i = 0;i < 4;i++)
8919                                 {
8920                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
8921                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
8922                                 }
8923                         }
8924                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
8925                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
8926                         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);
8927                         break;
8928                 case Q3DEFORM_AUTOSPRITE2:
8929                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8930                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8931                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8932                         VectorNormalize(newforward);
8933                         VectorNormalize(newright);
8934                         VectorNormalize(newup);
8935 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8936 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8937 //                      rsurface.batchvertex3f_bufferoffset = 0;
8938                         {
8939                                 const float *v1, *v2;
8940                                 vec3_t start, end;
8941                                 float f, l;
8942                                 struct
8943                                 {
8944                                         float length2;
8945                                         const float *v1;
8946                                         const float *v2;
8947                                 }
8948                                 shortest[2];
8949                                 memset(shortest, 0, sizeof(shortest));
8950                                 // a single autosprite surface can contain multiple sprites...
8951                                 for (j = 0;j < batchnumvertices - 3;j += 4)
8952                                 {
8953                                         VectorClear(center);
8954                                         for (i = 0;i < 4;i++)
8955                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
8956                                         VectorScale(center, 0.25f, center);
8957                                         // find the two shortest edges, then use them to define the
8958                                         // axis vectors for rotating around the central axis
8959                                         for (i = 0;i < 6;i++)
8960                                         {
8961                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
8962                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
8963                                                 l = VectorDistance2(v1, v2);
8964                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
8965                                                 if (v1[2] != v2[2])
8966                                                         l += (1.0f / 1024.0f);
8967                                                 if (shortest[0].length2 > l || i == 0)
8968                                                 {
8969                                                         shortest[1] = shortest[0];
8970                                                         shortest[0].length2 = l;
8971                                                         shortest[0].v1 = v1;
8972                                                         shortest[0].v2 = v2;
8973                                                 }
8974                                                 else if (shortest[1].length2 > l || i == 1)
8975                                                 {
8976                                                         shortest[1].length2 = l;
8977                                                         shortest[1].v1 = v1;
8978                                                         shortest[1].v2 = v2;
8979                                                 }
8980                                         }
8981                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
8982                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
8983                                         // this calculates the right vector from the shortest edge
8984                                         // and the up vector from the edge midpoints
8985                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
8986                                         VectorNormalize(right);
8987                                         VectorSubtract(end, start, up);
8988                                         VectorNormalize(up);
8989                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
8990                                         VectorSubtract(rsurface.localvieworigin, center, forward);
8991                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
8992                                         VectorNegate(forward, forward);
8993                                         VectorReflect(forward, 0, up, forward);
8994                                         VectorNormalize(forward);
8995                                         CrossProduct(up, forward, newright);
8996                                         VectorNormalize(newright);
8997                                         // rotate the quad around the up axis vector, this is made
8998                                         // especially easy by the fact we know the quad is flat,
8999                                         // so we only have to subtract the center position and
9000                                         // measure distance along the right vector, and then
9001                                         // multiply that by the newright vector and add back the
9002                                         // center position
9003                                         // we also need to subtract the old position to undo the
9004                                         // displacement from the center, which we do with a
9005                                         // DotProduct, the subtraction/addition of center is also
9006                                         // optimized into DotProducts here
9007                                         l = DotProduct(right, center);
9008                                         for (i = 0;i < 4;i++)
9009                                         {
9010                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9011                                                 f = DotProduct(right, v1) - l;
9012                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9013                                         }
9014                                 }
9015                         }
9016                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9017                         {
9018 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9019 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9020 //                              rsurface.batchnormal3f_bufferoffset = 0;
9021                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9022                         }
9023                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9024                         {
9025 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9026 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9027 //                              rsurface.batchsvector3f_bufferoffset = 0;
9028 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9029 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9030 //                              rsurface.batchtvector3f_bufferoffset = 0;
9031                                 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);
9032                         }
9033                         break;
9034                 case Q3DEFORM_NORMAL:
9035                         // deform the normals to make reflections wavey
9036                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9037                         rsurface.batchnormal3f_vertexbuffer = NULL;
9038                         rsurface.batchnormal3f_bufferoffset = 0;
9039                         for (j = 0;j < batchnumvertices;j++)
9040                         {
9041                                 float vertex[3];
9042                                 float *normal = rsurface.batchnormal3f + 3*j;
9043                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9044                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9045                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9046                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9047                                 VectorNormalize(normal);
9048                         }
9049                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9050                         {
9051 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9052 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9053 //                              rsurface.batchsvector3f_bufferoffset = 0;
9054 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9055 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9056 //                              rsurface.batchtvector3f_bufferoffset = 0;
9057                                 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);
9058                         }
9059                         break;
9060                 case Q3DEFORM_WAVE:
9061                         // deform vertex array to make wavey water and flags and such
9062                         waveparms[0] = deform->waveparms[0];
9063                         waveparms[1] = deform->waveparms[1];
9064                         waveparms[2] = deform->waveparms[2];
9065                         waveparms[3] = deform->waveparms[3];
9066                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9067                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9068                         // this is how a divisor of vertex influence on deformation
9069                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9070                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9071 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9072 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9073 //                      rsurface.batchvertex3f_bufferoffset = 0;
9074 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9075 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9076 //                      rsurface.batchnormal3f_bufferoffset = 0;
9077                         for (j = 0;j < batchnumvertices;j++)
9078                         {
9079                                 // if the wavefunc depends on time, evaluate it per-vertex
9080                                 if (waveparms[3])
9081                                 {
9082                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9083                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9084                                 }
9085                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9086                         }
9087                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9088                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9089                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9090                         {
9091 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9092 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9093 //                              rsurface.batchsvector3f_bufferoffset = 0;
9094 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9095 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9096 //                              rsurface.batchtvector3f_bufferoffset = 0;
9097                                 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);
9098                         }
9099                         break;
9100                 case Q3DEFORM_BULGE:
9101                         // deform vertex array to make the surface have moving bulges
9102 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9103 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9104 //                      rsurface.batchvertex3f_bufferoffset = 0;
9105 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9106 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9107 //                      rsurface.batchnormal3f_bufferoffset = 0;
9108                         for (j = 0;j < batchnumvertices;j++)
9109                         {
9110                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9111                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9112                         }
9113                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9114                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9115                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9116                         {
9117 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9118 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9119 //                              rsurface.batchsvector3f_bufferoffset = 0;
9120 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9121 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9122 //                              rsurface.batchtvector3f_bufferoffset = 0;
9123                                 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);
9124                         }
9125                         break;
9126                 case Q3DEFORM_MOVE:
9127                         // deform vertex array
9128                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9129                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9130                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9131                         VectorScale(deform->parms, scale, waveparms);
9132 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9133 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9134 //                      rsurface.batchvertex3f_bufferoffset = 0;
9135                         for (j = 0;j < batchnumvertices;j++)
9136                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9137                         break;
9138                 }
9139         }
9140
9141         // generate texcoords based on the chosen texcoord source
9142         switch(rsurface.texture->tcgen.tcgen)
9143         {
9144         default:
9145         case Q3TCGEN_TEXTURE:
9146                 break;
9147         case Q3TCGEN_LIGHTMAP:
9148 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9149 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9150 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9151                 if (rsurface.batchtexcoordlightmap2f)
9152                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9153                 break;
9154         case Q3TCGEN_VECTOR:
9155 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9156 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9157 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9158                 for (j = 0;j < batchnumvertices;j++)
9159                 {
9160                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9161                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9162                 }
9163                 break;
9164         case Q3TCGEN_ENVIRONMENT:
9165                 // make environment reflections using a spheremap
9166                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9167                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9168                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9169                 for (j = 0;j < batchnumvertices;j++)
9170                 {
9171                         // identical to Q3A's method, but executed in worldspace so
9172                         // carried models can be shiny too
9173
9174                         float viewer[3], d, reflected[3], worldreflected[3];
9175
9176                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9177                         // VectorNormalize(viewer);
9178
9179                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9180
9181                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9182                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9183                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9184                         // note: this is proportinal to viewer, so we can normalize later
9185
9186                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9187                         VectorNormalize(worldreflected);
9188
9189                         // note: this sphere map only uses world x and z!
9190                         // so positive and negative y will LOOK THE SAME.
9191                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9192                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9193                 }
9194                 break;
9195         }
9196         // the only tcmod that needs software vertex processing is turbulent, so
9197         // check for it here and apply the changes if needed
9198         // and we only support that as the first one
9199         // (handling a mixture of turbulent and other tcmods would be problematic
9200         //  without punting it entirely to a software path)
9201         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9202         {
9203                 amplitude = rsurface.texture->tcmods[0].parms[1];
9204                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9205 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9206 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9207 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9208                 for (j = 0;j < batchnumvertices;j++)
9209                 {
9210                         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);
9211                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9212                 }
9213         }
9214
9215         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9216         {
9217                 // convert the modified arrays to vertex structs
9218 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9219 //              rsurface.batchvertexmeshbuffer = NULL;
9220                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9221                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9222                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9223                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9224                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9225                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9226                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9227                 {
9228                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9229                         {
9230                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9231                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9232                         }
9233                 }
9234                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9235                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9236                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9237                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9238                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9239                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9240                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9241                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9242                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9243         }
9244 }
9245
9246 void RSurf_DrawBatch(void)
9247 {
9248         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9249         // through the pipeline, killing it earlier in the pipeline would have
9250         // per-surface overhead rather than per-batch overhead, so it's best to
9251         // reject it here, before it hits glDraw.
9252         if (rsurface.batchnumtriangles == 0)
9253                 return;
9254 #if 0
9255         // batch debugging code
9256         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9257         {
9258                 int i;
9259                 int j;
9260                 int c;
9261                 const int *e;
9262                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9263                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9264                 {
9265                         c = e[i];
9266                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9267                         {
9268                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9269                                 {
9270                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9271                                                 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);
9272                                         break;
9273                                 }
9274                         }
9275                 }
9276         }
9277 #endif
9278         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);
9279 }
9280
9281 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9282 {
9283         // pick the closest matching water plane
9284         int planeindex, vertexindex, bestplaneindex = -1;
9285         float d, bestd;
9286         vec3_t vert;
9287         const float *v;
9288         r_waterstate_waterplane_t *p;
9289         qboolean prepared = false;
9290         bestd = 0;
9291         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9292         {
9293                 if(p->camera_entity != rsurface.texture->camera_entity)
9294                         continue;
9295                 d = 0;
9296                 if(!prepared)
9297                 {
9298                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9299                         prepared = true;
9300                         if(rsurface.batchnumvertices == 0)
9301                                 break;
9302                 }
9303                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9304                 {
9305                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9306                         d += fabs(PlaneDiff(vert, &p->plane));
9307                 }
9308                 if (bestd > d || bestplaneindex < 0)
9309                 {
9310                         bestd = d;
9311                         bestplaneindex = planeindex;
9312                 }
9313         }
9314         return bestplaneindex;
9315         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9316         // this situation though, as it might be better to render single larger
9317         // batches with useless stuff (backface culled for example) than to
9318         // render multiple smaller batches
9319 }
9320
9321 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9322 {
9323         int i;
9324         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9325         rsurface.passcolor4f_vertexbuffer = 0;
9326         rsurface.passcolor4f_bufferoffset = 0;
9327         for (i = 0;i < rsurface.batchnumvertices;i++)
9328                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9329 }
9330
9331 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9332 {
9333         int i;
9334         float f;
9335         const float *v;
9336         const float *c;
9337         float *c2;
9338         if (rsurface.passcolor4f)
9339         {
9340                 // generate color arrays
9341                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9342                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9343                 rsurface.passcolor4f_vertexbuffer = 0;
9344                 rsurface.passcolor4f_bufferoffset = 0;
9345                 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)
9346                 {
9347                         f = RSurf_FogVertex(v);
9348                         c2[0] = c[0] * f;
9349                         c2[1] = c[1] * f;
9350                         c2[2] = c[2] * f;
9351                         c2[3] = c[3];
9352                 }
9353         }
9354         else
9355         {
9356                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9357                 rsurface.passcolor4f_vertexbuffer = 0;
9358                 rsurface.passcolor4f_bufferoffset = 0;
9359                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9360                 {
9361                         f = RSurf_FogVertex(v);
9362                         c2[0] = f;
9363                         c2[1] = f;
9364                         c2[2] = f;
9365                         c2[3] = 1;
9366                 }
9367         }
9368 }
9369
9370 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9371 {
9372         int i;
9373         float f;
9374         const float *v;
9375         const float *c;
9376         float *c2;
9377         if (!rsurface.passcolor4f)
9378                 return;
9379         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9380         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9381         rsurface.passcolor4f_vertexbuffer = 0;
9382         rsurface.passcolor4f_bufferoffset = 0;
9383         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)
9384         {
9385                 f = RSurf_FogVertex(v);
9386                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9387                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9388                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9389                 c2[3] = c[3];
9390         }
9391 }
9392
9393 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9394 {
9395         int i;
9396         const float *c;
9397         float *c2;
9398         if (!rsurface.passcolor4f)
9399                 return;
9400         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9401         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9402         rsurface.passcolor4f_vertexbuffer = 0;
9403         rsurface.passcolor4f_bufferoffset = 0;
9404         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9405         {
9406                 c2[0] = c[0] * r;
9407                 c2[1] = c[1] * g;
9408                 c2[2] = c[2] * b;
9409                 c2[3] = c[3] * a;
9410         }
9411 }
9412
9413 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9414 {
9415         int i;
9416         const float *c;
9417         float *c2;
9418         if (!rsurface.passcolor4f)
9419                 return;
9420         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9421         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9422         rsurface.passcolor4f_vertexbuffer = 0;
9423         rsurface.passcolor4f_bufferoffset = 0;
9424         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9425         {
9426                 c2[0] = c[0] + r_refdef.scene.ambient;
9427                 c2[1] = c[1] + r_refdef.scene.ambient;
9428                 c2[2] = c[2] + r_refdef.scene.ambient;
9429                 c2[3] = c[3];
9430         }
9431 }
9432
9433 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9434 {
9435         // TODO: optimize
9436         rsurface.passcolor4f = NULL;
9437         rsurface.passcolor4f_vertexbuffer = 0;
9438         rsurface.passcolor4f_bufferoffset = 0;
9439         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9440         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9441         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9442         GL_Color(r, g, b, a);
9443         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9444         RSurf_DrawBatch();
9445 }
9446
9447 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9448 {
9449         // TODO: optimize applyfog && applycolor case
9450         // just apply fog if necessary, and tint the fog color array if necessary
9451         rsurface.passcolor4f = NULL;
9452         rsurface.passcolor4f_vertexbuffer = 0;
9453         rsurface.passcolor4f_bufferoffset = 0;
9454         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9455         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9456         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9457         GL_Color(r, g, b, a);
9458         RSurf_DrawBatch();
9459 }
9460
9461 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9462 {
9463         // TODO: optimize
9464         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9465         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9466         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9467         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9468         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9469         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9470         GL_Color(r, g, b, a);
9471         RSurf_DrawBatch();
9472 }
9473
9474 static void RSurf_DrawBatch_GL11_ClampColor(void)
9475 {
9476         int i;
9477         const float *c1;
9478         float *c2;
9479         if (!rsurface.passcolor4f)
9480                 return;
9481         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9482         {
9483                 c2[0] = bound(0.0f, c1[0], 1.0f);
9484                 c2[1] = bound(0.0f, c1[1], 1.0f);
9485                 c2[2] = bound(0.0f, c1[2], 1.0f);
9486                 c2[3] = bound(0.0f, c1[3], 1.0f);
9487         }
9488 }
9489
9490 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9491 {
9492         int i;
9493         float f;
9494         const float *v;
9495         const float *n;
9496         float *c;
9497         //vec3_t eyedir;
9498
9499         // fake shading
9500         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9501         rsurface.passcolor4f_vertexbuffer = 0;
9502         rsurface.passcolor4f_bufferoffset = 0;
9503         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)
9504         {
9505                 f = -DotProduct(r_refdef.view.forward, n);
9506                 f = max(0, f);
9507                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9508                 f *= r_refdef.lightmapintensity;
9509                 Vector4Set(c, f, f, f, 1);
9510         }
9511 }
9512
9513 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9514 {
9515         RSurf_DrawBatch_GL11_ApplyFakeLight();
9516         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9517         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9518         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9519         GL_Color(r, g, b, a);
9520         RSurf_DrawBatch();
9521 }
9522
9523 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9524 {
9525         int i;
9526         float f;
9527         float alpha;
9528         const float *v;
9529         const float *n;
9530         float *c;
9531         vec3_t ambientcolor;
9532         vec3_t diffusecolor;
9533         vec3_t lightdir;
9534         // TODO: optimize
9535         // model lighting
9536         VectorCopy(rsurface.modellight_lightdir, lightdir);
9537         f = 0.5f * r_refdef.lightmapintensity;
9538         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9539         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9540         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9541         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9542         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9543         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9544         alpha = *a;
9545         if (VectorLength2(diffusecolor) > 0)
9546         {
9547                 // q3-style directional shading
9548                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9549                 rsurface.passcolor4f_vertexbuffer = 0;
9550                 rsurface.passcolor4f_bufferoffset = 0;
9551                 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)
9552                 {
9553                         if ((f = DotProduct(n, lightdir)) > 0)
9554                                 VectorMA(ambientcolor, f, diffusecolor, c);
9555                         else
9556                                 VectorCopy(ambientcolor, c);
9557                         c[3] = alpha;
9558                 }
9559                 *r = 1;
9560                 *g = 1;
9561                 *b = 1;
9562                 *a = 1;
9563                 *applycolor = false;
9564         }
9565         else
9566         {
9567                 *r = ambientcolor[0];
9568                 *g = ambientcolor[1];
9569                 *b = ambientcolor[2];
9570                 rsurface.passcolor4f = NULL;
9571                 rsurface.passcolor4f_vertexbuffer = 0;
9572                 rsurface.passcolor4f_bufferoffset = 0;
9573         }
9574 }
9575
9576 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9577 {
9578         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9579         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9580         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9581         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9582         GL_Color(r, g, b, a);
9583         RSurf_DrawBatch();
9584 }
9585
9586 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9587 {
9588         int i;
9589         float f;
9590         const float *v;
9591         float *c;
9592
9593         // fake shading
9594         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9595         rsurface.passcolor4f_vertexbuffer = 0;
9596         rsurface.passcolor4f_bufferoffset = 0;
9597
9598         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9599         {
9600                 f = 1 - RSurf_FogVertex(v);
9601                 c[0] = r;
9602                 c[1] = g;
9603                 c[2] = b;
9604                 c[3] = f * a;
9605         }
9606 }
9607
9608 void RSurf_SetupDepthAndCulling(void)
9609 {
9610         // submodels are biased to avoid z-fighting with world surfaces that they
9611         // may be exactly overlapping (avoids z-fighting artifacts on certain
9612         // doors and things in Quake maps)
9613         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9614         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9615         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9616         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9617 }
9618
9619 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9620 {
9621         // transparent sky would be ridiculous
9622         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9623                 return;
9624         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9625         skyrenderlater = true;
9626         RSurf_SetupDepthAndCulling();
9627         GL_DepthMask(true);
9628         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9629         // skymasking on them, and Quake3 never did sky masking (unlike
9630         // software Quake and software Quake2), so disable the sky masking
9631         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9632         // and skymasking also looks very bad when noclipping outside the
9633         // level, so don't use it then either.
9634         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9635         {
9636                 R_Mesh_ResetTextureState();
9637                 if (skyrendermasked)
9638                 {
9639                         R_SetupShader_DepthOrShadow(false);
9640                         // depth-only (masking)
9641                         GL_ColorMask(0,0,0,0);
9642                         // just to make sure that braindead drivers don't draw
9643                         // anything despite that colormask...
9644                         GL_BlendFunc(GL_ZERO, GL_ONE);
9645                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9646                         if (rsurface.batchvertex3fbuffer)
9647                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9648                         else
9649                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9650                 }
9651                 else
9652                 {
9653                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9654                         // fog sky
9655                         GL_BlendFunc(GL_ONE, GL_ZERO);
9656                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9657                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9658                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9659                 }
9660                 RSurf_DrawBatch();
9661                 if (skyrendermasked)
9662                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9663         }
9664         R_Mesh_ResetTextureState();
9665         GL_Color(1, 1, 1, 1);
9666 }
9667
9668 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9669 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9670 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9671 {
9672         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9673                 return;
9674         if (prepass)
9675         {
9676                 // render screenspace normalmap to texture
9677                 GL_DepthMask(true);
9678                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9679                 RSurf_DrawBatch();
9680         }
9681
9682         // bind lightmap texture
9683
9684         // water/refraction/reflection/camera surfaces have to be handled specially
9685         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9686         {
9687                 int start, end, startplaneindex;
9688                 for (start = 0;start < texturenumsurfaces;start = end)
9689                 {
9690                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9691                         if(startplaneindex < 0)
9692                         {
9693                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9694                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9695                                 end = start + 1;
9696                                 continue;
9697                         }
9698                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9699                                 ;
9700                         // now that we have a batch using the same planeindex, render it
9701                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9702                         {
9703                                 // render water or distortion background
9704                                 GL_DepthMask(true);
9705                                 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);
9706                                 RSurf_DrawBatch();
9707                                 // blend surface on top
9708                                 GL_DepthMask(false);
9709                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9710                                 RSurf_DrawBatch();
9711                         }
9712                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9713                         {
9714                                 // render surface with reflection texture as input
9715                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9716                                 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);
9717                                 RSurf_DrawBatch();
9718                         }
9719                 }
9720                 return;
9721         }
9722
9723         // render surface batch normally
9724         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9725         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);
9726         RSurf_DrawBatch();
9727 }
9728
9729 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9730 {
9731         // OpenGL 1.3 path - anything not completely ancient
9732         qboolean applycolor;
9733         qboolean applyfog;
9734         int layerindex;
9735         const texturelayer_t *layer;
9736         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);
9737         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9738
9739         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9740         {
9741                 vec4_t layercolor;
9742                 int layertexrgbscale;
9743                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9744                 {
9745                         if (layerindex == 0)
9746                                 GL_AlphaTest(true);
9747                         else
9748                         {
9749                                 GL_AlphaTest(false);
9750                                 GL_DepthFunc(GL_EQUAL);
9751                         }
9752                 }
9753                 GL_DepthMask(layer->depthmask && writedepth);
9754                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9755                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9756                 {
9757                         layertexrgbscale = 4;
9758                         VectorScale(layer->color, 0.25f, layercolor);
9759                 }
9760                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9761                 {
9762                         layertexrgbscale = 2;
9763                         VectorScale(layer->color, 0.5f, layercolor);
9764                 }
9765                 else
9766                 {
9767                         layertexrgbscale = 1;
9768                         VectorScale(layer->color, 1.0f, layercolor);
9769                 }
9770                 layercolor[3] = layer->color[3];
9771                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9772                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9773                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9774                 switch (layer->type)
9775                 {
9776                 case TEXTURELAYERTYPE_LITTEXTURE:
9777                         // single-pass lightmapped texture with 2x rgbscale
9778                         R_Mesh_TexBind(0, r_texture_white);
9779                         R_Mesh_TexMatrix(0, NULL);
9780                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9781                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9782                         R_Mesh_TexBind(1, layer->texture);
9783                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9784                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9785                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9786                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9787                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9788                         else if (FAKELIGHT_ENABLED)
9789                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9790                         else if (rsurface.uselightmaptexture)
9791                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9792                         else
9793                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9794                         break;
9795                 case TEXTURELAYERTYPE_TEXTURE:
9796                         // singletexture unlit texture with transparency support
9797                         R_Mesh_TexBind(0, layer->texture);
9798                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9799                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9800                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9801                         R_Mesh_TexBind(1, 0);
9802                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9803                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9804                         break;
9805                 case TEXTURELAYERTYPE_FOG:
9806                         // singletexture fogging
9807                         if (layer->texture)
9808                         {
9809                                 R_Mesh_TexBind(0, layer->texture);
9810                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9811                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9812                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9813                         }
9814                         else
9815                         {
9816                                 R_Mesh_TexBind(0, 0);
9817                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9818                         }
9819                         R_Mesh_TexBind(1, 0);
9820                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9821                         // generate a color array for the fog pass
9822                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9823                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9824                         RSurf_DrawBatch();
9825                         break;
9826                 default:
9827                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9828                 }
9829         }
9830         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9831         {
9832                 GL_DepthFunc(GL_LEQUAL);
9833                 GL_AlphaTest(false);
9834         }
9835 }
9836
9837 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9838 {
9839         // OpenGL 1.1 - crusty old voodoo path
9840         qboolean applyfog;
9841         int layerindex;
9842         const texturelayer_t *layer;
9843         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);
9844         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9845
9846         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9847         {
9848                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9849                 {
9850                         if (layerindex == 0)
9851                                 GL_AlphaTest(true);
9852                         else
9853                         {
9854                                 GL_AlphaTest(false);
9855                                 GL_DepthFunc(GL_EQUAL);
9856                         }
9857                 }
9858                 GL_DepthMask(layer->depthmask && writedepth);
9859                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9860                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9861                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9862                 switch (layer->type)
9863                 {
9864                 case TEXTURELAYERTYPE_LITTEXTURE:
9865                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9866                         {
9867                                 // two-pass lit texture with 2x rgbscale
9868                                 // first the lightmap pass
9869                                 R_Mesh_TexBind(0, r_texture_white);
9870                                 R_Mesh_TexMatrix(0, NULL);
9871                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9872                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9873                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9874                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9875                                 else if (FAKELIGHT_ENABLED)
9876                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9877                                 else if (rsurface.uselightmaptexture)
9878                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9879                                 else
9880                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9881                                 // then apply the texture to it
9882                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9883                                 R_Mesh_TexBind(0, layer->texture);
9884                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9885                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9886                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9887                                 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);
9888                         }
9889                         else
9890                         {
9891                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9892                                 R_Mesh_TexBind(0, layer->texture);
9893                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9894                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9895                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9896                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9897                                         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);
9898                                 else
9899                                         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);
9900                         }
9901                         break;
9902                 case TEXTURELAYERTYPE_TEXTURE:
9903                         // singletexture unlit texture with transparency support
9904                         R_Mesh_TexBind(0, layer->texture);
9905                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9906                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9907                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9908                         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);
9909                         break;
9910                 case TEXTURELAYERTYPE_FOG:
9911                         // singletexture fogging
9912                         if (layer->texture)
9913                         {
9914                                 R_Mesh_TexBind(0, layer->texture);
9915                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9916                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9917                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9918                         }
9919                         else
9920                         {
9921                                 R_Mesh_TexBind(0, 0);
9922                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9923                         }
9924                         // generate a color array for the fog pass
9925                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9926                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
9927                         RSurf_DrawBatch();
9928                         break;
9929                 default:
9930                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9931                 }
9932         }
9933         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9934         {
9935                 GL_DepthFunc(GL_LEQUAL);
9936                 GL_AlphaTest(false);
9937         }
9938 }
9939
9940 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9941 {
9942         int vi;
9943         int j;
9944         r_vertexgeneric_t *batchvertex;
9945         float c[4];
9946
9947 //      R_Mesh_ResetTextureState();
9948         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
9949
9950         if(rsurface.texture && rsurface.texture->currentskinframe)
9951         {
9952                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
9953                 c[3] *= rsurface.texture->currentalpha;
9954         }
9955         else
9956         {
9957                 c[0] = 1;
9958                 c[1] = 0;
9959                 c[2] = 1;
9960                 c[3] = 1;
9961         }
9962
9963         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
9964         {
9965                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
9966                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
9967                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
9968         }
9969
9970         // brighten it up (as texture value 127 means "unlit")
9971         c[0] *= 2 * r_refdef.view.colorscale;
9972         c[1] *= 2 * r_refdef.view.colorscale;
9973         c[2] *= 2 * r_refdef.view.colorscale;
9974
9975         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
9976                 c[3] *= r_wateralpha.value;
9977
9978         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
9979         {
9980                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
9981                 GL_DepthMask(false);
9982         }
9983         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
9984         {
9985                 GL_BlendFunc(GL_ONE, GL_ONE);
9986                 GL_DepthMask(false);
9987         }
9988         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9989         {
9990                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
9991                 GL_DepthMask(false);
9992         }
9993         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
9994         {
9995                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
9996                 GL_DepthMask(false);
9997         }
9998         else
9999         {
10000                 GL_BlendFunc(GL_ONE, GL_ZERO);
10001                 GL_DepthMask(writedepth);
10002         }
10003
10004         if (r_showsurfaces.integer == 3)
10005         {
10006                 rsurface.passcolor4f = NULL;
10007
10008                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10009                 {
10010                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10011
10012                         rsurface.passcolor4f = NULL;
10013                         rsurface.passcolor4f_vertexbuffer = 0;
10014                         rsurface.passcolor4f_bufferoffset = 0;
10015                 }
10016                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10017                 {
10018                         qboolean applycolor = true;
10019                         float one = 1.0;
10020
10021                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10022
10023                         r_refdef.lightmapintensity = 1;
10024                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10025                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10026                 }
10027                 else if (FAKELIGHT_ENABLED)
10028                 {
10029                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10030
10031                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10032                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10033                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10034                 }
10035                 else
10036                 {
10037                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10038
10039                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10040                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10041                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10042                 }
10043
10044                 if(!rsurface.passcolor4f)
10045                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10046
10047                 RSurf_DrawBatch_GL11_ApplyAmbient();
10048                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10049                 if(r_refdef.fogenabled)
10050                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10051                 RSurf_DrawBatch_GL11_ClampColor();
10052
10053                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10054                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10055                 RSurf_DrawBatch();
10056         }
10057         else if (!r_refdef.view.showdebug)
10058         {
10059                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10060                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10061                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10062                 {
10063                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10064                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10065                 }
10066                 R_Mesh_PrepareVertices_Generic_Unlock();
10067                 RSurf_DrawBatch();
10068         }
10069         else if (r_showsurfaces.integer == 4)
10070         {
10071                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10072                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10073                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10074                 {
10075                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10076                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10077                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10078                 }
10079                 R_Mesh_PrepareVertices_Generic_Unlock();
10080                 RSurf_DrawBatch();
10081         }
10082         else if (r_showsurfaces.integer == 2)
10083         {
10084                 const int *e;
10085                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10086                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10087                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10088                 {
10089                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10090                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10091                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10092                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10093                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10094                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10095                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10096                 }
10097                 R_Mesh_PrepareVertices_Generic_Unlock();
10098                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10099         }
10100         else
10101         {
10102                 int texturesurfaceindex;
10103                 int k;
10104                 const msurface_t *surface;
10105                 float surfacecolor4f[4];
10106                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10107                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10108                 vi = 0;
10109                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10110                 {
10111                         surface = texturesurfacelist[texturesurfaceindex];
10112                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10113                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10114                         for (j = 0;j < surface->num_vertices;j++)
10115                         {
10116                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10117                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10118                                 vi++;
10119                         }
10120                 }
10121                 R_Mesh_PrepareVertices_Generic_Unlock();
10122                 RSurf_DrawBatch();
10123         }
10124 }
10125
10126 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10127 {
10128         CHECKGLERROR
10129         RSurf_SetupDepthAndCulling();
10130         if (r_showsurfaces.integer)
10131         {
10132                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10133                 return;
10134         }
10135         switch (vid.renderpath)
10136         {
10137         case RENDERPATH_GL20:
10138         case RENDERPATH_D3D9:
10139         case RENDERPATH_D3D10:
10140         case RENDERPATH_D3D11:
10141         case RENDERPATH_SOFT:
10142         case RENDERPATH_GLES2:
10143                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10144                 break;
10145         case RENDERPATH_GL13:
10146         case RENDERPATH_GLES1:
10147                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10148                 break;
10149         case RENDERPATH_GL11:
10150                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10151                 break;
10152         }
10153         CHECKGLERROR
10154 }
10155
10156 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10157 {
10158         CHECKGLERROR
10159         RSurf_SetupDepthAndCulling();
10160         if (r_showsurfaces.integer)
10161         {
10162                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10163                 return;
10164         }
10165         switch (vid.renderpath)
10166         {
10167         case RENDERPATH_GL20:
10168         case RENDERPATH_D3D9:
10169         case RENDERPATH_D3D10:
10170         case RENDERPATH_D3D11:
10171         case RENDERPATH_SOFT:
10172         case RENDERPATH_GLES2:
10173                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10174                 break;
10175         case RENDERPATH_GL13:
10176         case RENDERPATH_GLES1:
10177                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10178                 break;
10179         case RENDERPATH_GL11:
10180                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10181                 break;
10182         }
10183         CHECKGLERROR
10184 }
10185
10186 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10187 {
10188         int i, j;
10189         int texturenumsurfaces, endsurface;
10190         texture_t *texture;
10191         const msurface_t *surface;
10192         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10193
10194         // if the model is static it doesn't matter what value we give for
10195         // wantnormals and wanttangents, so this logic uses only rules applicable
10196         // to a model, knowing that they are meaningless otherwise
10197         if (ent == r_refdef.scene.worldentity)
10198                 RSurf_ActiveWorldEntity();
10199         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10200                 RSurf_ActiveModelEntity(ent, false, false, false);
10201         else
10202         {
10203                 switch (vid.renderpath)
10204                 {
10205                 case RENDERPATH_GL20:
10206                 case RENDERPATH_D3D9:
10207                 case RENDERPATH_D3D10:
10208                 case RENDERPATH_D3D11:
10209                 case RENDERPATH_SOFT:
10210                 case RENDERPATH_GLES2:
10211                         RSurf_ActiveModelEntity(ent, true, true, false);
10212                         break;
10213                 case RENDERPATH_GL11:
10214                 case RENDERPATH_GL13:
10215                 case RENDERPATH_GLES1:
10216                         RSurf_ActiveModelEntity(ent, true, false, false);
10217                         break;
10218                 }
10219         }
10220
10221         if (r_transparentdepthmasking.integer)
10222         {
10223                 qboolean setup = false;
10224                 for (i = 0;i < numsurfaces;i = j)
10225                 {
10226                         j = i + 1;
10227                         surface = rsurface.modelsurfaces + surfacelist[i];
10228                         texture = surface->texture;
10229                         rsurface.texture = R_GetCurrentTexture(texture);
10230                         rsurface.lightmaptexture = NULL;
10231                         rsurface.deluxemaptexture = NULL;
10232                         rsurface.uselightmaptexture = false;
10233                         // scan ahead until we find a different texture
10234                         endsurface = min(i + 1024, numsurfaces);
10235                         texturenumsurfaces = 0;
10236                         texturesurfacelist[texturenumsurfaces++] = surface;
10237                         for (;j < endsurface;j++)
10238                         {
10239                                 surface = rsurface.modelsurfaces + surfacelist[j];
10240                                 if (texture != surface->texture)
10241                                         break;
10242                                 texturesurfacelist[texturenumsurfaces++] = surface;
10243                         }
10244                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10245                                 continue;
10246                         // render the range of surfaces as depth
10247                         if (!setup)
10248                         {
10249                                 setup = true;
10250                                 GL_ColorMask(0,0,0,0);
10251                                 GL_Color(1,1,1,1);
10252                                 GL_DepthTest(true);
10253                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10254                                 GL_DepthMask(true);
10255 //                              R_Mesh_ResetTextureState();
10256                                 R_SetupShader_DepthOrShadow(false);
10257                         }
10258                         RSurf_SetupDepthAndCulling();
10259                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10260                         if (rsurface.batchvertex3fbuffer)
10261                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10262                         else
10263                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10264                         RSurf_DrawBatch();
10265                 }
10266                 if (setup)
10267                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10268         }
10269
10270         for (i = 0;i < numsurfaces;i = j)
10271         {
10272                 j = i + 1;
10273                 surface = rsurface.modelsurfaces + surfacelist[i];
10274                 texture = surface->texture;
10275                 rsurface.texture = R_GetCurrentTexture(texture);
10276                 // scan ahead until we find a different texture
10277                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10278                 texturenumsurfaces = 0;
10279                 texturesurfacelist[texturenumsurfaces++] = surface;
10280                 if(FAKELIGHT_ENABLED)
10281                 {
10282                         rsurface.lightmaptexture = NULL;
10283                         rsurface.deluxemaptexture = NULL;
10284                         rsurface.uselightmaptexture = false;
10285                         for (;j < endsurface;j++)
10286                         {
10287                                 surface = rsurface.modelsurfaces + surfacelist[j];
10288                                 if (texture != surface->texture)
10289                                         break;
10290                                 texturesurfacelist[texturenumsurfaces++] = surface;
10291                         }
10292                 }
10293                 else
10294                 {
10295                         rsurface.lightmaptexture = surface->lightmaptexture;
10296                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10297                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10298                         for (;j < endsurface;j++)
10299                         {
10300                                 surface = rsurface.modelsurfaces + surfacelist[j];
10301                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10302                                         break;
10303                                 texturesurfacelist[texturenumsurfaces++] = surface;
10304                         }
10305                 }
10306                 // render the range of surfaces
10307                 if (ent == r_refdef.scene.worldentity)
10308                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10309                 else
10310                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10311         }
10312         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10313 }
10314
10315 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10316 {
10317         // transparent surfaces get pushed off into the transparent queue
10318         int surfacelistindex;
10319         const msurface_t *surface;
10320         vec3_t tempcenter, center;
10321         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10322         {
10323                 surface = texturesurfacelist[surfacelistindex];
10324                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10325                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10326                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10327                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10328                 if (queueentity->transparent_offset) // transparent offset
10329                 {
10330                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10331                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10332                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10333                 }
10334                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10335         }
10336 }
10337
10338 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10339 {
10340         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10341                 return;
10342         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10343                 return;
10344         RSurf_SetupDepthAndCulling();
10345         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10346         if (rsurface.batchvertex3fbuffer)
10347                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10348         else
10349                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10350         RSurf_DrawBatch();
10351 }
10352
10353 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10354 {
10355         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10356         CHECKGLERROR
10357         if (depthonly)
10358                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10359         else if (prepass)
10360         {
10361                 if (!rsurface.texture->currentnumlayers)
10362                         return;
10363                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10364                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10365                 else
10366                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10367         }
10368         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10369                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10370         else if (!rsurface.texture->currentnumlayers)
10371                 return;
10372         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10373         {
10374                 // in the deferred case, transparent surfaces were queued during prepass
10375                 if (!r_shadow_usingdeferredprepass)
10376                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10377         }
10378         else
10379         {
10380                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10381                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10382         }
10383         CHECKGLERROR
10384 }
10385
10386 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10387 {
10388         int i, j;
10389         texture_t *texture;
10390         R_FrameData_SetMark();
10391         // break the surface list down into batches by texture and use of lightmapping
10392         for (i = 0;i < numsurfaces;i = j)
10393         {
10394                 j = i + 1;
10395                 // texture is the base texture pointer, rsurface.texture is the
10396                 // current frame/skin the texture is directing us to use (for example
10397                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10398                 // use skin 1 instead)
10399                 texture = surfacelist[i]->texture;
10400                 rsurface.texture = R_GetCurrentTexture(texture);
10401                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10402                 {
10403                         // if this texture is not the kind we want, skip ahead to the next one
10404                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10405                                 ;
10406                         continue;
10407                 }
10408                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10409                 {
10410                         rsurface.lightmaptexture = NULL;
10411                         rsurface.deluxemaptexture = NULL;
10412                         rsurface.uselightmaptexture = false;
10413                         // simply scan ahead until we find a different texture or lightmap state
10414                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10415                                 ;
10416                 }
10417                 else
10418                 {
10419                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10420                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10421                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10422                         // simply scan ahead until we find a different texture or lightmap state
10423                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10424                                 ;
10425                 }
10426                 // render the range of surfaces
10427                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10428         }
10429         R_FrameData_ReturnToMark();
10430 }
10431
10432 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10433 {
10434         CHECKGLERROR
10435         if (depthonly)
10436                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10437         else if (prepass)
10438         {
10439                 if (!rsurface.texture->currentnumlayers)
10440                         return;
10441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10442                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10443                 else
10444                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10445         }
10446         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10447                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10448         else if (!rsurface.texture->currentnumlayers)
10449                 return;
10450         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10451         {
10452                 // in the deferred case, transparent surfaces were queued during prepass
10453                 if (!r_shadow_usingdeferredprepass)
10454                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10455         }
10456         else
10457         {
10458                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10459                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10460         }
10461         CHECKGLERROR
10462 }
10463
10464 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10465 {
10466         int i, j;
10467         texture_t *texture;
10468         R_FrameData_SetMark();
10469         // break the surface list down into batches by texture and use of lightmapping
10470         for (i = 0;i < numsurfaces;i = j)
10471         {
10472                 j = i + 1;
10473                 // texture is the base texture pointer, rsurface.texture is the
10474                 // current frame/skin the texture is directing us to use (for example
10475                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10476                 // use skin 1 instead)
10477                 texture = surfacelist[i]->texture;
10478                 rsurface.texture = R_GetCurrentTexture(texture);
10479                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10480                 {
10481                         // if this texture is not the kind we want, skip ahead to the next one
10482                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10483                                 ;
10484                         continue;
10485                 }
10486                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10487                 {
10488                         rsurface.lightmaptexture = NULL;
10489                         rsurface.deluxemaptexture = NULL;
10490                         rsurface.uselightmaptexture = false;
10491                         // simply scan ahead until we find a different texture or lightmap state
10492                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10493                                 ;
10494                 }
10495                 else
10496                 {
10497                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10498                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10499                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10500                         // simply scan ahead until we find a different texture or lightmap state
10501                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10502                                 ;
10503                 }
10504                 // render the range of surfaces
10505                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10506         }
10507         R_FrameData_ReturnToMark();
10508 }
10509
10510 float locboxvertex3f[6*4*3] =
10511 {
10512         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10513         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10514         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10515         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10516         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10517         1,0,0, 0,0,0, 0,1,0, 1,1,0
10518 };
10519
10520 unsigned short locboxelements[6*2*3] =
10521 {
10522          0, 1, 2, 0, 2, 3,
10523          4, 5, 6, 4, 6, 7,
10524          8, 9,10, 8,10,11,
10525         12,13,14, 12,14,15,
10526         16,17,18, 16,18,19,
10527         20,21,22, 20,22,23
10528 };
10529
10530 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10531 {
10532         int i, j;
10533         cl_locnode_t *loc = (cl_locnode_t *)ent;
10534         vec3_t mins, size;
10535         float vertex3f[6*4*3];
10536         CHECKGLERROR
10537         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10538         GL_DepthMask(false);
10539         GL_DepthRange(0, 1);
10540         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10541         GL_DepthTest(true);
10542         GL_CullFace(GL_NONE);
10543         R_EntityMatrix(&identitymatrix);
10544
10545 //      R_Mesh_ResetTextureState();
10546
10547         i = surfacelist[0];
10548         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10549                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10550                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10551                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10552
10553         if (VectorCompare(loc->mins, loc->maxs))
10554         {
10555                 VectorSet(size, 2, 2, 2);
10556                 VectorMA(loc->mins, -0.5f, size, mins);
10557         }
10558         else
10559         {
10560                 VectorCopy(loc->mins, mins);
10561                 VectorSubtract(loc->maxs, loc->mins, size);
10562         }
10563
10564         for (i = 0;i < 6*4*3;)
10565                 for (j = 0;j < 3;j++, i++)
10566                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10567
10568         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10569         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
10570         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10571 }
10572
10573 void R_DrawLocs(void)
10574 {
10575         int index;
10576         cl_locnode_t *loc, *nearestloc;
10577         vec3_t center;
10578         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10579         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10580         {
10581                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10582                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10583         }
10584 }
10585
10586 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10587 {
10588         if (decalsystem->decals)
10589                 Mem_Free(decalsystem->decals);
10590         memset(decalsystem, 0, sizeof(*decalsystem));
10591 }
10592
10593 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)
10594 {
10595         tridecal_t *decal;
10596         tridecal_t *decals;
10597         int i;
10598
10599         // expand or initialize the system
10600         if (decalsystem->maxdecals <= decalsystem->numdecals)
10601         {
10602                 decalsystem_t old = *decalsystem;
10603                 qboolean useshortelements;
10604                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10605                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10606                 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)));
10607                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10608                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10609                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10610                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10611                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10612                 if (decalsystem->numdecals)
10613                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10614                 if (old.decals)
10615                         Mem_Free(old.decals);
10616                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10617                         decalsystem->element3i[i] = i;
10618                 if (useshortelements)
10619                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10620                                 decalsystem->element3s[i] = i;
10621         }
10622
10623         // grab a decal and search for another free slot for the next one
10624         decals = decalsystem->decals;
10625         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10626         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10627                 ;
10628         decalsystem->freedecal = i;
10629         if (decalsystem->numdecals <= i)
10630                 decalsystem->numdecals = i + 1;
10631
10632         // initialize the decal
10633         decal->lived = 0;
10634         decal->triangleindex = triangleindex;
10635         decal->surfaceindex = surfaceindex;
10636         decal->decalsequence = decalsequence;
10637         decal->color4f[0][0] = c0[0];
10638         decal->color4f[0][1] = c0[1];
10639         decal->color4f[0][2] = c0[2];
10640         decal->color4f[0][3] = 1;
10641         decal->color4f[1][0] = c1[0];
10642         decal->color4f[1][1] = c1[1];
10643         decal->color4f[1][2] = c1[2];
10644         decal->color4f[1][3] = 1;
10645         decal->color4f[2][0] = c2[0];
10646         decal->color4f[2][1] = c2[1];
10647         decal->color4f[2][2] = c2[2];
10648         decal->color4f[2][3] = 1;
10649         decal->vertex3f[0][0] = v0[0];
10650         decal->vertex3f[0][1] = v0[1];
10651         decal->vertex3f[0][2] = v0[2];
10652         decal->vertex3f[1][0] = v1[0];
10653         decal->vertex3f[1][1] = v1[1];
10654         decal->vertex3f[1][2] = v1[2];
10655         decal->vertex3f[2][0] = v2[0];
10656         decal->vertex3f[2][1] = v2[1];
10657         decal->vertex3f[2][2] = v2[2];
10658         decal->texcoord2f[0][0] = t0[0];
10659         decal->texcoord2f[0][1] = t0[1];
10660         decal->texcoord2f[1][0] = t1[0];
10661         decal->texcoord2f[1][1] = t1[1];
10662         decal->texcoord2f[2][0] = t2[0];
10663         decal->texcoord2f[2][1] = t2[1];
10664         TriangleNormal(v0, v1, v2, decal->plane);
10665         VectorNormalize(decal->plane);
10666         decal->plane[3] = DotProduct(v0, decal->plane);
10667 }
10668
10669 extern cvar_t cl_decals_bias;
10670 extern cvar_t cl_decals_models;
10671 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10672 // baseparms, parms, temps
10673 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)
10674 {
10675         int cornerindex;
10676         int index;
10677         float v[9][3];
10678         const float *vertex3f;
10679         const float *normal3f;
10680         int numpoints;
10681         float points[2][9][3];
10682         float temp[3];
10683         float tc[9][2];
10684         float f;
10685         float c[9][4];
10686         const int *e;
10687
10688         e = rsurface.modelelement3i + 3*triangleindex;
10689
10690         vertex3f = rsurface.modelvertex3f;
10691         normal3f = rsurface.modelnormal3f;
10692
10693         if (normal3f)
10694         {
10695                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10696                 {
10697                         index = 3*e[cornerindex];
10698                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10699                 }
10700         }
10701         else
10702         {
10703                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10704                 {
10705                         index = 3*e[cornerindex];
10706                         VectorCopy(vertex3f + index, v[cornerindex]);
10707                 }
10708         }
10709
10710         // cull backfaces
10711         //TriangleNormal(v[0], v[1], v[2], normal);
10712         //if (DotProduct(normal, localnormal) < 0.0f)
10713         //      continue;
10714         // clip by each of the box planes formed from the projection matrix
10715         // if anything survives, we emit the decal
10716         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]);
10717         if (numpoints < 3)
10718                 return;
10719         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]);
10720         if (numpoints < 3)
10721                 return;
10722         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]);
10723         if (numpoints < 3)
10724                 return;
10725         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]);
10726         if (numpoints < 3)
10727                 return;
10728         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]);
10729         if (numpoints < 3)
10730                 return;
10731         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]);
10732         if (numpoints < 3)
10733                 return;
10734         // some part of the triangle survived, so we have to accept it...
10735         if (dynamic)
10736         {
10737                 // dynamic always uses the original triangle
10738                 numpoints = 3;
10739                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10740                 {
10741                         index = 3*e[cornerindex];
10742                         VectorCopy(vertex3f + index, v[cornerindex]);
10743                 }
10744         }
10745         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10746         {
10747                 // convert vertex positions to texcoords
10748                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10749                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10750                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10751                 // calculate distance fade from the projection origin
10752                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10753                 f = bound(0.0f, f, 1.0f);
10754                 c[cornerindex][0] = r * f;
10755                 c[cornerindex][1] = g * f;
10756                 c[cornerindex][2] = b * f;
10757                 c[cornerindex][3] = 1.0f;
10758                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10759         }
10760         if (dynamic)
10761                 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);
10762         else
10763                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10764                         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);
10765 }
10766 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)
10767 {
10768         matrix4x4_t projection;
10769         decalsystem_t *decalsystem;
10770         qboolean dynamic;
10771         dp_model_t *model;
10772         const msurface_t *surface;
10773         const msurface_t *surfaces;
10774         const int *surfacelist;
10775         const texture_t *texture;
10776         int numtriangles;
10777         int numsurfacelist;
10778         int surfacelistindex;
10779         int surfaceindex;
10780         int triangleindex;
10781         float localorigin[3];
10782         float localnormal[3];
10783         float localmins[3];
10784         float localmaxs[3];
10785         float localsize;
10786         //float normal[3];
10787         float planes[6][4];
10788         float angles[3];
10789         bih_t *bih;
10790         int bih_triangles_count;
10791         int bih_triangles[256];
10792         int bih_surfaces[256];
10793
10794         decalsystem = &ent->decalsystem;
10795         model = ent->model;
10796         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10797         {
10798                 R_DecalSystem_Reset(&ent->decalsystem);
10799                 return;
10800         }
10801
10802         if (!model->brush.data_leafs && !cl_decals_models.integer)
10803         {
10804                 if (decalsystem->model)
10805                         R_DecalSystem_Reset(decalsystem);
10806                 return;
10807         }
10808
10809         if (decalsystem->model != model)
10810                 R_DecalSystem_Reset(decalsystem);
10811         decalsystem->model = model;
10812
10813         RSurf_ActiveModelEntity(ent, true, false, false);
10814
10815         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10816         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10817         VectorNormalize(localnormal);
10818         localsize = worldsize*rsurface.inversematrixscale;
10819         localmins[0] = localorigin[0] - localsize;
10820         localmins[1] = localorigin[1] - localsize;
10821         localmins[2] = localorigin[2] - localsize;
10822         localmaxs[0] = localorigin[0] + localsize;
10823         localmaxs[1] = localorigin[1] + localsize;
10824         localmaxs[2] = localorigin[2] + localsize;
10825
10826         //VectorCopy(localnormal, planes[4]);
10827         //VectorVectors(planes[4], planes[2], planes[0]);
10828         AnglesFromVectors(angles, localnormal, NULL, false);
10829         AngleVectors(angles, planes[0], planes[2], planes[4]);
10830         VectorNegate(planes[0], planes[1]);
10831         VectorNegate(planes[2], planes[3]);
10832         VectorNegate(planes[4], planes[5]);
10833         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10834         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10835         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10836         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10837         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10838         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10839
10840 #if 1
10841 // works
10842 {
10843         matrix4x4_t forwardprojection;
10844         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10845         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10846 }
10847 #else
10848 // broken
10849 {
10850         float projectionvector[4][3];
10851         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10852         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10853         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10854         projectionvector[0][0] = planes[0][0] * ilocalsize;
10855         projectionvector[0][1] = planes[1][0] * ilocalsize;
10856         projectionvector[0][2] = planes[2][0] * ilocalsize;
10857         projectionvector[1][0] = planes[0][1] * ilocalsize;
10858         projectionvector[1][1] = planes[1][1] * ilocalsize;
10859         projectionvector[1][2] = planes[2][1] * ilocalsize;
10860         projectionvector[2][0] = planes[0][2] * ilocalsize;
10861         projectionvector[2][1] = planes[1][2] * ilocalsize;
10862         projectionvector[2][2] = planes[2][2] * ilocalsize;
10863         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10864         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10865         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10866         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10867 }
10868 #endif
10869
10870         dynamic = model->surfmesh.isanimated;
10871         numsurfacelist = model->nummodelsurfaces;
10872         surfacelist = model->sortedmodelsurfaces;
10873         surfaces = model->data_surfaces;
10874
10875         bih = NULL;
10876         bih_triangles_count = -1;
10877         if(!dynamic)
10878         {
10879                 if(model->render_bih.numleafs)
10880                         bih = &model->render_bih;
10881                 else if(model->collision_bih.numleafs)
10882                         bih = &model->collision_bih;
10883         }
10884         if(bih)
10885                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10886         if(bih_triangles_count == 0)
10887                 return;
10888         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10889                 return;
10890         if(bih_triangles_count > 0)
10891         {
10892                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10893                 {
10894                         surfaceindex = bih_surfaces[triangleindex];
10895                         surface = surfaces + surfaceindex;
10896                         texture = surface->texture;
10897                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10898                                 continue;
10899                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10900                                 continue;
10901                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10902                 }
10903         }
10904         else
10905         {
10906                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
10907                 {
10908                         surfaceindex = surfacelist[surfacelistindex];
10909                         surface = surfaces + surfaceindex;
10910                         // check cull box first because it rejects more than any other check
10911                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
10912                                 continue;
10913                         // skip transparent surfaces
10914                         texture = surface->texture;
10915                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10916                                 continue;
10917                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10918                                 continue;
10919                         numtriangles = surface->num_triangles;
10920                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
10921                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
10922                 }
10923         }
10924 }
10925
10926 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
10927 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)
10928 {
10929         int renderentityindex;
10930         float worldmins[3];
10931         float worldmaxs[3];
10932         entity_render_t *ent;
10933
10934         if (!cl_decals_newsystem.integer)
10935                 return;
10936
10937         worldmins[0] = worldorigin[0] - worldsize;
10938         worldmins[1] = worldorigin[1] - worldsize;
10939         worldmins[2] = worldorigin[2] - worldsize;
10940         worldmaxs[0] = worldorigin[0] + worldsize;
10941         worldmaxs[1] = worldorigin[1] + worldsize;
10942         worldmaxs[2] = worldorigin[2] + worldsize;
10943
10944         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10945
10946         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
10947         {
10948                 ent = r_refdef.scene.entities[renderentityindex];
10949                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
10950                         continue;
10951
10952                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
10953         }
10954 }
10955
10956 typedef struct r_decalsystem_splatqueue_s
10957 {
10958         vec3_t worldorigin;
10959         vec3_t worldnormal;
10960         float color[4];
10961         float tcrange[4];
10962         float worldsize;
10963         int decalsequence;
10964 }
10965 r_decalsystem_splatqueue_t;
10966
10967 int r_decalsystem_numqueued = 0;
10968 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
10969
10970 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)
10971 {
10972         r_decalsystem_splatqueue_t *queue;
10973
10974         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
10975                 return;
10976
10977         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
10978         VectorCopy(worldorigin, queue->worldorigin);
10979         VectorCopy(worldnormal, queue->worldnormal);
10980         Vector4Set(queue->color, r, g, b, a);
10981         Vector4Set(queue->tcrange, s1, t1, s2, t2);
10982         queue->worldsize = worldsize;
10983         queue->decalsequence = cl.decalsequence++;
10984 }
10985
10986 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
10987 {
10988         int i;
10989         r_decalsystem_splatqueue_t *queue;
10990
10991         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
10992                 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);
10993         r_decalsystem_numqueued = 0;
10994 }
10995
10996 extern cvar_t cl_decals_max;
10997 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
10998 {
10999         int i;
11000         decalsystem_t *decalsystem = &ent->decalsystem;
11001         int numdecals;
11002         int killsequence;
11003         tridecal_t *decal;
11004         float frametime;
11005         float lifetime;
11006
11007         if (!decalsystem->numdecals)
11008                 return;
11009
11010         if (r_showsurfaces.integer)
11011                 return;
11012
11013         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11014         {
11015                 R_DecalSystem_Reset(decalsystem);
11016                 return;
11017         }
11018
11019         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11020         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11021
11022         if (decalsystem->lastupdatetime)
11023                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11024         else
11025                 frametime = 0;
11026         decalsystem->lastupdatetime = r_refdef.scene.time;
11027         decal = decalsystem->decals;
11028         numdecals = decalsystem->numdecals;
11029
11030         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11031         {
11032                 if (decal->color4f[0][3])
11033                 {
11034                         decal->lived += frametime;
11035                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11036                         {
11037                                 memset(decal, 0, sizeof(*decal));
11038                                 if (decalsystem->freedecal > i)
11039                                         decalsystem->freedecal = i;
11040                         }
11041                 }
11042         }
11043         decal = decalsystem->decals;
11044         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11045                 numdecals--;
11046
11047         // collapse the array by shuffling the tail decals into the gaps
11048         for (;;)
11049         {
11050                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11051                         decalsystem->freedecal++;
11052                 if (decalsystem->freedecal == numdecals)
11053                         break;
11054                 decal[decalsystem->freedecal] = decal[--numdecals];
11055         }
11056
11057         decalsystem->numdecals = numdecals;
11058
11059         if (numdecals <= 0)
11060         {
11061                 // if there are no decals left, reset decalsystem
11062                 R_DecalSystem_Reset(decalsystem);
11063         }
11064 }
11065
11066 extern skinframe_t *decalskinframe;
11067 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11068 {
11069         int i;
11070         decalsystem_t *decalsystem = &ent->decalsystem;
11071         int numdecals;
11072         tridecal_t *decal;
11073         float faderate;
11074         float alpha;
11075         float *v3f;
11076         float *c4f;
11077         float *t2f;
11078         const int *e;
11079         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11080         int numtris = 0;
11081
11082         numdecals = decalsystem->numdecals;
11083         if (!numdecals)
11084                 return;
11085
11086         if (r_showsurfaces.integer)
11087                 return;
11088
11089         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11090         {
11091                 R_DecalSystem_Reset(decalsystem);
11092                 return;
11093         }
11094
11095         // if the model is static it doesn't matter what value we give for
11096         // wantnormals and wanttangents, so this logic uses only rules applicable
11097         // to a model, knowing that they are meaningless otherwise
11098         if (ent == r_refdef.scene.worldentity)
11099                 RSurf_ActiveWorldEntity();
11100         else
11101                 RSurf_ActiveModelEntity(ent, false, false, false);
11102
11103         decalsystem->lastupdatetime = r_refdef.scene.time;
11104         decal = decalsystem->decals;
11105
11106         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11107
11108         // update vertex positions for animated models
11109         v3f = decalsystem->vertex3f;
11110         c4f = decalsystem->color4f;
11111         t2f = decalsystem->texcoord2f;
11112         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11113         {
11114                 if (!decal->color4f[0][3])
11115                         continue;
11116
11117                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11118                         continue;
11119
11120                 // skip backfaces
11121                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11122                         continue;
11123
11124                 // update color values for fading decals
11125                 if (decal->lived >= cl_decals_time.value)
11126                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11127                 else
11128                         alpha = 1.0f;
11129
11130                 c4f[ 0] = decal->color4f[0][0] * alpha;
11131                 c4f[ 1] = decal->color4f[0][1] * alpha;
11132                 c4f[ 2] = decal->color4f[0][2] * alpha;
11133                 c4f[ 3] = 1;
11134                 c4f[ 4] = decal->color4f[1][0] * alpha;
11135                 c4f[ 5] = decal->color4f[1][1] * alpha;
11136                 c4f[ 6] = decal->color4f[1][2] * alpha;
11137                 c4f[ 7] = 1;
11138                 c4f[ 8] = decal->color4f[2][0] * alpha;
11139                 c4f[ 9] = decal->color4f[2][1] * alpha;
11140                 c4f[10] = decal->color4f[2][2] * alpha;
11141                 c4f[11] = 1;
11142
11143                 t2f[0] = decal->texcoord2f[0][0];
11144                 t2f[1] = decal->texcoord2f[0][1];
11145                 t2f[2] = decal->texcoord2f[1][0];
11146                 t2f[3] = decal->texcoord2f[1][1];
11147                 t2f[4] = decal->texcoord2f[2][0];
11148                 t2f[5] = decal->texcoord2f[2][1];
11149
11150                 // update vertex positions for animated models
11151                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11152                 {
11153                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11154                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11155                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11156                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11157                 }
11158                 else
11159                 {
11160                         VectorCopy(decal->vertex3f[0], v3f);
11161                         VectorCopy(decal->vertex3f[1], v3f + 3);
11162                         VectorCopy(decal->vertex3f[2], v3f + 6);
11163                 }
11164
11165                 if (r_refdef.fogenabled)
11166                 {
11167                         alpha = RSurf_FogVertex(v3f);
11168                         VectorScale(c4f, alpha, c4f);
11169                         alpha = RSurf_FogVertex(v3f + 3);
11170                         VectorScale(c4f + 4, alpha, c4f + 4);
11171                         alpha = RSurf_FogVertex(v3f + 6);
11172                         VectorScale(c4f + 8, alpha, c4f + 8);
11173                 }
11174
11175                 v3f += 9;
11176                 c4f += 12;
11177                 t2f += 6;
11178                 numtris++;
11179         }
11180
11181         if (numtris > 0)
11182         {
11183                 r_refdef.stats.drawndecals += numtris;
11184
11185                 // now render the decals all at once
11186                 // (this assumes they all use one particle font texture!)
11187                 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);
11188 //              R_Mesh_ResetTextureState();
11189                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11190                 GL_DepthMask(false);
11191                 GL_DepthRange(0, 1);
11192                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11193                 GL_DepthTest(true);
11194                 GL_CullFace(GL_NONE);
11195                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11196                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false);
11197                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11198         }
11199 }
11200
11201 static void R_DrawModelDecals(void)
11202 {
11203         int i, numdecals;
11204
11205         // fade faster when there are too many decals
11206         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11207         for (i = 0;i < r_refdef.scene.numentities;i++)
11208                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11209
11210         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11211         for (i = 0;i < r_refdef.scene.numentities;i++)
11212                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11213                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11214
11215         R_DecalSystem_ApplySplatEntitiesQueue();
11216
11217         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11218         for (i = 0;i < r_refdef.scene.numentities;i++)
11219                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11220
11221         r_refdef.stats.totaldecals += numdecals;
11222
11223         if (r_showsurfaces.integer)
11224                 return;
11225
11226         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11227
11228         for (i = 0;i < r_refdef.scene.numentities;i++)
11229         {
11230                 if (!r_refdef.viewcache.entityvisible[i])
11231                         continue;
11232                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11233                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11234         }
11235 }
11236
11237 extern cvar_t mod_collision_bih;
11238 void R_DrawDebugModel(void)
11239 {
11240         entity_render_t *ent = rsurface.entity;
11241         int i, j, k, l, flagsmask;
11242         const msurface_t *surface;
11243         dp_model_t *model = ent->model;
11244         vec3_t v;
11245
11246         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11247                 return;
11248
11249         if (r_showoverdraw.value > 0)
11250         {
11251                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11252                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11253                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11254                 GL_DepthTest(false);
11255                 GL_DepthMask(false);
11256                 GL_DepthRange(0, 1);
11257                 GL_BlendFunc(GL_ONE, GL_ONE);
11258                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11259                 {
11260                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11261                                 continue;
11262                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11263                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11264                         {
11265                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11266                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11267                                 if (!rsurface.texture->currentlayers->depthmask)
11268                                         GL_Color(c, 0, 0, 1.0f);
11269                                 else if (ent == r_refdef.scene.worldentity)
11270                                         GL_Color(c, c, c, 1.0f);
11271                                 else
11272                                         GL_Color(0, c, 0, 1.0f);
11273                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11274                                 RSurf_DrawBatch();
11275                         }
11276                 }
11277                 rsurface.texture = NULL;
11278         }
11279
11280         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11281
11282 //      R_Mesh_ResetTextureState();
11283         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false);
11284         GL_DepthRange(0, 1);
11285         GL_DepthTest(!r_showdisabledepthtest.integer);
11286         GL_DepthMask(false);
11287         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11288
11289         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11290         {
11291                 int triangleindex;
11292                 int bihleafindex;
11293                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11294                 const q3mbrush_t *brush;
11295                 const bih_t *bih = &model->collision_bih;
11296                 const bih_leaf_t *bihleaf;
11297                 float vertex3f[3][3];
11298                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11299                 cullbox = false;
11300                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11301                 {
11302                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11303                                 continue;
11304                         switch (bihleaf->type)
11305                         {
11306                         case BIH_BRUSH:
11307                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11308                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11309                                 {
11310                                         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);
11311                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11312                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11313                                 }
11314                                 break;
11315                         case BIH_COLLISIONTRIANGLE:
11316                                 triangleindex = bihleaf->itemindex;
11317                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11318                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11319                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11320                                 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);
11321                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11322                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11323                                 break;
11324                         case BIH_RENDERTRIANGLE:
11325                                 triangleindex = bihleaf->itemindex;
11326                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11327                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11328                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11329                                 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);
11330                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11331                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11332                                 break;
11333                         }
11334                 }
11335         }
11336
11337         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11338
11339         if (r_showtris.integer && qglPolygonMode)
11340         {
11341                 if (r_showdisabledepthtest.integer)
11342                 {
11343                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11344                         GL_DepthMask(false);
11345                 }
11346                 else
11347                 {
11348                         GL_BlendFunc(GL_ONE, GL_ZERO);
11349                         GL_DepthMask(true);
11350                 }
11351                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11352                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11353                 {
11354                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11355                                 continue;
11356                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11357                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11358                         {
11359                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11360                                 if (!rsurface.texture->currentlayers->depthmask)
11361                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11362                                 else if (ent == r_refdef.scene.worldentity)
11363                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11364                                 else
11365                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11366                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11367                                 RSurf_DrawBatch();
11368                         }
11369                 }
11370                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11371                 rsurface.texture = NULL;
11372         }
11373
11374         if (r_shownormals.value != 0 && qglBegin)
11375         {
11376                 if (r_showdisabledepthtest.integer)
11377                 {
11378                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11379                         GL_DepthMask(false);
11380                 }
11381                 else
11382                 {
11383                         GL_BlendFunc(GL_ONE, GL_ZERO);
11384                         GL_DepthMask(true);
11385                 }
11386                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11387                 {
11388                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11389                                 continue;
11390                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11391                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11392                         {
11393                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11394                                 qglBegin(GL_LINES);
11395                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11396                                 {
11397                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11398                                         {
11399                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11400                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11401                                                 qglVertex3f(v[0], v[1], v[2]);
11402                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11403                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11404                                                 qglVertex3f(v[0], v[1], v[2]);
11405                                         }
11406                                 }
11407                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11408                                 {
11409                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11410                                         {
11411                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11412                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11413                                                 qglVertex3f(v[0], v[1], v[2]);
11414                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11415                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11416                                                 qglVertex3f(v[0], v[1], v[2]);
11417                                         }
11418                                 }
11419                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11420                                 {
11421                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11422                                         {
11423                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11424                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11425                                                 qglVertex3f(v[0], v[1], v[2]);
11426                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11427                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11428                                                 qglVertex3f(v[0], v[1], v[2]);
11429                                         }
11430                                 }
11431                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11432                                 {
11433                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11434                                         {
11435                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11436                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11437                                                 qglVertex3f(v[0], v[1], v[2]);
11438                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11439                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11440                                                 qglVertex3f(v[0], v[1], v[2]);
11441                                         }
11442                                 }
11443                                 qglEnd();
11444                                 CHECKGLERROR
11445                         }
11446                 }
11447                 rsurface.texture = NULL;
11448         }
11449 }
11450
11451 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11452 int r_maxsurfacelist = 0;
11453 const msurface_t **r_surfacelist = NULL;
11454 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11455 {
11456         int i, j, endj, flagsmask;
11457         dp_model_t *model = r_refdef.scene.worldmodel;
11458         msurface_t *surfaces;
11459         unsigned char *update;
11460         int numsurfacelist = 0;
11461         if (model == NULL)
11462                 return;
11463
11464         if (r_maxsurfacelist < model->num_surfaces)
11465         {
11466                 r_maxsurfacelist = model->num_surfaces;
11467                 if (r_surfacelist)
11468                         Mem_Free((msurface_t**)r_surfacelist);
11469                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11470         }
11471
11472         RSurf_ActiveWorldEntity();
11473
11474         surfaces = model->data_surfaces;
11475         update = model->brushq1.lightmapupdateflags;
11476
11477         // update light styles on this submodel
11478         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11479         {
11480                 model_brush_lightstyleinfo_t *style;
11481                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11482                 {
11483                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11484                         {
11485                                 int *list = style->surfacelist;
11486                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11487                                 for (j = 0;j < style->numsurfaces;j++)
11488                                         update[list[j]] = true;
11489                         }
11490                 }
11491         }
11492
11493         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11494
11495         if (debug)
11496         {
11497                 R_DrawDebugModel();
11498                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11499                 return;
11500         }
11501
11502         rsurface.lightmaptexture = NULL;
11503         rsurface.deluxemaptexture = NULL;
11504         rsurface.uselightmaptexture = false;
11505         rsurface.texture = NULL;
11506         rsurface.rtlight = NULL;
11507         numsurfacelist = 0;
11508         // add visible surfaces to draw list
11509         for (i = 0;i < model->nummodelsurfaces;i++)
11510         {
11511                 j = model->sortedmodelsurfaces[i];
11512                 if (r_refdef.viewcache.world_surfacevisible[j])
11513                         r_surfacelist[numsurfacelist++] = surfaces + j;
11514         }
11515         // update lightmaps if needed
11516         if (model->brushq1.firstrender)
11517         {
11518                 model->brushq1.firstrender = false;
11519                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11520                         if (update[j])
11521                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11522         }
11523         else if (update)
11524         {
11525                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11526                         if (r_refdef.viewcache.world_surfacevisible[j])
11527                                 if (update[j])
11528                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11529         }
11530         // don't do anything if there were no surfaces
11531         if (!numsurfacelist)
11532         {
11533                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11534                 return;
11535         }
11536         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11537
11538         // add to stats if desired
11539         if (r_speeds.integer && !skysurfaces && !depthonly)
11540         {
11541                 r_refdef.stats.world_surfaces += numsurfacelist;
11542                 for (j = 0;j < numsurfacelist;j++)
11543                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11544         }
11545
11546         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11547 }
11548
11549 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11550 {
11551         int i, j, endj, flagsmask;
11552         dp_model_t *model = ent->model;
11553         msurface_t *surfaces;
11554         unsigned char *update;
11555         int numsurfacelist = 0;
11556         if (model == NULL)
11557                 return;
11558
11559         if (r_maxsurfacelist < model->num_surfaces)
11560         {
11561                 r_maxsurfacelist = model->num_surfaces;
11562                 if (r_surfacelist)
11563                         Mem_Free((msurface_t **)r_surfacelist);
11564                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11565         }
11566
11567         // if the model is static it doesn't matter what value we give for
11568         // wantnormals and wanttangents, so this logic uses only rules applicable
11569         // to a model, knowing that they are meaningless otherwise
11570         if (ent == r_refdef.scene.worldentity)
11571                 RSurf_ActiveWorldEntity();
11572         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11573                 RSurf_ActiveModelEntity(ent, false, false, false);
11574         else if (prepass)
11575                 RSurf_ActiveModelEntity(ent, true, true, true);
11576         else if (depthonly)
11577         {
11578                 switch (vid.renderpath)
11579                 {
11580                 case RENDERPATH_GL20:
11581                 case RENDERPATH_D3D9:
11582                 case RENDERPATH_D3D10:
11583                 case RENDERPATH_D3D11:
11584                 case RENDERPATH_SOFT:
11585                 case RENDERPATH_GLES2:
11586                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11587                         break;
11588                 case RENDERPATH_GL11:
11589                 case RENDERPATH_GL13:
11590                 case RENDERPATH_GLES1:
11591                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11592                         break;
11593                 }
11594         }
11595         else
11596         {
11597                 switch (vid.renderpath)
11598                 {
11599                 case RENDERPATH_GL20:
11600                 case RENDERPATH_D3D9:
11601                 case RENDERPATH_D3D10:
11602                 case RENDERPATH_D3D11:
11603                 case RENDERPATH_SOFT:
11604                 case RENDERPATH_GLES2:
11605                         RSurf_ActiveModelEntity(ent, true, true, false);
11606                         break;
11607                 case RENDERPATH_GL11:
11608                 case RENDERPATH_GL13:
11609                 case RENDERPATH_GLES1:
11610                         RSurf_ActiveModelEntity(ent, true, false, false);
11611                         break;
11612                 }
11613         }
11614
11615         surfaces = model->data_surfaces;
11616         update = model->brushq1.lightmapupdateflags;
11617
11618         // update light styles
11619         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11620         {
11621                 model_brush_lightstyleinfo_t *style;
11622                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11623                 {
11624                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11625                         {
11626                                 int *list = style->surfacelist;
11627                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11628                                 for (j = 0;j < style->numsurfaces;j++)
11629                                         update[list[j]] = true;
11630                         }
11631                 }
11632         }
11633
11634         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11635
11636         if (debug)
11637         {
11638                 R_DrawDebugModel();
11639                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11640                 return;
11641         }
11642
11643         rsurface.lightmaptexture = NULL;
11644         rsurface.deluxemaptexture = NULL;
11645         rsurface.uselightmaptexture = false;
11646         rsurface.texture = NULL;
11647         rsurface.rtlight = NULL;
11648         numsurfacelist = 0;
11649         // add visible surfaces to draw list
11650         for (i = 0;i < model->nummodelsurfaces;i++)
11651                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11652         // don't do anything if there were no surfaces
11653         if (!numsurfacelist)
11654         {
11655                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11656                 return;
11657         }
11658         // update lightmaps if needed
11659         if (update)
11660         {
11661                 int updated = 0;
11662                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11663                 {
11664                         if (update[j])
11665                         {
11666                                 updated++;
11667                                 R_BuildLightMap(ent, surfaces + j);
11668                         }
11669                 }
11670         }
11671         if (update)
11672                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11673                         if (update[j])
11674                                 R_BuildLightMap(ent, surfaces + j);
11675         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11676
11677         // add to stats if desired
11678         if (r_speeds.integer && !skysurfaces && !depthonly)
11679         {
11680                 r_refdef.stats.entities_surfaces += numsurfacelist;
11681                 for (j = 0;j < numsurfacelist;j++)
11682                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11683         }
11684
11685         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11686 }
11687
11688 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11689 {
11690         static texture_t texture;
11691         static msurface_t surface;
11692         const msurface_t *surfacelist = &surface;
11693
11694         // fake enough texture and surface state to render this geometry
11695
11696         texture.update_lastrenderframe = -1; // regenerate this texture
11697         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11698         texture.currentskinframe = skinframe;
11699         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11700         texture.offsetmapping = OFFSETMAPPING_OFF;
11701         texture.offsetscale = 1;
11702         texture.specularscalemod = 1;
11703         texture.specularpowermod = 1;
11704
11705         surface.texture = &texture;
11706         surface.num_triangles = numtriangles;
11707         surface.num_firsttriangle = firsttriangle;
11708         surface.num_vertices = numvertices;
11709         surface.num_firstvertex = firstvertex;
11710
11711         // now render it
11712         rsurface.texture = R_GetCurrentTexture(surface.texture);
11713         rsurface.lightmaptexture = NULL;
11714         rsurface.deluxemaptexture = NULL;
11715         rsurface.uselightmaptexture = false;
11716         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11717 }
11718
11719 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)
11720 {
11721         static msurface_t surface;
11722         const msurface_t *surfacelist = &surface;
11723
11724         // fake enough texture and surface state to render this geometry
11725         surface.texture = texture;
11726         surface.num_triangles = numtriangles;
11727         surface.num_firsttriangle = firsttriangle;
11728         surface.num_vertices = numvertices;
11729         surface.num_firstvertex = firstvertex;
11730
11731         // now render it
11732         rsurface.texture = R_GetCurrentTexture(surface.texture);
11733         rsurface.lightmaptexture = NULL;
11734         rsurface.deluxemaptexture = NULL;
11735         rsurface.uselightmaptexture = false;
11736         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11737 }