]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
implement TEXF_FORCE_RELOAD to reload a pre-existing skinframe
[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_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 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."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 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."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 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"};
123 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"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 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"};
130 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
131 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
132
133 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
134 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
135 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
136 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
137 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
138 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
139 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
140 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
141
142 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)"};
143 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"};
144
145 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
146 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
147 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
148
149 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"};
150 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"};
151 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
152 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
153 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"};
154 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)"};
155 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)"};
156 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
157
158 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)"};
159 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
160 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)"};
161 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
162 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)"};
163 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)"};
164 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
165 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
166 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)"};
167 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)"};
168 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)"};
169 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)"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174
175 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)"};
176 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
177 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"};
178 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
179 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
180 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
181 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"};
182
183 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
184 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
185 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
186 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
187
188 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
189 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
190 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
191 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
192 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
193 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
194 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
195
196 cvar_t r_hdr = {CVAR_SAVE, "r_hdr", "0", "enables High Dynamic Range bloom effect (higher quality version of r_bloom)"};
197 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
198 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
199 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)"};
200 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
201 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
202 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
203 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
204 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
205 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
206 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
207
208 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"};
209
210 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"};
211
212 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
213
214 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
215
216 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
217 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"};
218
219 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."};
220
221 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)"};
222
223 extern cvar_t v_glslgamma;
224 extern cvar_t v_glslgamma_2d;
225
226 extern qboolean v_flipped_state;
227
228 static struct r_bloomstate_s
229 {
230         qboolean enabled;
231         qboolean hdr;
232
233         int bloomwidth, bloomheight;
234
235         textype_t texturetype;
236         int viewfbo; // used to check if r_viewfbo cvar has changed
237
238         int fbo_framebuffer; // non-zero if r_viewfbo is enabled and working
239         rtexture_t *texture_framebuffercolor; // non-NULL if fbo_screen is non-zero
240         rtexture_t *texture_framebufferdepth; // non-NULL if fbo_screen is non-zero
241
242         int screentexturewidth, screentextureheight;
243         rtexture_t *texture_screen; /// \note also used for motion blur if enabled!
244
245         int bloomtexturewidth, bloomtextureheight;
246         rtexture_t *texture_bloom;
247
248         // arrays for rendering the screen passes
249         float screentexcoord2f[8];
250         float bloomtexcoord2f[8];
251         float offsettexcoord2f[8];
252
253         r_viewport_t viewport;
254 }
255 r_bloomstate;
256
257 r_waterstate_t r_waterstate;
258
259 /// shadow volume bsp struct with automatically growing nodes buffer
260 svbsp_t r_svbsp;
261
262 rtexture_t *r_texture_blanknormalmap;
263 rtexture_t *r_texture_white;
264 rtexture_t *r_texture_grey128;
265 rtexture_t *r_texture_black;
266 rtexture_t *r_texture_notexture;
267 rtexture_t *r_texture_whitecube;
268 rtexture_t *r_texture_normalizationcube;
269 rtexture_t *r_texture_fogattenuation;
270 rtexture_t *r_texture_fogheighttexture;
271 rtexture_t *r_texture_gammaramps;
272 unsigned int r_texture_gammaramps_serial;
273 //rtexture_t *r_texture_fogintensity;
274 rtexture_t *r_texture_reflectcube;
275
276 // TODO: hash lookups?
277 typedef struct cubemapinfo_s
278 {
279         char basename[64];
280         rtexture_t *texture;
281 }
282 cubemapinfo_t;
283
284 int r_texture_numcubemaps;
285 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
286
287 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
288 unsigned int r_numqueries;
289 unsigned int r_maxqueries;
290
291 typedef struct r_qwskincache_s
292 {
293         char name[MAX_QPATH];
294         skinframe_t *skinframe;
295 }
296 r_qwskincache_t;
297
298 static r_qwskincache_t *r_qwskincache;
299 static int r_qwskincache_size;
300
301 /// vertex coordinates for a quad that covers the screen exactly
302 extern const float r_screenvertex3f[12];
303 extern const float r_d3dscreenvertex3f[12];
304 const float r_screenvertex3f[12] =
305 {
306         0, 0, 0,
307         1, 0, 0,
308         1, 1, 0,
309         0, 1, 0
310 };
311 const float r_d3dscreenvertex3f[12] =
312 {
313         0, 1, 0,
314         1, 1, 0,
315         1, 0, 0,
316         0, 0, 0
317 };
318
319 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
320 {
321         int i;
322         for (i = 0;i < verts;i++)
323         {
324                 out[0] = in[0] * r;
325                 out[1] = in[1] * g;
326                 out[2] = in[2] * b;
327                 out[3] = in[3];
328                 in += 4;
329                 out += 4;
330         }
331 }
332
333 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
334 {
335         int i;
336         for (i = 0;i < verts;i++)
337         {
338                 out[0] = r;
339                 out[1] = g;
340                 out[2] = b;
341                 out[3] = a;
342                 out += 4;
343         }
344 }
345
346 // FIXME: move this to client?
347 void FOG_clear(void)
348 {
349         if (gamemode == GAME_NEHAHRA)
350         {
351                 Cvar_Set("gl_fogenable", "0");
352                 Cvar_Set("gl_fogdensity", "0.2");
353                 Cvar_Set("gl_fogred", "0.3");
354                 Cvar_Set("gl_foggreen", "0.3");
355                 Cvar_Set("gl_fogblue", "0.3");
356         }
357         r_refdef.fog_density = 0;
358         r_refdef.fog_red = 0;
359         r_refdef.fog_green = 0;
360         r_refdef.fog_blue = 0;
361         r_refdef.fog_alpha = 1;
362         r_refdef.fog_start = 0;
363         r_refdef.fog_end = 16384;
364         r_refdef.fog_height = 1<<30;
365         r_refdef.fog_fadedepth = 128;
366         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
367 }
368
369 static void R_BuildBlankTextures(void)
370 {
371         unsigned char data[4];
372         data[2] = 128; // normal X
373         data[1] = 128; // normal Y
374         data[0] = 255; // normal Z
375         data[3] = 128; // height
376         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
377         data[0] = 255;
378         data[1] = 255;
379         data[2] = 255;
380         data[3] = 255;
381         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
382         data[0] = 128;
383         data[1] = 128;
384         data[2] = 128;
385         data[3] = 255;
386         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
387         data[0] = 0;
388         data[1] = 0;
389         data[2] = 0;
390         data[3] = 255;
391         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
392 }
393
394 static void R_BuildNoTexture(void)
395 {
396         int x, y;
397         unsigned char pix[16][16][4];
398         // this makes a light grey/dark grey checkerboard texture
399         for (y = 0;y < 16;y++)
400         {
401                 for (x = 0;x < 16;x++)
402                 {
403                         if ((y < 8) ^ (x < 8))
404                         {
405                                 pix[y][x][0] = 128;
406                                 pix[y][x][1] = 128;
407                                 pix[y][x][2] = 128;
408                                 pix[y][x][3] = 255;
409                         }
410                         else
411                         {
412                                 pix[y][x][0] = 64;
413                                 pix[y][x][1] = 64;
414                                 pix[y][x][2] = 64;
415                                 pix[y][x][3] = 255;
416                         }
417                 }
418         }
419         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
420 }
421
422 static void R_BuildWhiteCube(void)
423 {
424         unsigned char data[6*1*1*4];
425         memset(data, 255, sizeof(data));
426         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
427 }
428
429 static void R_BuildNormalizationCube(void)
430 {
431         int x, y, side;
432         vec3_t v;
433         vec_t s, t, intensity;
434 #define NORMSIZE 64
435         unsigned char *data;
436         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
437         for (side = 0;side < 6;side++)
438         {
439                 for (y = 0;y < NORMSIZE;y++)
440                 {
441                         for (x = 0;x < NORMSIZE;x++)
442                         {
443                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
445                                 switch(side)
446                                 {
447                                 default:
448                                 case 0:
449                                         v[0] = 1;
450                                         v[1] = -t;
451                                         v[2] = -s;
452                                         break;
453                                 case 1:
454                                         v[0] = -1;
455                                         v[1] = -t;
456                                         v[2] = s;
457                                         break;
458                                 case 2:
459                                         v[0] = s;
460                                         v[1] = 1;
461                                         v[2] = t;
462                                         break;
463                                 case 3:
464                                         v[0] = s;
465                                         v[1] = -1;
466                                         v[2] = -t;
467                                         break;
468                                 case 4:
469                                         v[0] = s;
470                                         v[1] = -t;
471                                         v[2] = 1;
472                                         break;
473                                 case 5:
474                                         v[0] = -s;
475                                         v[1] = -t;
476                                         v[2] = -1;
477                                         break;
478                                 }
479                                 intensity = 127.0f / sqrt(DotProduct(v, v));
480                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
481                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
482                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
483                                 data[((side*64+y)*64+x)*4+3] = 255;
484                         }
485                 }
486         }
487         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
488         Mem_Free(data);
489 }
490
491 static void R_BuildFogTexture(void)
492 {
493         int x, b;
494 #define FOGWIDTH 256
495         unsigned char data1[FOGWIDTH][4];
496         //unsigned char data2[FOGWIDTH][4];
497         double d, r, alpha;
498
499         r_refdef.fogmasktable_start = r_refdef.fog_start;
500         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
501         r_refdef.fogmasktable_range = r_refdef.fogrange;
502         r_refdef.fogmasktable_density = r_refdef.fog_density;
503
504         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
505         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
506         {
507                 d = (x * r - r_refdef.fogmasktable_start);
508                 if(developer_extra.integer)
509                         Con_DPrintf("%f ", d);
510                 d = max(0, d);
511                 if (r_fog_exp2.integer)
512                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
513                 else
514                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
515                 if(developer_extra.integer)
516                         Con_DPrintf(" : %f ", alpha);
517                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
518                 if(developer_extra.integer)
519                         Con_DPrintf(" = %f\n", alpha);
520                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
521         }
522
523         for (x = 0;x < FOGWIDTH;x++)
524         {
525                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
526                 data1[x][0] = b;
527                 data1[x][1] = b;
528                 data1[x][2] = b;
529                 data1[x][3] = 255;
530                 //data2[x][0] = 255 - b;
531                 //data2[x][1] = 255 - b;
532                 //data2[x][2] = 255 - b;
533                 //data2[x][3] = 255;
534         }
535         if (r_texture_fogattenuation)
536         {
537                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
539         }
540         else
541         {
542                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
543                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
544         }
545 }
546
547 static void R_BuildFogHeightTexture(void)
548 {
549         unsigned char *inpixels;
550         int size;
551         int x;
552         int y;
553         int j;
554         float c[4];
555         float f;
556         inpixels = NULL;
557         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
558         if (r_refdef.fogheighttexturename[0])
559                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
560         if (!inpixels)
561         {
562                 r_refdef.fog_height_tablesize = 0;
563                 if (r_texture_fogheighttexture)
564                         R_FreeTexture(r_texture_fogheighttexture);
565                 r_texture_fogheighttexture = NULL;
566                 if (r_refdef.fog_height_table2d)
567                         Mem_Free(r_refdef.fog_height_table2d);
568                 r_refdef.fog_height_table2d = NULL;
569                 if (r_refdef.fog_height_table1d)
570                         Mem_Free(r_refdef.fog_height_table1d);
571                 r_refdef.fog_height_table1d = NULL;
572                 return;
573         }
574         size = image_width;
575         r_refdef.fog_height_tablesize = size;
576         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
577         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
578         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
579         Mem_Free(inpixels);
580         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
581         // average fog color table accounting for every fog layer between a point
582         // and the camera.  (Note: attenuation is handled separately!)
583         for (y = 0;y < size;y++)
584         {
585                 for (x = 0;x < size;x++)
586                 {
587                         Vector4Clear(c);
588                         f = 0;
589                         if (x < y)
590                         {
591                                 for (j = x;j <= y;j++)
592                                 {
593                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
594                                         f++;
595                                 }
596                         }
597                         else
598                         {
599                                 for (j = x;j >= y;j--)
600                                 {
601                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
602                                         f++;
603                                 }
604                         }
605                         f = 1.0f / f;
606                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
609                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
610                 }
611         }
612         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
613 }
614
615 //=======================================================================================================================================================
616
617 static const char *builtinshaderstring =
618 #include "shader_glsl.h"
619 ;
620
621 const char *builtinhlslshaderstring =
622 #include "shader_hlsl.h"
623 ;
624
625 char *glslshaderstring = NULL;
626 char *hlslshaderstring = NULL;
627
628 //=======================================================================================================================================================
629
630 typedef struct shaderpermutationinfo_s
631 {
632         const char *pretext;
633         const char *name;
634 }
635 shaderpermutationinfo_t;
636
637 typedef struct shadermodeinfo_s
638 {
639         const char *vertexfilename;
640         const char *geometryfilename;
641         const char *fragmentfilename;
642         const char *pretext;
643         const char *name;
644 }
645 shadermodeinfo_t;
646
647 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
648 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
649 {
650         {"#define USEDIFFUSE\n", " diffuse"},
651         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
652         {"#define USEVIEWTINT\n", " viewtint"},
653         {"#define USECOLORMAPPING\n", " colormapping"},
654         {"#define USESATURATION\n", " saturation"},
655         {"#define USEFOGINSIDE\n", " foginside"},
656         {"#define USEFOGOUTSIDE\n", " fogoutside"},
657         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
658         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
659         {"#define USEGAMMARAMPS\n", " gammaramps"},
660         {"#define USECUBEFILTER\n", " cubefilter"},
661         {"#define USEGLOW\n", " glow"},
662         {"#define USEBLOOM\n", " bloom"},
663         {"#define USESPECULAR\n", " specular"},
664         {"#define USEPOSTPROCESSING\n", " postprocessing"},
665         {"#define USEREFLECTION\n", " reflection"},
666         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
667         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
668         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
669         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"},
670         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"},
671         {"#define USESHADOWSAMPLER\n", " shadowsampler"},
672         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"},
673         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
674         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
675         {"#define USEALPHAKILL\n", " alphakill"},
676         {"#define USEREFLECTCUBE\n", " reflectcube"},
677         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
678         {"#define USEBOUNCEGRID\n", " bouncegrid"},
679         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"},
680         {"#define USETRIPPY\n", " trippy"},
681 };
682
683 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
684 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
685 {
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
696         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
697         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
700         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
701         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
707 {
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
713         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
714         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
715         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
716         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
717         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
718         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
719         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
720         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
721         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
722         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
723         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
724         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
725         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
726 };
727
728 struct r_glsl_permutation_s;
729 typedef struct r_glsl_permutation_s
730 {
731         /// hash lookup data
732         struct r_glsl_permutation_s *hashnext;
733         unsigned int mode;
734         unsigned int permutation;
735
736         /// indicates if we have tried compiling this permutation already
737         qboolean compiled;
738         /// 0 if compilation failed
739         int program;
740         // texture units assigned to each detected uniform
741         int tex_Texture_First;
742         int tex_Texture_Second;
743         int tex_Texture_GammaRamps;
744         int tex_Texture_Normal;
745         int tex_Texture_Color;
746         int tex_Texture_Gloss;
747         int tex_Texture_Glow;
748         int tex_Texture_SecondaryNormal;
749         int tex_Texture_SecondaryColor;
750         int tex_Texture_SecondaryGloss;
751         int tex_Texture_SecondaryGlow;
752         int tex_Texture_Pants;
753         int tex_Texture_Shirt;
754         int tex_Texture_FogHeightTexture;
755         int tex_Texture_FogMask;
756         int tex_Texture_Lightmap;
757         int tex_Texture_Deluxemap;
758         int tex_Texture_Attenuation;
759         int tex_Texture_Cube;
760         int tex_Texture_Refraction;
761         int tex_Texture_Reflection;
762         int tex_Texture_ShadowMap2D;
763         int tex_Texture_CubeProjection;
764         int tex_Texture_ScreenDepth;
765         int tex_Texture_ScreenNormalMap;
766         int tex_Texture_ScreenDiffuse;
767         int tex_Texture_ScreenSpecular;
768         int tex_Texture_ReflectMask;
769         int tex_Texture_ReflectCube;
770         int tex_Texture_BounceGrid;
771         /// locations of detected uniforms in program object, or -1 if not found
772         int loc_Texture_First;
773         int loc_Texture_Second;
774         int loc_Texture_GammaRamps;
775         int loc_Texture_Normal;
776         int loc_Texture_Color;
777         int loc_Texture_Gloss;
778         int loc_Texture_Glow;
779         int loc_Texture_SecondaryNormal;
780         int loc_Texture_SecondaryColor;
781         int loc_Texture_SecondaryGloss;
782         int loc_Texture_SecondaryGlow;
783         int loc_Texture_Pants;
784         int loc_Texture_Shirt;
785         int loc_Texture_FogHeightTexture;
786         int loc_Texture_FogMask;
787         int loc_Texture_Lightmap;
788         int loc_Texture_Deluxemap;
789         int loc_Texture_Attenuation;
790         int loc_Texture_Cube;
791         int loc_Texture_Refraction;
792         int loc_Texture_Reflection;
793         int loc_Texture_ShadowMap2D;
794         int loc_Texture_CubeProjection;
795         int loc_Texture_ScreenDepth;
796         int loc_Texture_ScreenNormalMap;
797         int loc_Texture_ScreenDiffuse;
798         int loc_Texture_ScreenSpecular;
799         int loc_Texture_ReflectMask;
800         int loc_Texture_ReflectCube;
801         int loc_Texture_BounceGrid;
802         int loc_Alpha;
803         int loc_BloomBlur_Parameters;
804         int loc_ClientTime;
805         int loc_Color_Ambient;
806         int loc_Color_Diffuse;
807         int loc_Color_Specular;
808         int loc_Color_Glow;
809         int loc_Color_Pants;
810         int loc_Color_Shirt;
811         int loc_DeferredColor_Ambient;
812         int loc_DeferredColor_Diffuse;
813         int loc_DeferredColor_Specular;
814         int loc_DeferredMod_Diffuse;
815         int loc_DeferredMod_Specular;
816         int loc_DistortScaleRefractReflect;
817         int loc_EyePosition;
818         int loc_FogColor;
819         int loc_FogHeightFade;
820         int loc_FogPlane;
821         int loc_FogPlaneViewDist;
822         int loc_FogRangeRecip;
823         int loc_LightColor;
824         int loc_LightDir;
825         int loc_LightPosition;
826         int loc_OffsetMapping_ScaleSteps;
827         int loc_PixelSize;
828         int loc_ReflectColor;
829         int loc_ReflectFactor;
830         int loc_ReflectOffset;
831         int loc_RefractColor;
832         int loc_Saturation;
833         int loc_ScreenCenterRefractReflect;
834         int loc_ScreenScaleRefractReflect;
835         int loc_ScreenToDepth;
836         int loc_ShadowMap_Parameters;
837         int loc_ShadowMap_TextureScale;
838         int loc_SpecularPower;
839         int loc_UserVec1;
840         int loc_UserVec2;
841         int loc_UserVec3;
842         int loc_UserVec4;
843         int loc_ViewTintColor;
844         int loc_ViewToLight;
845         int loc_ModelToLight;
846         int loc_TexMatrix;
847         int loc_BackgroundTexMatrix;
848         int loc_ModelViewProjectionMatrix;
849         int loc_ModelViewMatrix;
850         int loc_PixelToScreenTexCoord;
851         int loc_ModelToReflectCube;
852         int loc_ShadowMapMatrix;
853         int loc_BloomColorSubtract;
854         int loc_NormalmapScrollBlend;
855         int loc_BounceGridMatrix;
856         int loc_BounceGridIntensity;
857 }
858 r_glsl_permutation_t;
859
860 #define SHADERPERMUTATION_HASHSIZE 256
861
862
863 // non-degradable "lightweight" shader parameters to keep the permutations simpler
864 // these can NOT degrade! only use for simple stuff
865 enum
866 {
867         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
868         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
869         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
870         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
871         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
872         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
873         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6 // use both alpha layers while blending materials, allows more advanced microblending
874 };
875 #define SHADERSTATICPARMS_COUNT 7
876
877 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
878 static int shaderstaticparms_count = 0;
879
880 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
881 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
882 qboolean R_CompileShader_CheckStaticParms(void)
883 {
884         static int r_compileshader_staticparms_save[1];
885         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
886         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
887
888         // detect all
889         if (r_glsl_saturation_redcompensate.integer)
890                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
891         if (r_glsl_vertextextureblend_usebothalphas.integer)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
893         if (r_shadow_glossexact.integer)
894                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
895         if (r_glsl_postprocess.integer)
896         {
897                 if (r_glsl_postprocess_uservec1_enable.integer)
898                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
899                 if (r_glsl_postprocess_uservec2_enable.integer)
900                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
901                 if (r_glsl_postprocess_uservec3_enable.integer)
902                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
903                 if (r_glsl_postprocess_uservec4_enable.integer)
904                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
905         }
906         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
907 }
908
909 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
910         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
911                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
912         else \
913                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
914 void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
915 {
916         shaderstaticparms_count = 0;
917
918         // emit all
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
926 }
927
928 /// information about each possible shader permutation
929 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
930 /// currently selected permutation
931 r_glsl_permutation_t *r_glsl_permutation;
932 /// storage for permutations linked in the hash table
933 memexpandablearray_t r_glsl_permutationarray;
934
935 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
936 {
937         //unsigned int hashdepth = 0;
938         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
939         r_glsl_permutation_t *p;
940         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
941         {
942                 if (p->mode == mode && p->permutation == permutation)
943                 {
944                         //if (hashdepth > 10)
945                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
946                         return p;
947                 }
948                 //hashdepth++;
949         }
950         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
951         p->mode = mode;
952         p->permutation = permutation;
953         p->hashnext = r_glsl_permutationhash[mode][hashindex];
954         r_glsl_permutationhash[mode][hashindex] = p;
955         //if (hashdepth > 10)
956         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
957         return p;
958 }
959
960 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
961 {
962         char *shaderstring;
963         if (!filename || !filename[0])
964                 return NULL;
965         if (!strcmp(filename, "glsl/default.glsl"))
966         {
967                 if (!glslshaderstring)
968                 {
969                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
970                         if (glslshaderstring)
971                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
972                         else
973                                 glslshaderstring = (char *)builtinshaderstring;
974                 }
975                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
976                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
977                 return shaderstring;
978         }
979         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
980         if (shaderstring)
981         {
982                 if (printfromdisknotice)
983                         Con_DPrintf("from disk %s... ", filename);
984                 return shaderstring;
985         }
986         return shaderstring;
987 }
988
989 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
990 {
991         int i;
992         int sampler;
993         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
994         char *vertexstring, *geometrystring, *fragmentstring;
995         char permutationname[256];
996         int vertstrings_count = 0;
997         int geomstrings_count = 0;
998         int fragstrings_count = 0;
999         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1000         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1001         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1002
1003         if (p->compiled)
1004                 return;
1005         p->compiled = true;
1006         p->program = 0;
1007
1008         permutationname[0] = 0;
1009         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1010         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1011         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1012
1013         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1014
1015         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1016         if(vid.support.gl20shaders130)
1017         {
1018                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1019                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1020                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1021                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1022                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1023                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1024         }
1025
1026         // the first pretext is which type of shader to compile as
1027         // (later these will all be bound together as a program object)
1028         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1029         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1030         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1031
1032         // the second pretext is the mode (for example a light source)
1033         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1034         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1035         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1036         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1037
1038         // now add all the permutation pretexts
1039         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1040         {
1041                 if (permutation & (1<<i))
1042                 {
1043                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1044                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1045                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1046                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1047                 }
1048                 else
1049                 {
1050                         // keep line numbers correct
1051                         vertstrings_list[vertstrings_count++] = "\n";
1052                         geomstrings_list[geomstrings_count++] = "\n";
1053                         fragstrings_list[fragstrings_count++] = "\n";
1054                 }
1055         }
1056
1057         // add static parms
1058         R_CompileShader_AddStaticParms(mode, permutation);
1059         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1060         vertstrings_count += shaderstaticparms_count;
1061         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1062         geomstrings_count += shaderstaticparms_count;
1063         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1064         fragstrings_count += shaderstaticparms_count;
1065
1066         // now append the shader text itself
1067         vertstrings_list[vertstrings_count++] = vertexstring;
1068         geomstrings_list[geomstrings_count++] = geometrystring;
1069         fragstrings_list[fragstrings_count++] = fragmentstring;
1070
1071         // if any sources were NULL, clear the respective list
1072         if (!vertexstring)
1073                 vertstrings_count = 0;
1074         if (!geometrystring)
1075                 geomstrings_count = 0;
1076         if (!fragmentstring)
1077                 fragstrings_count = 0;
1078
1079         // compile the shader program
1080         if (vertstrings_count + geomstrings_count + fragstrings_count)
1081                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1082         if (p->program)
1083         {
1084                 CHECKGLERROR
1085                 qglUseProgram(p->program);CHECKGLERROR
1086                 // look up all the uniform variable names we care about, so we don't
1087                 // have to look them up every time we set them
1088
1089                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1090                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1091                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1092                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1093                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1094                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1095                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1096                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1097                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1098                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1099                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1100                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1101                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1102                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1103                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1104                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1105                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1106                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1107                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1108                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1109                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1110                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1111                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1112                 p->loc_Texture_ScreenDepth        = qglGetUniformLocation(p->program, "Texture_ScreenDepth");
1113                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1114                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1115                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1116                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1117                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1118                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1119                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1120                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1121                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1122                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1123                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1124                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1125                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1126                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1127                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1128                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1129                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1130                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1131                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1132                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1133                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1134                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1135                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1136                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1137                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1138                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1139                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1140                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1141                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1142                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1143                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1144                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1145                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1146                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1147                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1148                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1149                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1150                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1151                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1152                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1153                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1154                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1155                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1156                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1157                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1158                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1159                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1160                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1161                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1162                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1163                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1164                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1165                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1166                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1167                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1168                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1169                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1170                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1171                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1172                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1173                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1174                 // initialize the samplers to refer to the texture units we use
1175                 p->tex_Texture_First = -1;
1176                 p->tex_Texture_Second = -1;
1177                 p->tex_Texture_GammaRamps = -1;
1178                 p->tex_Texture_Normal = -1;
1179                 p->tex_Texture_Color = -1;
1180                 p->tex_Texture_Gloss = -1;
1181                 p->tex_Texture_Glow = -1;
1182                 p->tex_Texture_SecondaryNormal = -1;
1183                 p->tex_Texture_SecondaryColor = -1;
1184                 p->tex_Texture_SecondaryGloss = -1;
1185                 p->tex_Texture_SecondaryGlow = -1;
1186                 p->tex_Texture_Pants = -1;
1187                 p->tex_Texture_Shirt = -1;
1188                 p->tex_Texture_FogHeightTexture = -1;
1189                 p->tex_Texture_FogMask = -1;
1190                 p->tex_Texture_Lightmap = -1;
1191                 p->tex_Texture_Deluxemap = -1;
1192                 p->tex_Texture_Attenuation = -1;
1193                 p->tex_Texture_Cube = -1;
1194                 p->tex_Texture_Refraction = -1;
1195                 p->tex_Texture_Reflection = -1;
1196                 p->tex_Texture_ShadowMap2D = -1;
1197                 p->tex_Texture_CubeProjection = -1;
1198                 p->tex_Texture_ScreenDepth = -1;
1199                 p->tex_Texture_ScreenNormalMap = -1;
1200                 p->tex_Texture_ScreenDiffuse = -1;
1201                 p->tex_Texture_ScreenSpecular = -1;
1202                 p->tex_Texture_ReflectMask = -1;
1203                 p->tex_Texture_ReflectCube = -1;
1204                 p->tex_Texture_BounceGrid = -1;
1205                 sampler = 0;
1206                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1207                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1208                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1209                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1210                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1211                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1212                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1213                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1214                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1215                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1216                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1217                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1218                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1219                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1220                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1221                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1222                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1223                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1224                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1225                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1226                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1227                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1228                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1229                 if (p->loc_Texture_ScreenDepth     >= 0) {p->tex_Texture_ScreenDepth      = sampler;qglUniform1i(p->loc_Texture_ScreenDepth     , sampler);sampler++;}
1230                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1231                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1232                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1233                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1234                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1235                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1236                 CHECKGLERROR
1237                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1238         }
1239         else
1240                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1241
1242         // free the strings
1243         if (vertexstring)
1244                 Mem_Free(vertexstring);
1245         if (geometrystring)
1246                 Mem_Free(geometrystring);
1247         if (fragmentstring)
1248                 Mem_Free(fragmentstring);
1249 }
1250
1251 void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1252 {
1253         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1254         if (r_glsl_permutation != perm)
1255         {
1256                 r_glsl_permutation = perm;
1257                 if (!r_glsl_permutation->program)
1258                 {
1259                         if (!r_glsl_permutation->compiled)
1260                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1261                         if (!r_glsl_permutation->program)
1262                         {
1263                                 // remove features until we find a valid permutation
1264                                 int i;
1265                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1266                                 {
1267                                         // reduce i more quickly whenever it would not remove any bits
1268                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1269                                         if (!(permutation & j))
1270                                                 continue;
1271                                         permutation -= j;
1272                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1273                                         if (!r_glsl_permutation->compiled)
1274                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1275                                         if (r_glsl_permutation->program)
1276                                                 break;
1277                                 }
1278                                 if (i >= SHADERPERMUTATION_COUNT)
1279                                 {
1280                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1281                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1282                                         qglUseProgram(0);CHECKGLERROR
1283                                         return; // no bit left to clear, entire mode is broken
1284                                 }
1285                         }
1286                 }
1287                 CHECKGLERROR
1288                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1289         }
1290         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1291         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1292         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1293 }
1294
1295 #ifdef SUPPORTD3D
1296
1297 #ifdef SUPPORTD3D
1298 #include <d3d9.h>
1299 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1300 extern D3DCAPS9 vid_d3d9caps;
1301 #endif
1302
1303 struct r_hlsl_permutation_s;
1304 typedef struct r_hlsl_permutation_s
1305 {
1306         /// hash lookup data
1307         struct r_hlsl_permutation_s *hashnext;
1308         unsigned int mode;
1309         unsigned int permutation;
1310
1311         /// indicates if we have tried compiling this permutation already
1312         qboolean compiled;
1313         /// NULL if compilation failed
1314         IDirect3DVertexShader9 *vertexshader;
1315         IDirect3DPixelShader9 *pixelshader;
1316 }
1317 r_hlsl_permutation_t;
1318
1319 typedef enum D3DVSREGISTER_e
1320 {
1321         D3DVSREGISTER_TexMatrix = 0, // float4x4
1322         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1323         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1324         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1325         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1326         D3DVSREGISTER_ModelToLight = 20, // float4x4
1327         D3DVSREGISTER_EyePosition = 24,
1328         D3DVSREGISTER_FogPlane = 25,
1329         D3DVSREGISTER_LightDir = 26,
1330         D3DVSREGISTER_LightPosition = 27,
1331 }
1332 D3DVSREGISTER_t;
1333
1334 typedef enum D3DPSREGISTER_e
1335 {
1336         D3DPSREGISTER_Alpha = 0,
1337         D3DPSREGISTER_BloomBlur_Parameters = 1,
1338         D3DPSREGISTER_ClientTime = 2,
1339         D3DPSREGISTER_Color_Ambient = 3,
1340         D3DPSREGISTER_Color_Diffuse = 4,
1341         D3DPSREGISTER_Color_Specular = 5,
1342         D3DPSREGISTER_Color_Glow = 6,
1343         D3DPSREGISTER_Color_Pants = 7,
1344         D3DPSREGISTER_Color_Shirt = 8,
1345         D3DPSREGISTER_DeferredColor_Ambient = 9,
1346         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1347         D3DPSREGISTER_DeferredColor_Specular = 11,
1348         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1349         D3DPSREGISTER_DeferredMod_Specular = 13,
1350         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1351         D3DPSREGISTER_EyePosition = 15, // unused
1352         D3DPSREGISTER_FogColor = 16,
1353         D3DPSREGISTER_FogHeightFade = 17,
1354         D3DPSREGISTER_FogPlane = 18,
1355         D3DPSREGISTER_FogPlaneViewDist = 19,
1356         D3DPSREGISTER_FogRangeRecip = 20,
1357         D3DPSREGISTER_LightColor = 21,
1358         D3DPSREGISTER_LightDir = 22, // unused
1359         D3DPSREGISTER_LightPosition = 23,
1360         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1361         D3DPSREGISTER_PixelSize = 25,
1362         D3DPSREGISTER_ReflectColor = 26,
1363         D3DPSREGISTER_ReflectFactor = 27,
1364         D3DPSREGISTER_ReflectOffset = 28,
1365         D3DPSREGISTER_RefractColor = 29,
1366         D3DPSREGISTER_Saturation = 30,
1367         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1368         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1369         D3DPSREGISTER_ScreenToDepth = 33,
1370         D3DPSREGISTER_ShadowMap_Parameters = 34,
1371         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1372         D3DPSREGISTER_SpecularPower = 36,
1373         D3DPSREGISTER_UserVec1 = 37,
1374         D3DPSREGISTER_UserVec2 = 38,
1375         D3DPSREGISTER_UserVec3 = 39,
1376         D3DPSREGISTER_UserVec4 = 40,
1377         D3DPSREGISTER_ViewTintColor = 41,
1378         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1379         D3DPSREGISTER_BloomColorSubtract = 43,
1380         D3DPSREGISTER_ViewToLight = 44, // float4x4
1381         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1382         D3DPSREGISTER_NormalmapScrollBlend = 52,
1383         // next at 53
1384 }
1385 D3DPSREGISTER_t;
1386
1387 /// information about each possible shader permutation
1388 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1389 /// currently selected permutation
1390 r_hlsl_permutation_t *r_hlsl_permutation;
1391 /// storage for permutations linked in the hash table
1392 memexpandablearray_t r_hlsl_permutationarray;
1393
1394 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1395 {
1396         //unsigned int hashdepth = 0;
1397         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1398         r_hlsl_permutation_t *p;
1399         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1400         {
1401                 if (p->mode == mode && p->permutation == permutation)
1402                 {
1403                         //if (hashdepth > 10)
1404                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1405                         return p;
1406                 }
1407                 //hashdepth++;
1408         }
1409         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1410         p->mode = mode;
1411         p->permutation = permutation;
1412         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1413         r_hlsl_permutationhash[mode][hashindex] = p;
1414         //if (hashdepth > 10)
1415         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1416         return p;
1417 }
1418
1419 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1420 {
1421         char *shaderstring;
1422         if (!filename || !filename[0])
1423                 return NULL;
1424         if (!strcmp(filename, "hlsl/default.hlsl"))
1425         {
1426                 if (!hlslshaderstring)
1427                 {
1428                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429                         if (hlslshaderstring)
1430                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1431                         else
1432                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1433                 }
1434                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1435                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1436                 return shaderstring;
1437         }
1438         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439         if (shaderstring)
1440         {
1441                 if (printfromdisknotice)
1442                         Con_DPrintf("from disk %s... ", filename);
1443                 return shaderstring;
1444         }
1445         return shaderstring;
1446 }
1447
1448 #include <d3dx9.h>
1449 //#include <d3dx9shader.h>
1450 //#include <d3dx9mesh.h>
1451
1452 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1453 {
1454         DWORD *vsbin = NULL;
1455         DWORD *psbin = NULL;
1456         fs_offset_t vsbinsize;
1457         fs_offset_t psbinsize;
1458 //      IDirect3DVertexShader9 *vs = NULL;
1459 //      IDirect3DPixelShader9 *ps = NULL;
1460         ID3DXBuffer *vslog = NULL;
1461         ID3DXBuffer *vsbuffer = NULL;
1462         ID3DXConstantTable *vsconstanttable = NULL;
1463         ID3DXBuffer *pslog = NULL;
1464         ID3DXBuffer *psbuffer = NULL;
1465         ID3DXConstantTable *psconstanttable = NULL;
1466         int vsresult = 0;
1467         int psresult = 0;
1468         char temp[MAX_INPUTLINE];
1469         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1470         qboolean debugshader = gl_paranoid.integer != 0;
1471         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1472         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1473         if (!debugshader)
1474         {
1475                 vsbin = (DWORD *)FS_LoadFile(va("%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1476                 psbin = (DWORD *)FS_LoadFile(va("%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1477         }
1478         if ((!vsbin && vertstring) || (!psbin && fragstring))
1479         {
1480                 const char* dllnames_d3dx9 [] =
1481                 {
1482                         "d3dx9_43.dll",
1483                         "d3dx9_42.dll",
1484                         "d3dx9_41.dll",
1485                         "d3dx9_40.dll",
1486                         "d3dx9_39.dll",
1487                         "d3dx9_38.dll",
1488                         "d3dx9_37.dll",
1489                         "d3dx9_36.dll",
1490                         "d3dx9_35.dll",
1491                         "d3dx9_34.dll",
1492                         "d3dx9_33.dll",
1493                         "d3dx9_32.dll",
1494                         "d3dx9_31.dll",
1495                         "d3dx9_30.dll",
1496                         "d3dx9_29.dll",
1497                         "d3dx9_28.dll",
1498                         "d3dx9_27.dll",
1499                         "d3dx9_26.dll",
1500                         "d3dx9_25.dll",
1501                         "d3dx9_24.dll",
1502                         NULL
1503                 };
1504                 dllhandle_t d3dx9_dll = NULL;
1505                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1506                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1507                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1508                 dllfunction_t d3dx9_dllfuncs[] =
1509                 {
1510                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1511                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1512                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1513                         {NULL, NULL}
1514                 };
1515                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1516                 {
1517                         DWORD shaderflags = 0;
1518                         if (debugshader)
1519                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1520                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1521                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1522                         if (vertstring && vertstring[0])
1523                         {
1524                                 if (debugshader)
1525                                 {
1526 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1527 //                                      FS_WriteFile(va("%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1528                                         FS_WriteFile(va("%s_vs.fx", cachename), vertstring, strlen(vertstring));
1529                                         vsresult = qD3DXCompileShaderFromFileA(va("%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1530                                 }
1531                                 else
1532                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1533                                 if (vsbuffer)
1534                                 {
1535                                         vsbinsize = vsbuffer->GetBufferSize();
1536                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1537                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1538                                         vsbuffer->Release();
1539                                 }
1540                                 if (vslog)
1541                                 {
1542                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1543                                         Con_Printf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1544                                         vslog->Release();
1545                                 }
1546                         }
1547                         if (fragstring && fragstring[0])
1548                         {
1549                                 if (debugshader)
1550                                 {
1551 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1552 //                                      FS_WriteFile(va("%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1553                                         FS_WriteFile(va("%s_ps.fx", cachename), fragstring, strlen(fragstring));
1554                                         psresult = qD3DXCompileShaderFromFileA(va("%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1555                                 }
1556                                 else
1557                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1558                                 if (psbuffer)
1559                                 {
1560                                         psbinsize = psbuffer->GetBufferSize();
1561                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1562                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1563                                         psbuffer->Release();
1564                                 }
1565                                 if (pslog)
1566                                 {
1567                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1568                                         Con_Printf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1569                                         pslog->Release();
1570                                 }
1571                         }
1572                         Sys_UnloadLibrary(&d3dx9_dll);
1573                 }
1574                 else
1575                         Con_Printf("Unable to compile shader - D3DXCompileShader function not found\n");
1576         }
1577         if (vsbin && psbin)
1578         {
1579                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1580                 if (FAILED(vsresult))
1581                         Con_Printf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1582                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1583                 if (FAILED(psresult))
1584                         Con_Printf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1585         }
1586         // free the shader data
1587         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1588         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1589 }
1590
1591 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1592 {
1593         int i;
1594         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1595         int vertstring_length = 0;
1596         int geomstring_length = 0;
1597         int fragstring_length = 0;
1598         char *t;
1599         char *vertexstring, *geometrystring, *fragmentstring;
1600         char *vertstring, *geomstring, *fragstring;
1601         char permutationname[256];
1602         char cachename[256];
1603         int vertstrings_count = 0;
1604         int geomstrings_count = 0;
1605         int fragstrings_count = 0;
1606         const char *vertstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1607         const char *geomstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1608         const char *fragstrings_list[32+3+SHADERSTATICPARMS_COUNT+1];
1609
1610         if (p->compiled)
1611                 return;
1612         p->compiled = true;
1613         p->vertexshader = NULL;
1614         p->pixelshader = NULL;
1615
1616         permutationname[0] = 0;
1617         cachename[0] = 0;
1618         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1619         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1620         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1621
1622         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1623         strlcat(cachename, "hlsl/", sizeof(cachename));
1624
1625         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1626         vertstrings_count = 0;
1627         geomstrings_count = 0;
1628         fragstrings_count = 0;
1629         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1630         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1631         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1632
1633         // the first pretext is which type of shader to compile as
1634         // (later these will all be bound together as a program object)
1635         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1636         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1637         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1638
1639         // the second pretext is the mode (for example a light source)
1640         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1641         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1642         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1643         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1644         strlcat(cachename, modeinfo->name, sizeof(cachename));
1645
1646         // now add all the permutation pretexts
1647         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1648         {
1649                 if (permutation & (1<<i))
1650                 {
1651                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1652                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1653                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1654                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1655                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1656                 }
1657                 else
1658                 {
1659                         // keep line numbers correct
1660                         vertstrings_list[vertstrings_count++] = "\n";
1661                         geomstrings_list[geomstrings_count++] = "\n";
1662                         fragstrings_list[fragstrings_count++] = "\n";
1663                 }
1664         }
1665
1666         // add static parms
1667         R_CompileShader_AddStaticParms(mode, permutation);
1668         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1669         vertstrings_count += shaderstaticparms_count;
1670         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1671         geomstrings_count += shaderstaticparms_count;
1672         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1673         fragstrings_count += shaderstaticparms_count;
1674
1675         // replace spaces in the cachename with _ characters
1676         for (i = 0;cachename[i];i++)
1677                 if (cachename[i] == ' ')
1678                         cachename[i] = '_';
1679
1680         // now append the shader text itself
1681         vertstrings_list[vertstrings_count++] = vertexstring;
1682         geomstrings_list[geomstrings_count++] = geometrystring;
1683         fragstrings_list[fragstrings_count++] = fragmentstring;
1684
1685         // if any sources were NULL, clear the respective list
1686         if (!vertexstring)
1687                 vertstrings_count = 0;
1688         if (!geometrystring)
1689                 geomstrings_count = 0;
1690         if (!fragmentstring)
1691                 fragstrings_count = 0;
1692
1693         vertstring_length = 0;
1694         for (i = 0;i < vertstrings_count;i++)
1695                 vertstring_length += strlen(vertstrings_list[i]);
1696         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1697         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1698                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1699
1700         geomstring_length = 0;
1701         for (i = 0;i < geomstrings_count;i++)
1702                 geomstring_length += strlen(geomstrings_list[i]);
1703         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1704         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1705                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1706
1707         fragstring_length = 0;
1708         for (i = 0;i < fragstrings_count;i++)
1709                 fragstring_length += strlen(fragstrings_list[i]);
1710         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1711         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1712                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1713
1714         // try to load the cached shader, or generate one
1715         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1716
1717         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1718                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1719         else
1720                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1721
1722         // free the strings
1723         if (vertstring)
1724                 Mem_Free(vertstring);
1725         if (geomstring)
1726                 Mem_Free(geomstring);
1727         if (fragstring)
1728                 Mem_Free(fragstring);
1729         if (vertexstring)
1730                 Mem_Free(vertexstring);
1731         if (geometrystring)
1732                 Mem_Free(geometrystring);
1733         if (fragmentstring)
1734                 Mem_Free(fragmentstring);
1735 }
1736
1737 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1738 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1739 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);}
1740 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);}
1741 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);}
1742 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);}
1743
1744 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1745 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1746 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);}
1747 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);}
1748 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);}
1749 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);}
1750
1751 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1752 {
1753         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1754         if (r_hlsl_permutation != perm)
1755         {
1756                 r_hlsl_permutation = perm;
1757                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1758                 {
1759                         if (!r_hlsl_permutation->compiled)
1760                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1761                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1762                         {
1763                                 // remove features until we find a valid permutation
1764                                 int i;
1765                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1766                                 {
1767                                         // reduce i more quickly whenever it would not remove any bits
1768                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1769                                         if (!(permutation & j))
1770                                                 continue;
1771                                         permutation -= j;
1772                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1773                                         if (!r_hlsl_permutation->compiled)
1774                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1775                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1776                                                 break;
1777                                 }
1778                                 if (i >= SHADERPERMUTATION_COUNT)
1779                                 {
1780                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1781                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1782                                         return; // no bit left to clear, entire mode is broken
1783                                 }
1784                         }
1785                 }
1786                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1787                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1788         }
1789         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1790         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1791         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1792 }
1793 #endif
1794
1795 void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1796 {
1797         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1798         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1799         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1800         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1801 }
1802
1803 void R_GLSL_Restart_f(void)
1804 {
1805         unsigned int i, limit;
1806         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1807                 Mem_Free(glslshaderstring);
1808         glslshaderstring = NULL;
1809         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1810                 Mem_Free(hlslshaderstring);
1811         hlslshaderstring = NULL;
1812         switch(vid.renderpath)
1813         {
1814         case RENDERPATH_D3D9:
1815 #ifdef SUPPORTD3D
1816                 {
1817                         r_hlsl_permutation_t *p;
1818                         r_hlsl_permutation = NULL;
1819                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1820                         for (i = 0;i < limit;i++)
1821                         {
1822                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1823                                 {
1824                                         if (p->vertexshader)
1825                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1826                                         if (p->pixelshader)
1827                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1828                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1829                                 }
1830                         }
1831                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1832                 }
1833 #endif
1834                 break;
1835         case RENDERPATH_D3D10:
1836                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1837                 break;
1838         case RENDERPATH_D3D11:
1839                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1840                 break;
1841         case RENDERPATH_GL20:
1842         case RENDERPATH_GLES2:
1843                 {
1844                         r_glsl_permutation_t *p;
1845                         r_glsl_permutation = NULL;
1846                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1847                         for (i = 0;i < limit;i++)
1848                         {
1849                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1850                                 {
1851                                         GL_Backend_FreeProgram(p->program);
1852                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1853                                 }
1854                         }
1855                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1856                 }
1857                 break;
1858         case RENDERPATH_GL11:
1859         case RENDERPATH_GL13:
1860         case RENDERPATH_GLES1:
1861                 break;
1862         case RENDERPATH_SOFT:
1863                 break;
1864         }
1865 }
1866
1867 void R_GLSL_DumpShader_f(void)
1868 {
1869         int i;
1870         qfile_t *file;
1871
1872         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1873         if (file)
1874         {
1875                 FS_Print(file, "/* The engine may define the following macros:\n");
1876                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1877                 for (i = 0;i < SHADERMODE_COUNT;i++)
1878                         FS_Print(file, glslshadermodeinfo[i].pretext);
1879                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1880                         FS_Print(file, shaderpermutationinfo[i].pretext);
1881                 FS_Print(file, "*/\n");
1882                 FS_Print(file, builtinshaderstring);
1883                 FS_Close(file);
1884                 Con_Printf("glsl/default.glsl written\n");
1885         }
1886         else
1887                 Con_Printf("failed to write to glsl/default.glsl\n");
1888
1889         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1890         if (file)
1891         {
1892                 FS_Print(file, "/* The engine may define the following macros:\n");
1893                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1894                 for (i = 0;i < SHADERMODE_COUNT;i++)
1895                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1896                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1897                         FS_Print(file, shaderpermutationinfo[i].pretext);
1898                 FS_Print(file, "*/\n");
1899                 FS_Print(file, builtinhlslshaderstring);
1900                 FS_Close(file);
1901                 Con_Printf("hlsl/default.hlsl written\n");
1902         }
1903         else
1904                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1905 }
1906
1907 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy)
1908 {
1909         unsigned int permutation = 0;
1910         if (r_trippy.integer && !notrippy)
1911                 permutation |= SHADERPERMUTATION_TRIPPY;
1912         permutation |= SHADERPERMUTATION_VIEWTINT;
1913         if (first)
1914                 permutation |= SHADERPERMUTATION_DIFFUSE;
1915         if (second)
1916                 permutation |= SHADERPERMUTATION_SPECULAR;
1917         if (texturemode == GL_MODULATE)
1918                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1919         else if (texturemode == GL_ADD)
1920                 permutation |= SHADERPERMUTATION_GLOW;
1921         else if (texturemode == GL_DECAL)
1922                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1923         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1924                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1925         if (!second)
1926                 texturemode = GL_MODULATE;
1927         if (vid.allowalphatocoverage)
1928                 GL_AlphaToCoverage(false);
1929         switch (vid.renderpath)
1930         {
1931         case RENDERPATH_D3D9:
1932 #ifdef SUPPORTD3D
1933                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1934                 R_Mesh_TexBind(GL20TU_FIRST , first );
1935                 R_Mesh_TexBind(GL20TU_SECOND, second);
1936                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1937                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1938 #endif
1939                 break;
1940         case RENDERPATH_D3D10:
1941                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1942                 break;
1943         case RENDERPATH_D3D11:
1944                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1945                 break;
1946         case RENDERPATH_GL20:
1947         case RENDERPATH_GLES2:
1948                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1949                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1950                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1951                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1952                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1953                 break;
1954         case RENDERPATH_GL13:
1955         case RENDERPATH_GLES1:
1956                 R_Mesh_TexBind(0, first );
1957                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1958                 R_Mesh_TexBind(1, second);
1959                 if (second)
1960                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1961                 break;
1962         case RENDERPATH_GL11:
1963                 R_Mesh_TexBind(0, first );
1964                 break;
1965         case RENDERPATH_SOFT:
1966                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1967                 R_Mesh_TexBind(GL20TU_FIRST , first );
1968                 R_Mesh_TexBind(GL20TU_SECOND, second);
1969                 break;
1970         }
1971 }
1972
1973 void R_SetupShader_DepthOrShadow(qboolean notrippy)
1974 {
1975         unsigned int permutation = 0;
1976         if (r_trippy.integer && !notrippy)
1977                 permutation |= SHADERPERMUTATION_TRIPPY;
1978         if (vid.allowalphatocoverage)
1979                 GL_AlphaToCoverage(false);
1980         switch (vid.renderpath)
1981         {
1982         case RENDERPATH_D3D9:
1983 #ifdef SUPPORTD3D
1984                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1985 #endif
1986                 break;
1987         case RENDERPATH_D3D10:
1988                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1989                 break;
1990         case RENDERPATH_D3D11:
1991                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1992                 break;
1993         case RENDERPATH_GL20:
1994         case RENDERPATH_GLES2:
1995                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1996                 break;
1997         case RENDERPATH_GL13:
1998         case RENDERPATH_GLES1:
1999                 R_Mesh_TexBind(0, 0);
2000                 R_Mesh_TexBind(1, 0);
2001                 break;
2002         case RENDERPATH_GL11:
2003                 R_Mesh_TexBind(0, 0);
2004                 break;
2005         case RENDERPATH_SOFT:
2006                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2007                 break;
2008         }
2009 }
2010
2011 void R_SetupShader_ShowDepth(qboolean notrippy)
2012 {
2013         int permutation = 0;
2014         if (r_trippy.integer && !notrippy)
2015                 permutation |= SHADERPERMUTATION_TRIPPY;
2016         if (vid.allowalphatocoverage)
2017                 GL_AlphaToCoverage(false);
2018         switch (vid.renderpath)
2019         {
2020         case RENDERPATH_D3D9:
2021 #ifdef SUPPORTHLSL
2022                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2023 #endif
2024                 break;
2025         case RENDERPATH_D3D10:
2026                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2027                 break;
2028         case RENDERPATH_D3D11:
2029                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2030                 break;
2031         case RENDERPATH_GL20:
2032         case RENDERPATH_GLES2:
2033                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2034                 break;
2035         case RENDERPATH_GL13:
2036         case RENDERPATH_GLES1:
2037                 break;
2038         case RENDERPATH_GL11:
2039                 break;
2040         case RENDERPATH_SOFT:
2041                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2042                 break;
2043         }
2044 }
2045
2046 extern qboolean r_shadow_usingdeferredprepass;
2047 extern cvar_t r_shadow_deferred_8bitrange;
2048 extern rtexture_t *r_shadow_attenuationgradienttexture;
2049 extern rtexture_t *r_shadow_attenuation2dtexture;
2050 extern rtexture_t *r_shadow_attenuation3dtexture;
2051 extern qboolean r_shadow_usingshadowmap2d;
2052 extern qboolean r_shadow_usingshadowmaportho;
2053 extern float r_shadow_shadowmap_texturescale[2];
2054 extern float r_shadow_shadowmap_parameters[4];
2055 extern qboolean r_shadow_shadowmapvsdct;
2056 extern qboolean r_shadow_shadowmapsampler;
2057 extern int r_shadow_shadowmappcf;
2058 extern rtexture_t *r_shadow_shadowmap2dtexture;
2059 extern rtexture_t *r_shadow_shadowmap2dcolortexture;
2060 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2061 extern matrix4x4_t r_shadow_shadowmapmatrix;
2062 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2063 extern int r_shadow_prepass_width;
2064 extern int r_shadow_prepass_height;
2065 extern rtexture_t *r_shadow_prepassgeometrydepthtexture;
2066 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2067 extern rtexture_t *r_shadow_prepassgeometrydepthcolortexture;
2068 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2069 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2070
2071 #define BLENDFUNC_ALLOWS_COLORMOD      1
2072 #define BLENDFUNC_ALLOWS_FOG           2
2073 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2074 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2075 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2076 static int R_BlendFuncFlags(int src, int dst)
2077 {
2078         int r = 0;
2079
2080         // a blendfunc allows colormod if:
2081         // a) it can never keep the destination pixel invariant, or
2082         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2083         // this is to prevent unintended side effects from colormod
2084
2085         // a blendfunc allows fog if:
2086         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2087         // this is to prevent unintended side effects from fog
2088
2089         // these checks are the output of fogeval.pl
2090
2091         r |= BLENDFUNC_ALLOWS_COLORMOD;
2092         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2093         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2094         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2095         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2097         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2098         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2100         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2101         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2103         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2104         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2105         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2106         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2107         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2108         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2109         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2112         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113
2114         return r;
2115 }
2116
2117 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)
2118 {
2119         // select a permutation of the lighting shader appropriate to this
2120         // combination of texture, entity, light source, and fogging, only use the
2121         // minimum features necessary to avoid wasting rendering time in the
2122         // fragment shader on features that are not being used
2123         unsigned int permutation = 0;
2124         unsigned int mode = 0;
2125         int blendfuncflags;
2126         static float dummy_colormod[3] = {1, 1, 1};
2127         float *colormod = rsurface.colormod;
2128         float m16f[16];
2129         matrix4x4_t tempmatrix;
2130         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2131         if (r_trippy.integer && !notrippy)
2132                 permutation |= SHADERPERMUTATION_TRIPPY;
2133         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2134                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2135         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2136                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2137         if (rsurfacepass == RSURFPASS_BACKGROUND)
2138         {
2139                 // distorted background
2140                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2141                 {
2142                         mode = SHADERMODE_WATER;
2143                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2144                         {
2145                                 // this is the right thing to do for wateralpha
2146                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2147                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2148                         }
2149                         else
2150                         {
2151                                 // this is the right thing to do for entity alpha
2152                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2153                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2154                         }
2155                 }
2156                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2157                 {
2158                         mode = SHADERMODE_REFRACTION;
2159                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2160                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2161                 }
2162                 else
2163                 {
2164                         mode = SHADERMODE_GENERIC;
2165                         permutation |= SHADERPERMUTATION_DIFFUSE;
2166                         GL_BlendFunc(GL_ONE, GL_ZERO);
2167                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2168                 }
2169                 if (vid.allowalphatocoverage)
2170                         GL_AlphaToCoverage(false);
2171         }
2172         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2173         {
2174                 if (r_glsl_offsetmapping.integer)
2175                 {
2176                         switch(rsurface.texture->offsetmapping)
2177                         {
2178                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2179                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2180                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2181                         case OFFSETMAPPING_OFF: break;
2182                         }
2183                 }
2184                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2185                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2186                 // normalmap (deferred prepass), may use alpha test on diffuse
2187                 mode = SHADERMODE_DEFERREDGEOMETRY;
2188                 GL_BlendFunc(GL_ONE, GL_ZERO);
2189                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2190                 if (vid.allowalphatocoverage)
2191                         GL_AlphaToCoverage(false);
2192         }
2193         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2194         {
2195                 if (r_glsl_offsetmapping.integer)
2196                 {
2197                         switch(rsurface.texture->offsetmapping)
2198                         {
2199                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2200                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202                         case OFFSETMAPPING_OFF: break;
2203                         }
2204                 }
2205                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2206                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2207                 // light source
2208                 mode = SHADERMODE_LIGHTSOURCE;
2209                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2210                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2211                 if (diffusescale > 0)
2212                         permutation |= SHADERPERMUTATION_DIFFUSE;
2213                 if (specularscale > 0)
2214                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2215                 if (r_refdef.fogenabled)
2216                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2217                 if (rsurface.texture->colormapping)
2218                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2219                 if (r_shadow_usingshadowmap2d)
2220                 {
2221                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2222                         if(r_shadow_shadowmapvsdct)
2223                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2224
2225                         if (r_shadow_shadowmapsampler)
2226                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2227                         if (r_shadow_shadowmappcf > 1)
2228                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2229                         else if (r_shadow_shadowmappcf)
2230                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2231                 }
2232                 if (rsurface.texture->reflectmasktexture)
2233                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2234                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2235                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2236                 if (vid.allowalphatocoverage)
2237                         GL_AlphaToCoverage(false);
2238         }
2239         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2240         {
2241                 if (r_glsl_offsetmapping.integer)
2242                 {
2243                         switch(rsurface.texture->offsetmapping)
2244                         {
2245                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2246                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2247                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2248                         case OFFSETMAPPING_OFF: break;
2249                         }
2250                 }
2251                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2252                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2253                 // unshaded geometry (fullbright or ambient model lighting)
2254                 mode = SHADERMODE_FLATCOLOR;
2255                 ambientscale = diffusescale = specularscale = 0;
2256                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2257                         permutation |= SHADERPERMUTATION_GLOW;
2258                 if (r_refdef.fogenabled)
2259                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2260                 if (rsurface.texture->colormapping)
2261                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2262                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2263                 {
2264                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2265                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2266
2267                         if (r_shadow_shadowmapsampler)
2268                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2269                         if (r_shadow_shadowmappcf > 1)
2270                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2271                         else if (r_shadow_shadowmappcf)
2272                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2273                 }
2274                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2275                         permutation |= SHADERPERMUTATION_REFLECTION;
2276                 if (rsurface.texture->reflectmasktexture)
2277                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2278                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2279                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2280                 // when using alphatocoverage, we don't need alphakill
2281                 if (vid.allowalphatocoverage)
2282                 {
2283                         if (r_transparent_alphatocoverage.integer)
2284                         {
2285                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2286                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2287                         }
2288                         else
2289                                 GL_AlphaToCoverage(false);
2290                 }
2291         }
2292         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2293         {
2294                 if (r_glsl_offsetmapping.integer)
2295                 {
2296                         switch(rsurface.texture->offsetmapping)
2297                         {
2298                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2299                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2300                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2301                         case OFFSETMAPPING_OFF: break;
2302                         }
2303                 }
2304                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2305                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2306                 // directional model lighting
2307                 mode = SHADERMODE_LIGHTDIRECTION;
2308                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2309                         permutation |= SHADERPERMUTATION_GLOW;
2310                 permutation |= SHADERPERMUTATION_DIFFUSE;
2311                 if (specularscale > 0)
2312                         permutation |= SHADERPERMUTATION_SPECULAR;
2313                 if (r_refdef.fogenabled)
2314                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2315                 if (rsurface.texture->colormapping)
2316                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2317                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2318                 {
2319                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2320                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2321
2322                         if (r_shadow_shadowmapsampler)
2323                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2324                         if (r_shadow_shadowmappcf > 1)
2325                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2326                         else if (r_shadow_shadowmappcf)
2327                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2328                 }
2329                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2330                         permutation |= SHADERPERMUTATION_REFLECTION;
2331                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2332                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2333                 if (rsurface.texture->reflectmasktexture)
2334                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2335                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2336                 {
2337                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2338                         if (r_shadow_bouncegriddirectional)
2339                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2340                 }
2341                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2342                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2343                 // when using alphatocoverage, we don't need alphakill
2344                 if (vid.allowalphatocoverage)
2345                 {
2346                         if (r_transparent_alphatocoverage.integer)
2347                         {
2348                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2349                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2350                         }
2351                         else
2352                                 GL_AlphaToCoverage(false);
2353                 }
2354         }
2355         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2356         {
2357                 if (r_glsl_offsetmapping.integer)
2358                 {
2359                         switch(rsurface.texture->offsetmapping)
2360                         {
2361                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2362                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2363                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2364                         case OFFSETMAPPING_OFF: break;
2365                         }
2366                 }
2367                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2368                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2369                 // ambient model lighting
2370                 mode = SHADERMODE_LIGHTDIRECTION;
2371                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2372                         permutation |= SHADERPERMUTATION_GLOW;
2373                 if (r_refdef.fogenabled)
2374                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2375                 if (rsurface.texture->colormapping)
2376                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2377                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2378                 {
2379                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2380                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2381
2382                         if (r_shadow_shadowmapsampler)
2383                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2384                         if (r_shadow_shadowmappcf > 1)
2385                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2386                         else if (r_shadow_shadowmappcf)
2387                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2388                 }
2389                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2390                         permutation |= SHADERPERMUTATION_REFLECTION;
2391                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2392                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2393                 if (rsurface.texture->reflectmasktexture)
2394                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2395                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2396                 {
2397                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2398                         if (r_shadow_bouncegriddirectional)
2399                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2400                 }
2401                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2402                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2403                 // when using alphatocoverage, we don't need alphakill
2404                 if (vid.allowalphatocoverage)
2405                 {
2406                         if (r_transparent_alphatocoverage.integer)
2407                         {
2408                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2409                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2410                         }
2411                         else
2412                                 GL_AlphaToCoverage(false);
2413                 }
2414         }
2415         else
2416         {
2417                 if (r_glsl_offsetmapping.integer)
2418                 {
2419                         switch(rsurface.texture->offsetmapping)
2420                         {
2421                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2422                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2423                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2424                         case OFFSETMAPPING_OFF: break;
2425                         }
2426                 }
2427                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2428                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2429                 // lightmapped wall
2430                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2431                         permutation |= SHADERPERMUTATION_GLOW;
2432                 if (r_refdef.fogenabled)
2433                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2434                 if (rsurface.texture->colormapping)
2435                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2436                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2437                 {
2438                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2439                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2440
2441                         if (r_shadow_shadowmapsampler)
2442                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2443                         if (r_shadow_shadowmappcf > 1)
2444                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2445                         else if (r_shadow_shadowmappcf)
2446                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2447                 }
2448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2449                         permutation |= SHADERPERMUTATION_REFLECTION;
2450                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2451                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2452                 if (rsurface.texture->reflectmasktexture)
2453                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2454                 if (FAKELIGHT_ENABLED)
2455                 {
2456                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2457                         mode = SHADERMODE_FAKELIGHT;
2458                         permutation |= SHADERPERMUTATION_DIFFUSE;
2459                         if (specularscale > 0)
2460                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2461                 }
2462                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2463                 {
2464                         // deluxemapping (light direction texture)
2465                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2466                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2467                         else
2468                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2469                         permutation |= SHADERPERMUTATION_DIFFUSE;
2470                         if (specularscale > 0)
2471                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2472                 }
2473                 else if (r_glsl_deluxemapping.integer >= 2)
2474                 {
2475                         // fake deluxemapping (uniform light direction in tangentspace)
2476                         if (rsurface.uselightmaptexture)
2477                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2478                         else
2479                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2480                         permutation |= SHADERPERMUTATION_DIFFUSE;
2481                         if (specularscale > 0)
2482                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2483                 }
2484                 else if (rsurface.uselightmaptexture)
2485                 {
2486                         // ordinary lightmapping (q1bsp, q3bsp)
2487                         mode = SHADERMODE_LIGHTMAP;
2488                 }
2489                 else
2490                 {
2491                         // ordinary vertex coloring (q3bsp)
2492                         mode = SHADERMODE_VERTEXCOLOR;
2493                 }
2494                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2495                 {
2496                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2497                         if (r_shadow_bouncegriddirectional)
2498                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2499                 }
2500                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2501                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2502                 // when using alphatocoverage, we don't need alphakill
2503                 if (vid.allowalphatocoverage)
2504                 {
2505                         if (r_transparent_alphatocoverage.integer)
2506                         {
2507                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2508                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2509                         }
2510                         else
2511                                 GL_AlphaToCoverage(false);
2512                 }
2513         }
2514         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2515                 colormod = dummy_colormod;
2516         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2517                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2518         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2519                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2520         switch(vid.renderpath)
2521         {
2522         case RENDERPATH_D3D9:
2523 #ifdef SUPPORTD3D
2524                 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);
2525                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2526                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2527                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2528                 if (mode == SHADERMODE_LIGHTSOURCE)
2529                 {
2530                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2531                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2532                 }
2533                 else
2534                 {
2535                         if (mode == SHADERMODE_LIGHTDIRECTION)
2536                         {
2537                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2538                         }
2539                 }
2540                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2541                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2542                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2543                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2544                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2545
2546                 if (mode == SHADERMODE_LIGHTSOURCE)
2547                 {
2548                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2549                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2550                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2551                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2552                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2553
2554                         // additive passes are only darkened by fog, not tinted
2555                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2556                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2557                 }
2558                 else
2559                 {
2560                         if (mode == SHADERMODE_FLATCOLOR)
2561                         {
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2563                         }
2564                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2565                         {
2566                                 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]);
2567                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2568                                 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);
2569                                 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);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2573                         }
2574                         else
2575                         {
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2578                                 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);
2579                                 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);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2581                         }
2582                         // additive passes are only darkened by fog, not tinted
2583                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2584                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2585                         else
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2587                         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);
2588                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2589                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2590                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2591                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2592                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2593                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2594                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2595                         if (mode == SHADERMODE_WATER)
2596                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2597                 }
2598                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2599                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2600                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2601                 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));
2602                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2603                 if (rsurface.texture->pantstexture)
2604                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2605                 else
2606                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2607                 if (rsurface.texture->shirttexture)
2608                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2609                 else
2610                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2611                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2612                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2613                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2614                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2615                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2616                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2617                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2618                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2619                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2620                         );
2621                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2622                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2623
2624                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2625                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2626                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2627                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2628                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2629                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2630                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2631                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2632                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2633                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2634                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2635                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2636                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2637                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2638                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2639                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2640                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2641                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2642                 {
2643                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2644                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2645                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2646                 }
2647                 else
2648                 {
2649                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2650                 }
2651 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2652 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2653                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2654                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2655                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2656                 {
2657                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2658                         if (rsurface.rtlight)
2659                         {
2660                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2661                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2662                         }
2663                 }
2664 #endif
2665                 break;
2666         case RENDERPATH_D3D10:
2667                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2668                 break;
2669         case RENDERPATH_D3D11:
2670                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2671                 break;
2672         case RENDERPATH_GL20:
2673         case RENDERPATH_GLES2:
2674                 if (!vid.useinterleavedarrays)
2675                 {
2676                         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);
2677                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2678                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2679                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2680                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2681                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2682                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2683                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2684                 }
2685                 else
2686                 {
2687                         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);
2688                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2689                 }
2690                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2691                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2692                 if (mode == SHADERMODE_LIGHTSOURCE)
2693                 {
2694                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2695                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2696                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2697                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2698                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2699                         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);
2700         
2701                         // additive passes are only darkened by fog, not tinted
2702                         if (r_glsl_permutation->loc_FogColor >= 0)
2703                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2704                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2705                 }
2706                 else
2707                 {
2708                         if (mode == SHADERMODE_FLATCOLOR)
2709                         {
2710                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2711                         }
2712                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2713                         {
2714                                 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]);
2715                                 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]);
2716                                 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);
2717                                 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);
2718                                 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);
2719                                 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]);
2720                                 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]);
2721                         }
2722                         else
2723                         {
2724                                 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]);
2725                                 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]);
2726                                 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);
2727                                 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);
2728                                 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);
2729                         }
2730                         // additive passes are only darkened by fog, not tinted
2731                         if (r_glsl_permutation->loc_FogColor >= 0)
2732                         {
2733                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2734                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2735                                 else
2736                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2737                         }
2738                         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);
2739                         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]);
2740                         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]);
2741                         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]);
2742                         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]);
2743                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2744                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2745                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2746                         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]);
2747                 }
2748                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2749                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2750                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2751                 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]);
2752                 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]);
2753
2754                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2755                 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));
2756                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2757                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2758                 {
2759                         if (rsurface.texture->pantstexture)
2760                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2761                         else
2762                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2763                 }
2764                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2765                 {
2766                         if (rsurface.texture->shirttexture)
2767                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2768                         else
2769                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2770                 }
2771                 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]);
2772                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2773                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2774                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2775                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2776                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2777                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2778                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2779                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2780                         );
2781                 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]);
2782                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2783                 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);}
2784                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2785
2786                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2787                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2788                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2789                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2790                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2791                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2792                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2793                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2794                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2795                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2796                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2797                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2798                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2799                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2800                 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);
2801                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2802                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2803                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2804                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2805                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2806                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2807                 {
2808                         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);
2809                         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);
2810                         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);
2811                 }
2812                 else
2813                 {
2814                         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);
2815                 }
2816                 if (r_glsl_permutation->tex_Texture_ScreenDepth     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth       , r_shadow_prepassgeometrydepthtexture                );
2817                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2818                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2819                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2820                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2821                 {
2822                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2dtexture                         );
2823                         if (rsurface.rtlight)
2824                         {
2825                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2826                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2827                         }
2828                 }
2829                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2830                 CHECKGLERROR
2831                 break;
2832         case RENDERPATH_GL11:
2833         case RENDERPATH_GL13:
2834         case RENDERPATH_GLES1:
2835                 break;
2836         case RENDERPATH_SOFT:
2837                 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);
2838                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2839                 R_SetupShader_SetPermutationSoft(mode, permutation);
2840                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2841                 if (mode == SHADERMODE_LIGHTSOURCE)
2842                 {
2843                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2844                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2845                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2846                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2847                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2848                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2849         
2850                         // additive passes are only darkened by fog, not tinted
2851                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2852                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2853                 }
2854                 else
2855                 {
2856                         if (mode == SHADERMODE_FLATCOLOR)
2857                         {
2858                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2859                         }
2860                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2861                         {
2862                                 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]);
2863                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2864                                 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);
2865                                 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);
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2867                                 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]);
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2869                         }
2870                         else
2871                         {
2872                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2873                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2874                                 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);
2875                                 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);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value, specularscale * r_shadow_deferred_8bitrange.value);
2877                         }
2878                         // additive passes are only darkened by fog, not tinted
2879                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2881                         else
2882                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2883                         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);
2884                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_waterstate.screenscale[0], r_waterstate.screenscale[1], r_waterstate.screenscale[0], r_waterstate.screenscale[1]);
2885                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_waterstate.screencenter[0], r_waterstate.screencenter[1], r_waterstate.screencenter[0], r_waterstate.screencenter[1]);
2886                         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]);
2887                         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]);
2888                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2889                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2890                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2891                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2892                 }
2893                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2894                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2895                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2896                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2897                 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]);
2898
2899                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2900                 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));
2901                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2902                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2903                 {
2904                         if (rsurface.texture->pantstexture)
2905                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2906                         else
2907                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2908                 }
2909                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2910                 {
2911                         if (rsurface.texture->shirttexture)
2912                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2913                         else
2914                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2915                 }
2916                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2917                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2918                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2919                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2920                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2921                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2922                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2923                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2924                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2925                         );
2926                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2927                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2928
2929                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2930                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2931                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2932                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2933                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2934                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2935                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2936                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2937                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2938                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2939                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2940                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2941                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2942                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2943                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2944                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2945                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2946                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2947                 {
2948                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2949                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2950                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2951                 }
2952                 else
2953                 {
2954                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2955                 }
2956 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENDEPTH       , r_shadow_prepassgeometrydepthtexture                );
2957 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2958                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2959                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2960                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2961                 {
2962                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2dcolortexture);
2963                         if (rsurface.rtlight)
2964                         {
2965                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2966                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2967                         }
2968                 }
2969                 break;
2970         }
2971 }
2972
2973 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2974 {
2975         // select a permutation of the lighting shader appropriate to this
2976         // combination of texture, entity, light source, and fogging, only use the
2977         // minimum features necessary to avoid wasting rendering time in the
2978         // fragment shader on features that are not being used
2979         unsigned int permutation = 0;
2980         unsigned int mode = 0;
2981         const float *lightcolorbase = rtlight->currentcolor;
2982         float ambientscale = rtlight->ambientscale;
2983         float diffusescale = rtlight->diffusescale;
2984         float specularscale = rtlight->specularscale;
2985         // this is the location of the light in view space
2986         vec3_t viewlightorigin;
2987         // this transforms from view space (camera) to light space (cubemap)
2988         matrix4x4_t viewtolight;
2989         matrix4x4_t lighttoview;
2990         float viewtolight16f[16];
2991         float range = 1.0f / r_shadow_deferred_8bitrange.value;
2992         // light source
2993         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2994         if (rtlight->currentcubemap != r_texture_whitecube)
2995                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2996         if (diffusescale > 0)
2997                 permutation |= SHADERPERMUTATION_DIFFUSE;
2998         if (specularscale > 0 && r_shadow_gloss.integer > 0)
2999                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3000         if (r_shadow_usingshadowmap2d)
3001         {
3002                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3003                 if (r_shadow_shadowmapvsdct)
3004                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3005
3006                 if (r_shadow_shadowmapsampler)
3007                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3008                 if (r_shadow_shadowmappcf > 1)
3009                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3010                 else if (r_shadow_shadowmappcf)
3011                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3012         }
3013         if (vid.allowalphatocoverage)
3014                 GL_AlphaToCoverage(false);
3015         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3016         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3017         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3018         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3019         switch(vid.renderpath)
3020         {
3021         case RENDERPATH_D3D9:
3022 #ifdef SUPPORTD3D
3023                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3024                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3025                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3026                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3027                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3028                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3029                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3030                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3031                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3032                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3033                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3034
3035                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3036                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthcolortexture           );
3037                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3038                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3039                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dcolortexture                    );
3040                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3041 #endif
3042                 break;
3043         case RENDERPATH_D3D10:
3044                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3045                 break;
3046         case RENDERPATH_D3D11:
3047                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3048                 break;
3049         case RENDERPATH_GL20:
3050         case RENDERPATH_GLES2:
3051                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3052                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3053                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3054                 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);
3055                 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);
3056                 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);
3057                 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]);
3058                 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]);
3059                 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) - 1.0f);
3060                 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]);
3061                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3062
3063                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3064                 if (r_glsl_permutation->tex_Texture_ScreenDepth       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDepth        , r_shadow_prepassgeometrydepthtexture                );
3065                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3066                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3067                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2dtexture                         );
3068                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3069                 break;
3070         case RENDERPATH_GL11:
3071         case RENDERPATH_GL13:
3072         case RENDERPATH_GLES1:
3073                 break;
3074         case RENDERPATH_SOFT:
3075                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3076                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3077                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3078                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale  * range, lightcolorbase[1] * ambientscale  * range, lightcolorbase[2] * ambientscale  * range);
3079                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale  * range, lightcolorbase[1] * diffusescale  * range, lightcolorbase[2] * diffusescale  * range);
3080                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale * range, lightcolorbase[1] * specularscale * range, lightcolorbase[2] * specularscale * range);
3081                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3082                 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]);
3083                 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) - 1.0f);
3084                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3085                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3086
3087                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3088                 R_Mesh_TexBind(GL20TU_SCREENDEPTH        , r_shadow_prepassgeometrydepthtexture                );
3089                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3090                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3091                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2dtexture                         );
3092                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3093                 break;
3094         }
3095 }
3096
3097 #define SKINFRAME_HASH 1024
3098
3099 typedef struct
3100 {
3101         int loadsequence; // incremented each level change
3102         memexpandablearray_t array;
3103         skinframe_t *hash[SKINFRAME_HASH];
3104 }
3105 r_skinframe_t;
3106 r_skinframe_t r_skinframe;
3107
3108 void R_SkinFrame_PrepareForPurge(void)
3109 {
3110         r_skinframe.loadsequence++;
3111         // wrap it without hitting zero
3112         if (r_skinframe.loadsequence >= 200)
3113                 r_skinframe.loadsequence = 1;
3114 }
3115
3116 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3117 {
3118         if (!skinframe)
3119                 return;
3120         // mark the skinframe as used for the purging code
3121         skinframe->loadsequence = r_skinframe.loadsequence;
3122 }
3123
3124 void R_SkinFrame_Purge(void)
3125 {
3126         int i;
3127         skinframe_t *s;
3128         for (i = 0;i < SKINFRAME_HASH;i++)
3129         {
3130                 for (s = r_skinframe.hash[i];s;s = s->next)
3131                 {
3132                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3133                         {
3134                                 if (s->merged == s->base)
3135                                         s->merged = NULL;
3136                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3137                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3138                                 R_PurgeTexture(s->merged);s->merged = NULL;
3139                                 R_PurgeTexture(s->base  );s->base   = NULL;
3140                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3141                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3142                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3143                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3144                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3145                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3146                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3147                                 s->loadsequence = 0;
3148                         }
3149                 }
3150         }
3151 }
3152
3153 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3154         skinframe_t *item;
3155         char basename[MAX_QPATH];
3156
3157         Image_StripImageExtension(name, basename, sizeof(basename));
3158
3159         if( last == NULL ) {
3160                 int hashindex;
3161                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3162                 item = r_skinframe.hash[hashindex];
3163         } else {
3164                 item = last->next;
3165         }
3166
3167         // linearly search through the hash bucket
3168         for( ; item ; item = item->next ) {
3169                 if( !strcmp( item->basename, basename ) ) {
3170                         return item;
3171                 }
3172         }
3173         return NULL;
3174 }
3175
3176 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3177 {
3178         skinframe_t *item;
3179         int hashindex;
3180         char basename[MAX_QPATH];
3181
3182         Image_StripImageExtension(name, basename, sizeof(basename));
3183
3184         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3185         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3186                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3187                         break;
3188
3189         if (!item) {
3190                 rtexture_t *dyntexture;
3191                 // check whether its a dynamic texture
3192                 dyntexture = CL_GetDynTexture( basename );
3193                 if (!add && !dyntexture)
3194                         return NULL;
3195                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3196                 memset(item, 0, sizeof(*item));
3197                 strlcpy(item->basename, basename, sizeof(item->basename));
3198                 item->base = dyntexture; // either NULL or dyntexture handle
3199                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3200                 item->comparewidth = comparewidth;
3201                 item->compareheight = compareheight;
3202                 item->comparecrc = comparecrc;
3203                 item->next = r_skinframe.hash[hashindex];
3204                 r_skinframe.hash[hashindex] = item;
3205         }
3206         else if (textureflags & TEXF_FORCE_RELOAD)
3207         {
3208                 rtexture_t *dyntexture;
3209                 // check whether its a dynamic texture
3210                 dyntexture = CL_GetDynTexture( basename );
3211                 if (!add && !dyntexture)
3212                         return NULL;
3213                 if (item->merged == item->base)
3214                         item->merged = NULL;
3215                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3216                 R_PurgeTexture(item->stain );item->stain  = NULL;
3217                 R_PurgeTexture(item->merged);item->merged = NULL;
3218                 R_PurgeTexture(item->base  );item->base   = NULL;
3219                 R_PurgeTexture(item->pants );item->pants  = NULL;
3220                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3221                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3222                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3223                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3224                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3225         R_PurgeTexture(item->reflect);item->reflect = NULL;
3226                 item->loadsequence = 0;
3227         }
3228         else if( item->base == NULL )
3229         {
3230                 rtexture_t *dyntexture;
3231                 // check whether its a dynamic texture
3232                 // 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]
3233                 dyntexture = CL_GetDynTexture( basename );
3234                 item->base = dyntexture; // either NULL or dyntexture handle
3235         }
3236
3237         R_SkinFrame_MarkUsed(item);
3238         return item;
3239 }
3240
3241 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3242         { \
3243                 unsigned long long avgcolor[5], wsum; \
3244                 int pix, comp, w; \
3245                 avgcolor[0] = 0; \
3246                 avgcolor[1] = 0; \
3247                 avgcolor[2] = 0; \
3248                 avgcolor[3] = 0; \
3249                 avgcolor[4] = 0; \
3250                 wsum = 0; \
3251                 for(pix = 0; pix < cnt; ++pix) \
3252                 { \
3253                         w = 0; \
3254                         for(comp = 0; comp < 3; ++comp) \
3255                                 w += getpixel; \
3256                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3257                         { \
3258                                 ++wsum; \
3259                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3260                                 w = getpixel; \
3261                                 for(comp = 0; comp < 3; ++comp) \
3262                                         avgcolor[comp] += getpixel * w; \
3263                                 avgcolor[3] += w; \
3264                         } \
3265                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3266                         avgcolor[4] += getpixel; \
3267                 } \
3268                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3269                         avgcolor[3] = 1; \
3270                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3271                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3272                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3273                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3274         }
3275
3276 extern cvar_t gl_picmip;
3277 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3278 {
3279         int j;
3280         unsigned char *pixels;
3281         unsigned char *bumppixels;
3282         unsigned char *basepixels = NULL;
3283         int basepixels_width = 0;
3284         int basepixels_height = 0;
3285         skinframe_t *skinframe;
3286         rtexture_t *ddsbase = NULL;
3287         qboolean ddshasalpha = false;
3288         float ddsavgcolor[4];
3289         char basename[MAX_QPATH];
3290         int miplevel = R_PicmipForFlags(textureflags);
3291         int savemiplevel = miplevel;
3292         int mymiplevel;
3293
3294         if (cls.state == ca_dedicated)
3295                 return NULL;
3296
3297         // return an existing skinframe if already loaded
3298         // if loading of the first image fails, don't make a new skinframe as it
3299         // would cause all future lookups of this to be missing
3300         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3301         if (skinframe && skinframe->base)
3302                 return skinframe;
3303
3304         Image_StripImageExtension(name, basename, sizeof(basename));
3305
3306         // check for DDS texture file first
3307         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s.dds", basename), textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3308         {
3309                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3310                 if (basepixels == NULL)
3311                         return NULL;
3312         }
3313
3314         // FIXME handle miplevel
3315
3316         if (developer_loading.integer)
3317                 Con_Printf("loading skin \"%s\"\n", name);
3318
3319         // we've got some pixels to store, so really allocate this new texture now
3320         if (!skinframe)
3321                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3322         textureflags &= ~TEXF_FORCE_RELOAD;
3323         skinframe->stain = NULL;
3324         skinframe->merged = NULL;
3325         skinframe->base = NULL;
3326         skinframe->pants = NULL;
3327         skinframe->shirt = NULL;
3328         skinframe->nmap = NULL;
3329         skinframe->gloss = NULL;
3330         skinframe->glow = NULL;
3331         skinframe->fog = NULL;
3332         skinframe->reflect = NULL;
3333         skinframe->hasalpha = false;
3334
3335         if (ddsbase)
3336         {
3337                 skinframe->base = ddsbase;
3338                 skinframe->hasalpha = ddshasalpha;
3339                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3340                 if (r_loadfog && skinframe->hasalpha)
3341                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_mask.dds", skinframe->basename), textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3342                 //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]);
3343         }
3344         else
3345         {
3346                 basepixels_width = image_width;
3347                 basepixels_height = image_height;
3348                 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);
3349                 if (textureflags & TEXF_ALPHA)
3350                 {
3351                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3352                         {
3353                                 if (basepixels[j] < 255)
3354                                 {
3355                                         skinframe->hasalpha = true;
3356                                         break;
3357                                 }
3358                         }
3359                         if (r_loadfog && skinframe->hasalpha)
3360                         {
3361                                 // has transparent pixels
3362                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3363                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3364                                 {
3365                                         pixels[j+0] = 255;
3366                                         pixels[j+1] = 255;
3367                                         pixels[j+2] = 255;
3368                                         pixels[j+3] = basepixels[j+3];
3369                                 }
3370                                 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);
3371                                 Mem_Free(pixels);
3372                         }
3373                 }
3374                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3375 #ifndef USE_GLES2
3376                 //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]);
3377                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3378                         R_SaveTextureDDSFile(skinframe->base, va("dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3379                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3380                         R_SaveTextureDDSFile(skinframe->fog, va("dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3381 #endif
3382         }
3383
3384         if (r_loaddds)
3385         {
3386                 mymiplevel = savemiplevel;
3387                 if (r_loadnormalmap)
3388                         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);
3389                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_glow.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3390                 if (r_loadgloss)
3391                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_gloss.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3392                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_pants.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3393                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_shirt.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3394                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va("dds/%s_reflect.dds", skinframe->basename), textureflags, NULL, NULL, mymiplevel);
3395         }
3396
3397         // _norm is the name used by tenebrae and has been adopted as standard
3398         if (r_loadnormalmap && skinframe->nmap == NULL)
3399         {
3400                 mymiplevel = savemiplevel;
3401                 if ((pixels = loadimagepixelsbgra(va("%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3402                 {
3403                         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);
3404                         Mem_Free(pixels);
3405                         pixels = NULL;
3406                 }
3407                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va("%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3408                 {
3409                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3410                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3411                         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);
3412                         Mem_Free(pixels);
3413                         Mem_Free(bumppixels);
3414                 }
3415                 else if (r_shadow_bumpscale_basetexture.value > 0)
3416                 {
3417                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3418                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3419                         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);
3420                         Mem_Free(pixels);
3421                 }
3422 #ifndef USE_GLES2
3423                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3424                         R_SaveTextureDDSFile(skinframe->nmap, va("dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3425 #endif
3426         }
3427
3428         // _luma is supported only for tenebrae compatibility
3429         // _glow is the preferred name
3430         mymiplevel = savemiplevel;
3431         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))))
3432         {
3433                 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);
3434 #ifndef USE_GLES2
3435                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3436                         R_SaveTextureDDSFile(skinframe->glow, va("dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3437 #endif
3438                 Mem_Free(pixels);pixels = NULL;
3439         }
3440
3441         mymiplevel = savemiplevel;
3442         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va("%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3443         {
3444                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va("%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3445 #ifndef USE_GLES2
3446                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3447                         R_SaveTextureDDSFile(skinframe->gloss, va("dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3448 #endif
3449                 Mem_Free(pixels);
3450                 pixels = NULL;
3451         }
3452
3453         mymiplevel = savemiplevel;
3454         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va("%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3455         {
3456                 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);
3457 #ifndef USE_GLES2
3458                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3459                         R_SaveTextureDDSFile(skinframe->pants, va("dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3460 #endif
3461                 Mem_Free(pixels);
3462                 pixels = NULL;
3463         }
3464
3465         mymiplevel = savemiplevel;
3466         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va("%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3467         {
3468                 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);
3469 #ifndef USE_GLES2
3470                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3471                         R_SaveTextureDDSFile(skinframe->shirt, va("dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3472 #endif
3473                 Mem_Free(pixels);
3474                 pixels = NULL;
3475         }
3476
3477         mymiplevel = savemiplevel;
3478         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va("%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3479         {
3480                 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);
3481 #ifndef USE_GLES2
3482                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3483                         R_SaveTextureDDSFile(skinframe->reflect, va("dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3484 #endif
3485                 Mem_Free(pixels);
3486                 pixels = NULL;
3487         }
3488
3489         if (basepixels)
3490                 Mem_Free(basepixels);
3491
3492         return skinframe;
3493 }
3494
3495 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3496 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3497 {
3498         int i;
3499         unsigned char *temp1, *temp2;
3500         skinframe_t *skinframe;
3501
3502         if (cls.state == ca_dedicated)
3503                 return NULL;
3504
3505         // if already loaded just return it, otherwise make a new skinframe
3506         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3507         if (skinframe && skinframe->base)
3508                 return skinframe;
3509         textureflags &= ~TEXF_FORCE_RELOAD;
3510
3511         skinframe->stain = NULL;
3512         skinframe->merged = NULL;
3513         skinframe->base = NULL;
3514         skinframe->pants = NULL;
3515         skinframe->shirt = NULL;
3516         skinframe->nmap = NULL;
3517         skinframe->gloss = NULL;
3518         skinframe->glow = NULL;
3519         skinframe->fog = NULL;
3520         skinframe->reflect = NULL;
3521         skinframe->hasalpha = false;
3522
3523         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3524         if (!skindata)
3525                 return NULL;
3526
3527         if (developer_loading.integer)
3528                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3529
3530         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3531         {
3532                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3533                 temp2 = temp1 + width * height * 4;
3534                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3535                 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);
3536                 Mem_Free(temp1);
3537         }
3538         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3539         if (textureflags & TEXF_ALPHA)
3540         {
3541                 for (i = 3;i < width * height * 4;i += 4)
3542                 {
3543                         if (skindata[i] < 255)
3544                         {
3545                                 skinframe->hasalpha = true;
3546                                 break;
3547                         }
3548                 }
3549                 if (r_loadfog && skinframe->hasalpha)
3550                 {
3551                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3552                         memcpy(fogpixels, skindata, width * height * 4);
3553                         for (i = 0;i < width * height * 4;i += 4)
3554                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3555                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3556                         Mem_Free(fogpixels);
3557                 }
3558         }
3559
3560         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3561         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3562
3563         return skinframe;
3564 }
3565
3566 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3567 {
3568         int i;
3569         int featuresmask;
3570         skinframe_t *skinframe;
3571
3572         if (cls.state == ca_dedicated)
3573                 return NULL;
3574
3575         // if already loaded just return it, otherwise make a new skinframe
3576         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3577         if (skinframe && skinframe->base)
3578                 return skinframe;
3579         textureflags &= ~TEXF_FORCE_RELOAD;
3580
3581         skinframe->stain = NULL;
3582         skinframe->merged = NULL;
3583         skinframe->base = NULL;
3584         skinframe->pants = NULL;
3585         skinframe->shirt = NULL;
3586         skinframe->nmap = NULL;
3587         skinframe->gloss = NULL;
3588         skinframe->glow = NULL;
3589         skinframe->fog = NULL;
3590         skinframe->reflect = NULL;
3591         skinframe->hasalpha = false;
3592
3593         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3594         if (!skindata)
3595                 return NULL;
3596
3597         if (developer_loading.integer)
3598                 Con_Printf("loading quake skin \"%s\"\n", name);
3599
3600         // 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)
3601         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3602         memcpy(skinframe->qpixels, skindata, width*height);
3603         skinframe->qwidth = width;
3604         skinframe->qheight = height;
3605
3606         featuresmask = 0;
3607         for (i = 0;i < width * height;i++)
3608                 featuresmask |= palette_featureflags[skindata[i]];
3609
3610         skinframe->hasalpha = false;
3611         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3612         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3613         skinframe->qgeneratemerged = true;
3614         skinframe->qgeneratebase = skinframe->qhascolormapping;
3615         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3616
3617         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3618         //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]);
3619
3620         return skinframe;
3621 }
3622
3623 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3624 {
3625         int width;
3626         int height;
3627         unsigned char *skindata;
3628
3629         if (!skinframe->qpixels)
3630                 return;
3631
3632         if (!skinframe->qhascolormapping)
3633                 colormapped = false;
3634
3635         if (colormapped)
3636         {
3637                 if (!skinframe->qgeneratebase)
3638                         return;
3639         }
3640         else
3641         {
3642                 if (!skinframe->qgeneratemerged)
3643                         return;
3644         }
3645
3646         width = skinframe->qwidth;
3647         height = skinframe->qheight;
3648         skindata = skinframe->qpixels;
3649
3650         if (skinframe->qgeneratenmap)
3651         {
3652                 unsigned char *temp1, *temp2;
3653                 skinframe->qgeneratenmap = false;
3654                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3655                 temp2 = temp1 + width * height * 4;
3656                 // use either a custom palette or the quake palette
3657                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3658                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3659                 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);
3660                 Mem_Free(temp1);
3661         }
3662
3663         if (skinframe->qgenerateglow)
3664         {
3665                 skinframe->qgenerateglow = false;
3666                 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
3667         }
3668
3669         if (colormapped)
3670         {
3671                 skinframe->qgeneratebase = false;
3672                 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);
3673                 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);
3674                 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);
3675         }
3676         else
3677         {
3678                 skinframe->qgeneratemerged = false;
3679                 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);
3680         }
3681
3682         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3683         {
3684                 Mem_Free(skinframe->qpixels);
3685                 skinframe->qpixels = NULL;
3686         }
3687 }
3688
3689 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)
3690 {
3691         int i;
3692         skinframe_t *skinframe;
3693
3694         if (cls.state == ca_dedicated)
3695                 return NULL;
3696
3697         // if already loaded just return it, otherwise make a new skinframe
3698         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3699         if (skinframe && skinframe->base)
3700                 return skinframe;
3701         textureflags &= ~TEXF_FORCE_RELOAD;
3702
3703         skinframe->stain = NULL;
3704         skinframe->merged = NULL;
3705         skinframe->base = NULL;
3706         skinframe->pants = NULL;
3707         skinframe->shirt = NULL;
3708         skinframe->nmap = NULL;
3709         skinframe->gloss = NULL;
3710         skinframe->glow = NULL;
3711         skinframe->fog = NULL;
3712         skinframe->reflect = NULL;
3713         skinframe->hasalpha = false;
3714
3715         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3716         if (!skindata)
3717                 return NULL;
3718
3719         if (developer_loading.integer)
3720                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3721
3722         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3723         if (textureflags & TEXF_ALPHA)
3724         {
3725                 for (i = 0;i < width * height;i++)
3726                 {
3727                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3728                         {
3729                                 skinframe->hasalpha = true;
3730                                 break;
3731                         }
3732                 }
3733                 if (r_loadfog && skinframe->hasalpha)
3734                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va("%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3735         }
3736
3737         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3738         //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]);
3739
3740         return skinframe;
3741 }
3742
3743 skinframe_t *R_SkinFrame_LoadMissing(void)
3744 {
3745         skinframe_t *skinframe;
3746
3747         if (cls.state == ca_dedicated)
3748                 return NULL;
3749
3750         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3751         skinframe->stain = NULL;
3752         skinframe->merged = NULL;
3753         skinframe->base = NULL;
3754         skinframe->pants = NULL;
3755         skinframe->shirt = NULL;
3756         skinframe->nmap = NULL;
3757         skinframe->gloss = NULL;
3758         skinframe->glow = NULL;
3759         skinframe->fog = NULL;
3760         skinframe->reflect = NULL;
3761         skinframe->hasalpha = false;
3762
3763         skinframe->avgcolor[0] = rand() / RAND_MAX;
3764         skinframe->avgcolor[1] = rand() / RAND_MAX;
3765         skinframe->avgcolor[2] = rand() / RAND_MAX;
3766         skinframe->avgcolor[3] = 1;
3767
3768         return skinframe;
3769 }
3770
3771 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3772 typedef struct suffixinfo_s
3773 {
3774         const char *suffix;
3775         qboolean flipx, flipy, flipdiagonal;
3776 }
3777 suffixinfo_t;
3778 static suffixinfo_t suffix[3][6] =
3779 {
3780         {
3781                 {"px",   false, false, false},
3782                 {"nx",   false, false, false},
3783                 {"py",   false, false, false},
3784                 {"ny",   false, false, false},
3785                 {"pz",   false, false, false},
3786                 {"nz",   false, false, false}
3787         },
3788         {
3789                 {"posx", false, false, false},
3790                 {"negx", false, false, false},
3791                 {"posy", false, false, false},
3792                 {"negy", false, false, false},
3793                 {"posz", false, false, false},
3794                 {"negz", false, false, false}
3795         },
3796         {
3797                 {"rt",    true, false,  true},
3798                 {"lf",   false,  true,  true},
3799                 {"ft",    true,  true, false},
3800                 {"bk",   false, false, false},
3801                 {"up",    true, false,  true},
3802                 {"dn",    true, false,  true}
3803         }
3804 };
3805
3806 static int componentorder[4] = {0, 1, 2, 3};
3807
3808 rtexture_t *R_LoadCubemap(const char *basename)
3809 {
3810         int i, j, cubemapsize;
3811         unsigned char *cubemappixels, *image_buffer;
3812         rtexture_t *cubemaptexture;
3813         char name[256];
3814         // must start 0 so the first loadimagepixels has no requested width/height
3815         cubemapsize = 0;
3816         cubemappixels = NULL;
3817         cubemaptexture = NULL;
3818         // keep trying different suffix groups (posx, px, rt) until one loads
3819         for (j = 0;j < 3 && !cubemappixels;j++)
3820         {
3821                 // load the 6 images in the suffix group
3822                 for (i = 0;i < 6;i++)
3823                 {
3824                         // generate an image name based on the base and and suffix
3825                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3826                         // load it
3827                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3828                         {
3829                                 // an image loaded, make sure width and height are equal
3830                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3831                                 {
3832                                         // if this is the first image to load successfully, allocate the cubemap memory
3833                                         if (!cubemappixels && image_width >= 1)
3834                                         {
3835                                                 cubemapsize = image_width;
3836                                                 // note this clears to black, so unavailable sides are black
3837                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3838                                         }
3839                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3840                                         if (cubemappixels)
3841                                                 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);
3842                                 }
3843                                 else
3844                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3845                                 // free the image
3846                                 Mem_Free(image_buffer);
3847                         }
3848                 }
3849         }
3850         // if a cubemap loaded, upload it
3851         if (cubemappixels)
3852         {
3853                 if (developer_loading.integer)
3854                         Con_Printf("loading cubemap \"%s\"\n", basename);
3855
3856                 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);
3857                 Mem_Free(cubemappixels);
3858         }
3859         else
3860         {
3861                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3862                 if (developer_loading.integer)
3863                 {
3864                         Con_Printf("(tried tried images ");
3865                         for (j = 0;j < 3;j++)
3866                                 for (i = 0;i < 6;i++)
3867                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3868                         Con_Print(" and was unable to find any of them).\n");
3869                 }
3870         }
3871         return cubemaptexture;
3872 }
3873
3874 rtexture_t *R_GetCubemap(const char *basename)
3875 {
3876         int i;
3877         for (i = 0;i < r_texture_numcubemaps;i++)
3878                 if (r_texture_cubemaps[i] != NULL)
3879                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3880                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3881         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3882                 return r_texture_whitecube;
3883         r_texture_numcubemaps++;
3884         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3885         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3886         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3887         return r_texture_cubemaps[i]->texture;
3888 }
3889
3890 void R_FreeCubemap(const char *basename)
3891 {
3892         int i;
3893
3894         for (i = 0;i < r_texture_numcubemaps;i++)
3895         {
3896                 if (r_texture_cubemaps[i] != NULL)
3897                 {
3898                         if (r_texture_cubemaps[i]->texture)
3899                         {
3900                                 if (developer_loading.integer)
3901                                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3902                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3903                                 Mem_Free(r_texture_cubemaps[i]);
3904                                 r_texture_cubemaps[i] = NULL;
3905                         }
3906                 }
3907         }
3908 }
3909
3910 void R_FreeCubemaps(void)
3911 {
3912         int i;
3913         for (i = 0;i < r_texture_numcubemaps;i++)
3914         {
3915                 if (developer_loading.integer)
3916                         Con_DPrintf("unloading cubemap \"%s\"\n", r_texture_cubemaps[i]->basename);
3917                 if (r_texture_cubemaps[i] != NULL)
3918                 {
3919                         if (r_texture_cubemaps[i]->texture)
3920                                 R_FreeTexture(r_texture_cubemaps[i]->texture);
3921                         Mem_Free(r_texture_cubemaps[i]);
3922                 }
3923         }
3924         r_texture_numcubemaps = 0;
3925 }
3926
3927 void R_Main_FreeViewCache(void)
3928 {
3929         if (r_refdef.viewcache.entityvisible)
3930                 Mem_Free(r_refdef.viewcache.entityvisible);
3931         if (r_refdef.viewcache.world_pvsbits)
3932                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3933         if (r_refdef.viewcache.world_leafvisible)
3934                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3935         if (r_refdef.viewcache.world_surfacevisible)
3936                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3937         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3938 }
3939
3940 void R_Main_ResizeViewCache(void)
3941 {
3942         int numentities = r_refdef.scene.numentities;
3943         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3944         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3945         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3946         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3947         if (r_refdef.viewcache.maxentities < numentities)
3948         {
3949                 r_refdef.viewcache.maxentities = numentities;
3950                 if (r_refdef.viewcache.entityvisible)
3951                         Mem_Free(r_refdef.viewcache.entityvisible);
3952                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3953         }
3954         if (r_refdef.viewcache.world_numclusters != numclusters)
3955         {
3956                 r_refdef.viewcache.world_numclusters = numclusters;
3957                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3958                 if (r_refdef.viewcache.world_pvsbits)
3959                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3960                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3961         }
3962         if (r_refdef.viewcache.world_numleafs != numleafs)
3963         {
3964                 r_refdef.viewcache.world_numleafs = numleafs;
3965                 if (r_refdef.viewcache.world_leafvisible)
3966                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3967                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3968         }
3969         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3970         {
3971                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3972                 if (r_refdef.viewcache.world_surfacevisible)
3973                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3974                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3975         }
3976 }
3977
3978 extern rtexture_t *loadingscreentexture;
3979 void gl_main_start(void)
3980 {
3981         loadingscreentexture = NULL;
3982         r_texture_blanknormalmap = NULL;
3983         r_texture_white = NULL;
3984         r_texture_grey128 = NULL;
3985         r_texture_black = NULL;
3986         r_texture_whitecube = NULL;
3987         r_texture_normalizationcube = NULL;
3988         r_texture_fogattenuation = NULL;
3989         r_texture_fogheighttexture = NULL;
3990         r_texture_gammaramps = NULL;
3991         r_texture_numcubemaps = 0;
3992
3993         r_loaddds = r_texture_dds_load.integer != 0;
3994         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3995
3996         switch(vid.renderpath)
3997         {
3998         case RENDERPATH_GL20:
3999         case RENDERPATH_D3D9:
4000         case RENDERPATH_D3D10:
4001         case RENDERPATH_D3D11:
4002         case RENDERPATH_SOFT:
4003         case RENDERPATH_GLES2:
4004                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4005                 Cvar_SetValueQuick(&gl_combine, 1);
4006                 Cvar_SetValueQuick(&r_glsl, 1);
4007                 r_loadnormalmap = true;
4008                 r_loadgloss = true;
4009                 r_loadfog = false;
4010                 break;
4011         case RENDERPATH_GL13:
4012         case RENDERPATH_GLES1:
4013                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4014                 Cvar_SetValueQuick(&gl_combine, 1);
4015                 Cvar_SetValueQuick(&r_glsl, 0);
4016                 r_loadnormalmap = false;
4017                 r_loadgloss = false;
4018                 r_loadfog = true;
4019                 break;
4020         case RENDERPATH_GL11:
4021                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4022                 Cvar_SetValueQuick(&gl_combine, 0);
4023                 Cvar_SetValueQuick(&r_glsl, 0);
4024                 r_loadnormalmap = false;
4025                 r_loadgloss = false;
4026                 r_loadfog = true;
4027                 break;
4028         }
4029
4030         R_AnimCache_Free();
4031         R_FrameData_Reset();
4032
4033         r_numqueries = 0;
4034         r_maxqueries = 0;
4035         memset(r_queries, 0, sizeof(r_queries));
4036
4037         r_qwskincache = NULL;
4038         r_qwskincache_size = 0;
4039
4040         // due to caching of texture_t references, the collision cache must be reset
4041         Collision_Cache_Reset(true);
4042
4043         // set up r_skinframe loading system for textures
4044         memset(&r_skinframe, 0, sizeof(r_skinframe));
4045         r_skinframe.loadsequence = 1;
4046         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4047
4048         r_main_texturepool = R_AllocTexturePool();
4049         R_BuildBlankTextures();
4050         R_BuildNoTexture();
4051         if (vid.support.arb_texture_cube_map)
4052         {
4053                 R_BuildWhiteCube();
4054                 R_BuildNormalizationCube();
4055         }
4056         r_texture_fogattenuation = NULL;
4057         r_texture_fogheighttexture = NULL;
4058         r_texture_gammaramps = NULL;
4059         //r_texture_fogintensity = NULL;
4060         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4061         memset(&r_waterstate, 0, sizeof(r_waterstate));
4062         r_glsl_permutation = NULL;
4063         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4064         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4065         glslshaderstring = NULL;
4066 #ifdef SUPPORTD3D
4067         r_hlsl_permutation = NULL;
4068         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4069         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4070 #endif
4071         hlslshaderstring = NULL;
4072         memset(&r_svbsp, 0, sizeof (r_svbsp));
4073
4074         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4075         r_texture_numcubemaps = 0;
4076
4077         r_refdef.fogmasktable_density = 0;
4078 }
4079
4080 void gl_main_shutdown(void)
4081 {
4082         R_AnimCache_Free();
4083         R_FrameData_Reset();
4084
4085         R_Main_FreeViewCache();
4086
4087         switch(vid.renderpath)
4088         {
4089         case RENDERPATH_GL11:
4090         case RENDERPATH_GL13:
4091         case RENDERPATH_GL20:
4092         case RENDERPATH_GLES1:
4093         case RENDERPATH_GLES2:
4094 #ifdef GL_SAMPLES_PASSED_ARB
4095                 if (r_maxqueries)
4096                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4097 #endif
4098                 break;
4099         case RENDERPATH_D3D9:
4100                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4101                 break;
4102         case RENDERPATH_D3D10:
4103                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4104                 break;
4105         case RENDERPATH_D3D11:
4106                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4107                 break;
4108         case RENDERPATH_SOFT:
4109                 break;
4110         }
4111
4112         r_numqueries = 0;
4113         r_maxqueries = 0;
4114         memset(r_queries, 0, sizeof(r_queries));
4115
4116         r_qwskincache = NULL;
4117         r_qwskincache_size = 0;
4118
4119         // clear out the r_skinframe state
4120         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4121         memset(&r_skinframe, 0, sizeof(r_skinframe));
4122
4123         if (r_svbsp.nodes)
4124                 Mem_Free(r_svbsp.nodes);
4125         memset(&r_svbsp, 0, sizeof (r_svbsp));
4126         R_FreeTexturePool(&r_main_texturepool);
4127         loadingscreentexture = NULL;
4128         r_texture_blanknormalmap = NULL;
4129         r_texture_white = NULL;
4130         r_texture_grey128 = NULL;
4131         r_texture_black = NULL;
4132         r_texture_whitecube = NULL;
4133         r_texture_normalizationcube = NULL;
4134         r_texture_fogattenuation = NULL;
4135         r_texture_fogheighttexture = NULL;
4136         r_texture_gammaramps = NULL;
4137         r_texture_numcubemaps = 0;
4138         //r_texture_fogintensity = NULL;
4139         memset(&r_bloomstate, 0, sizeof(r_bloomstate));
4140         memset(&r_waterstate, 0, sizeof(r_waterstate));
4141         R_GLSL_Restart_f();
4142
4143         r_glsl_permutation = NULL;
4144         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4145         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4146         glslshaderstring = NULL;
4147 #ifdef SUPPORTD3D
4148         r_hlsl_permutation = NULL;
4149         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4150         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4151 #endif
4152         hlslshaderstring = NULL;
4153 }
4154
4155 extern void CL_ParseEntityLump(char *entitystring);
4156 void gl_main_newmap(void)
4157 {
4158         // FIXME: move this code to client
4159         char *entities, entname[MAX_QPATH];
4160         if (r_qwskincache)
4161                 Mem_Free(r_qwskincache);
4162         r_qwskincache = NULL;
4163         r_qwskincache_size = 0;
4164         if (cl.worldmodel)
4165         {
4166                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4167                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4168                 {
4169                         CL_ParseEntityLump(entities);
4170                         Mem_Free(entities);
4171                         return;
4172                 }
4173                 if (cl.worldmodel->brush.entities)
4174                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4175         }
4176         R_Main_FreeViewCache();
4177
4178         R_FrameData_Reset();
4179 }
4180
4181 void GL_Main_Init(void)
4182 {
4183         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4184
4185         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4186         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4187         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4188         if (gamemode == GAME_NEHAHRA)
4189         {
4190                 Cvar_RegisterVariable (&gl_fogenable);
4191                 Cvar_RegisterVariable (&gl_fogdensity);
4192                 Cvar_RegisterVariable (&gl_fogred);
4193                 Cvar_RegisterVariable (&gl_foggreen);
4194                 Cvar_RegisterVariable (&gl_fogblue);
4195                 Cvar_RegisterVariable (&gl_fogstart);
4196                 Cvar_RegisterVariable (&gl_fogend);
4197                 Cvar_RegisterVariable (&gl_skyclip);
4198         }
4199         Cvar_RegisterVariable(&r_motionblur);
4200         Cvar_RegisterVariable(&r_damageblur);
4201         Cvar_RegisterVariable(&r_motionblur_averaging);
4202         Cvar_RegisterVariable(&r_motionblur_randomize);
4203         Cvar_RegisterVariable(&r_motionblur_minblur);
4204         Cvar_RegisterVariable(&r_motionblur_maxblur);
4205         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4206         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4207         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4208         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4209         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4210         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4211         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4212         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4213         Cvar_RegisterVariable(&r_equalize_entities_by);
4214         Cvar_RegisterVariable(&r_equalize_entities_to);
4215         Cvar_RegisterVariable(&r_depthfirst);
4216         Cvar_RegisterVariable(&r_useinfinitefarclip);
4217         Cvar_RegisterVariable(&r_farclip_base);
4218         Cvar_RegisterVariable(&r_farclip_world);
4219         Cvar_RegisterVariable(&r_nearclip);
4220         Cvar_RegisterVariable(&r_deformvertexes);
4221         Cvar_RegisterVariable(&r_transparent);
4222         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4223         Cvar_RegisterVariable(&r_showoverdraw);
4224         Cvar_RegisterVariable(&r_showbboxes);
4225         Cvar_RegisterVariable(&r_showsurfaces);
4226         Cvar_RegisterVariable(&r_showtris);
4227         Cvar_RegisterVariable(&r_shownormals);
4228         Cvar_RegisterVariable(&r_showlighting);
4229         Cvar_RegisterVariable(&r_showshadowvolumes);
4230         Cvar_RegisterVariable(&r_showcollisionbrushes);
4231         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4232         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4233         Cvar_RegisterVariable(&r_showdisabledepthtest);
4234         Cvar_RegisterVariable(&r_drawportals);
4235         Cvar_RegisterVariable(&r_drawentities);
4236         Cvar_RegisterVariable(&r_draw2d);
4237         Cvar_RegisterVariable(&r_drawworld);
4238         Cvar_RegisterVariable(&r_cullentities_trace);
4239         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4240         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4241         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4242         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4243         Cvar_RegisterVariable(&r_sortentities);
4244         Cvar_RegisterVariable(&r_drawviewmodel);
4245         Cvar_RegisterVariable(&r_drawexteriormodel);
4246         Cvar_RegisterVariable(&r_speeds);
4247         Cvar_RegisterVariable(&r_fullbrights);
4248         Cvar_RegisterVariable(&r_wateralpha);
4249         Cvar_RegisterVariable(&r_dynamic);
4250         Cvar_RegisterVariable(&r_fakelight);
4251         Cvar_RegisterVariable(&r_fakelight_intensity);
4252         Cvar_RegisterVariable(&r_fullbright);
4253         Cvar_RegisterVariable(&r_shadows);
4254         Cvar_RegisterVariable(&r_shadows_darken);
4255         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4256         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4257         Cvar_RegisterVariable(&r_shadows_throwdistance);
4258         Cvar_RegisterVariable(&r_shadows_throwdirection);
4259         Cvar_RegisterVariable(&r_shadows_focus);
4260         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4261         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4262         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4263         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4264         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4265         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4266         Cvar_RegisterVariable(&r_fog_exp2);
4267         Cvar_RegisterVariable(&r_fog_clear);
4268         Cvar_RegisterVariable(&r_drawfog);
4269         Cvar_RegisterVariable(&r_transparentdepthmasking);
4270         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4271         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4272         Cvar_RegisterVariable(&r_texture_dds_load);
4273         Cvar_RegisterVariable(&r_texture_dds_save);
4274         Cvar_RegisterVariable(&r_textureunits);
4275         Cvar_RegisterVariable(&gl_combine);
4276         Cvar_RegisterVariable(&r_viewfbo);
4277         Cvar_RegisterVariable(&r_viewscale);
4278         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4279         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4280         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4281         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4282         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4283         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4284         Cvar_RegisterVariable(&r_glsl);
4285         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4286         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4287         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4288         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4289         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4290         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4291         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4292         Cvar_RegisterVariable(&r_glsl_postprocess);
4293         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4294         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4295         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4296         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4297         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4298         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4299         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4300         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4301
4302         Cvar_RegisterVariable(&r_water);
4303         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4304         Cvar_RegisterVariable(&r_water_clippingplanebias);
4305         Cvar_RegisterVariable(&r_water_refractdistort);
4306         Cvar_RegisterVariable(&r_water_reflectdistort);
4307         Cvar_RegisterVariable(&r_water_scissormode);
4308         Cvar_RegisterVariable(&r_water_lowquality);
4309
4310         Cvar_RegisterVariable(&r_lerpsprites);
4311         Cvar_RegisterVariable(&r_lerpmodels);
4312         Cvar_RegisterVariable(&r_lerplightstyles);
4313         Cvar_RegisterVariable(&r_waterscroll);
4314         Cvar_RegisterVariable(&r_bloom);
4315         Cvar_RegisterVariable(&r_bloom_colorscale);
4316         Cvar_RegisterVariable(&r_bloom_brighten);
4317         Cvar_RegisterVariable(&r_bloom_blur);
4318         Cvar_RegisterVariable(&r_bloom_resolution);
4319         Cvar_RegisterVariable(&r_bloom_colorexponent);
4320         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4321         Cvar_RegisterVariable(&r_hdr);
4322         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4323         Cvar_RegisterVariable(&r_hdr_glowintensity);
4324         Cvar_RegisterVariable(&r_hdr_range);
4325         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4326         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4327         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4328         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4329         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4330         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4331         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4332         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4333         Cvar_RegisterVariable(&developer_texturelogging);
4334         Cvar_RegisterVariable(&gl_lightmaps);
4335         Cvar_RegisterVariable(&r_test);
4336         Cvar_RegisterVariable(&r_glsl_saturation);
4337         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4338         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4339         Cvar_RegisterVariable(&r_framedatasize);
4340         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4341                 Cvar_SetValue("r_fullbrights", 0);
4342         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4343 }
4344
4345 extern void R_Textures_Init(void);
4346 extern void GL_Draw_Init(void);
4347 extern void GL_Main_Init(void);
4348 extern void R_Shadow_Init(void);
4349 extern void R_Sky_Init(void);
4350 extern void GL_Surf_Init(void);
4351 extern void R_Particles_Init(void);
4352 extern void R_Explosion_Init(void);
4353 extern void gl_backend_init(void);
4354 extern void Sbar_Init(void);
4355 extern void R_LightningBeams_Init(void);
4356 extern void Mod_RenderInit(void);
4357 extern void Font_Init(void);
4358
4359 void Render_Init(void)
4360 {
4361         gl_backend_init();
4362         R_Textures_Init();
4363         GL_Main_Init();
4364         Font_Init();
4365         GL_Draw_Init();
4366         R_Shadow_Init();
4367         R_Sky_Init();
4368         GL_Surf_Init();
4369         Sbar_Init();
4370         R_Particles_Init();
4371         R_Explosion_Init();
4372         R_LightningBeams_Init();
4373         Mod_RenderInit();
4374 }
4375
4376 /*
4377 ===============
4378 GL_Init
4379 ===============
4380 */
4381 #ifndef USE_GLES2
4382 extern char *ENGINE_EXTENSIONS;
4383 void GL_Init (void)
4384 {
4385         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4386         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4387         gl_version = (const char *)qglGetString(GL_VERSION);
4388         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4389
4390         if (!gl_extensions)
4391                 gl_extensions = "";
4392         if (!gl_platformextensions)
4393                 gl_platformextensions = "";
4394
4395         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4396         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4397         Con_Printf("GL_VERSION: %s\n", gl_version);
4398         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4399         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4400
4401         VID_CheckExtensions();
4402
4403         // LordHavoc: report supported extensions
4404         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4405
4406         // clear to black (loading plaque will be seen over this)
4407         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4408 }
4409 #endif
4410
4411 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4412 {
4413         int i;
4414         mplane_t *p;
4415         if (r_trippy.integer)
4416                 return false;
4417         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4418         {
4419                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4420                 if (i == 4)
4421                         continue;
4422                 p = r_refdef.view.frustum + i;
4423                 switch(p->signbits)
4424                 {
4425                 default:
4426                 case 0:
4427                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4428                                 return true;
4429                         break;
4430                 case 1:
4431                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4432                                 return true;
4433                         break;
4434                 case 2:
4435                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4436                                 return true;
4437                         break;
4438                 case 3:
4439                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4440                                 return true;
4441                         break;
4442                 case 4:
4443                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4444                                 return true;
4445                         break;
4446                 case 5:
4447                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4448                                 return true;
4449                         break;
4450                 case 6:
4451                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4452                                 return true;
4453                         break;
4454                 case 7:
4455                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4456                                 return true;
4457                         break;
4458                 }
4459         }
4460         return false;
4461 }
4462
4463 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4464 {
4465         int i;
4466         const mplane_t *p;
4467         if (r_trippy.integer)
4468                 return false;
4469         for (i = 0;i < numplanes;i++)
4470         {
4471                 p = planes + i;
4472                 switch(p->signbits)
4473                 {
4474                 default:
4475                 case 0:
4476                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4477                                 return true;
4478                         break;
4479                 case 1:
4480                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4481                                 return true;
4482                         break;
4483                 case 2:
4484                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4485                                 return true;
4486                         break;
4487                 case 3:
4488                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4489                                 return true;
4490                         break;
4491                 case 4:
4492                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4493                                 return true;
4494                         break;
4495                 case 5:
4496                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4497                                 return true;
4498                         break;
4499                 case 6:
4500                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4501                                 return true;
4502                         break;
4503                 case 7:
4504                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4505                                 return true;
4506                         break;
4507                 }
4508         }
4509         return false;
4510 }
4511
4512 //==================================================================================
4513
4514 // LordHavoc: this stores temporary data used within the same frame
4515
4516 typedef struct r_framedata_mem_s
4517 {
4518         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4519         size_t size; // how much usable space
4520         size_t current; // how much space in use
4521         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4522         size_t wantedsize; // how much space was allocated
4523         unsigned char *data; // start of real data (16byte aligned)
4524 }
4525 r_framedata_mem_t;
4526
4527 static r_framedata_mem_t *r_framedata_mem;
4528
4529 void R_FrameData_Reset(void)
4530 {
4531         while (r_framedata_mem)
4532         {
4533                 r_framedata_mem_t *next = r_framedata_mem->purge;
4534                 Mem_Free(r_framedata_mem);
4535                 r_framedata_mem = next;
4536         }
4537 }
4538
4539 void R_FrameData_Resize(void)
4540 {
4541         size_t wantedsize;
4542         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4543         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4544         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4545         {
4546                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4547                 newmem->wantedsize = wantedsize;
4548                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4549                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4550                 newmem->current = 0;
4551                 newmem->mark = 0;
4552                 newmem->purge = r_framedata_mem;
4553                 r_framedata_mem = newmem;
4554         }
4555 }
4556
4557 void R_FrameData_NewFrame(void)
4558 {
4559         R_FrameData_Resize();
4560         if (!r_framedata_mem)
4561                 return;
4562         // if we ran out of space on the last frame, free the old memory now
4563         while (r_framedata_mem->purge)
4564         {
4565                 // repeatedly remove the second item in the list, leaving only head
4566                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4567                 Mem_Free(r_framedata_mem->purge);
4568                 r_framedata_mem->purge = next;
4569         }
4570         // reset the current mem pointer
4571         r_framedata_mem->current = 0;
4572         r_framedata_mem->mark = 0;
4573 }
4574
4575 void *R_FrameData_Alloc(size_t size)
4576 {
4577         void *data;
4578
4579         // align to 16 byte boundary - the data pointer is already aligned, so we
4580         // only need to ensure the size of every allocation is also aligned
4581         size = (size + 15) & ~15;
4582
4583         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4584         {
4585                 // emergency - we ran out of space, allocate more memory
4586                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4587                 R_FrameData_Resize();
4588         }
4589
4590         data = r_framedata_mem->data + r_framedata_mem->current;
4591         r_framedata_mem->current += size;
4592
4593         // count the usage for stats
4594         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4595         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4596
4597         return (void *)data;
4598 }
4599
4600 void *R_FrameData_Store(size_t size, void *data)
4601 {
4602         void *d = R_FrameData_Alloc(size);
4603         if (d && data)
4604                 memcpy(d, data, size);
4605         return d;
4606 }
4607
4608 void R_FrameData_SetMark(void)
4609 {
4610         if (!r_framedata_mem)
4611                 return;
4612         r_framedata_mem->mark = r_framedata_mem->current;
4613 }
4614
4615 void R_FrameData_ReturnToMark(void)
4616 {
4617         if (!r_framedata_mem)
4618                 return;
4619         r_framedata_mem->current = r_framedata_mem->mark;
4620 }
4621
4622 //==================================================================================
4623
4624 // LordHavoc: animcache originally written by Echon, rewritten since then
4625
4626 /**
4627  * Animation cache prevents re-generating mesh data for an animated model
4628  * multiple times in one frame for lighting, shadowing, reflections, etc.
4629  */
4630
4631 void R_AnimCache_Free(void)
4632 {
4633 }
4634
4635 void R_AnimCache_ClearCache(void)
4636 {
4637         int i;
4638         entity_render_t *ent;
4639
4640         for (i = 0;i < r_refdef.scene.numentities;i++)
4641         {
4642                 ent = r_refdef.scene.entities[i];
4643                 ent->animcache_vertex3f = NULL;
4644                 ent->animcache_normal3f = NULL;
4645                 ent->animcache_svector3f = NULL;
4646                 ent->animcache_tvector3f = NULL;
4647                 ent->animcache_vertexmesh = NULL;
4648                 ent->animcache_vertex3fbuffer = NULL;
4649                 ent->animcache_vertexmeshbuffer = NULL;
4650         }
4651 }
4652
4653 void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4654 {
4655         int i;
4656
4657         // check if we need the meshbuffers
4658         if (!vid.useinterleavedarrays)
4659                 return;
4660
4661         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4662                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4663         // TODO: upload vertex3f buffer?
4664         if (ent->animcache_vertexmesh)
4665         {
4666                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4667                 for (i = 0;i < numvertices;i++)
4668                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4669                 if (ent->animcache_svector3f)
4670                         for (i = 0;i < numvertices;i++)
4671                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4672                 if (ent->animcache_tvector3f)
4673                         for (i = 0;i < numvertices;i++)
4674                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4675                 if (ent->animcache_normal3f)
4676                         for (i = 0;i < numvertices;i++)
4677                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4678                 // TODO: upload vertexmeshbuffer?
4679         }
4680 }
4681
4682 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4683 {
4684         dp_model_t *model = ent->model;
4685         int numvertices;
4686         // see if it's already cached this frame
4687         if (ent->animcache_vertex3f)
4688         {
4689                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4690                 if (wantnormals || wanttangents)
4691                 {
4692                         if (ent->animcache_normal3f)
4693                                 wantnormals = false;
4694                         if (ent->animcache_svector3f)
4695                                 wanttangents = false;
4696                         if (wantnormals || wanttangents)
4697                         {
4698                                 numvertices = model->surfmesh.num_vertices;
4699                                 if (wantnormals)
4700                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4701                                 if (wanttangents)
4702                                 {
4703                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4704                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4705                                 }
4706                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4707                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4708                         }
4709                 }
4710         }
4711         else
4712         {
4713                 // see if this ent is worth caching
4714                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4715                         return false;
4716                 // get some memory for this entity and generate mesh data
4717                 numvertices = model->surfmesh.num_vertices;
4718                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4719                 if (wantnormals)
4720                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4721                 if (wanttangents)
4722                 {
4723                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4724                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4725                 }
4726                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4727                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4728         }
4729         return true;
4730 }
4731
4732 void R_AnimCache_CacheVisibleEntities(void)
4733 {
4734         int i;
4735         qboolean wantnormals = true;
4736         qboolean wanttangents = !r_showsurfaces.integer;
4737
4738         switch(vid.renderpath)
4739         {
4740         case RENDERPATH_GL20:
4741         case RENDERPATH_D3D9:
4742         case RENDERPATH_D3D10:
4743         case RENDERPATH_D3D11:
4744         case RENDERPATH_GLES2:
4745                 break;
4746         case RENDERPATH_GL11:
4747         case RENDERPATH_GL13:
4748         case RENDERPATH_GLES1:
4749                 wanttangents = false;
4750                 break;
4751         case RENDERPATH_SOFT:
4752                 break;
4753         }
4754
4755         if (r_shownormals.integer)
4756                 wanttangents = wantnormals = true;
4757
4758         // TODO: thread this
4759         // NOTE: R_PrepareRTLights() also caches entities
4760
4761         for (i = 0;i < r_refdef.scene.numentities;i++)
4762                 if (r_refdef.viewcache.entityvisible[i])
4763                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4764 }
4765
4766 //==================================================================================
4767
4768 extern cvar_t r_overheadsprites_pushback;
4769
4770 static void R_View_UpdateEntityLighting (void)
4771 {
4772         int i;
4773         entity_render_t *ent;
4774         vec3_t tempdiffusenormal, avg;
4775         vec_t f, fa, fd, fdd;
4776         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4777
4778         for (i = 0;i < r_refdef.scene.numentities;i++)
4779         {
4780                 ent = r_refdef.scene.entities[i];
4781
4782                 // skip unseen models
4783                 if (!r_refdef.viewcache.entityvisible[i] && skipunseen)
4784                         continue;
4785
4786                 // skip bsp models
4787                 if (ent->model && ent->model->brush.num_leafs)
4788                 {
4789                         // TODO: use modellight for r_ambient settings on world?
4790                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4791                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4792                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4793                         continue;
4794                 }
4795
4796                 // fetch the lighting from the worldmodel data
4797                 VectorClear(ent->modellight_ambient);
4798                 VectorClear(ent->modellight_diffuse);
4799                 VectorClear(tempdiffusenormal);
4800                 if (ent->flags & RENDER_LIGHT)
4801                 {
4802                         vec3_t org;
4803                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4804
4805                         // complete lightning for lit sprites
4806                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4807                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4808                         {
4809                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4810                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4811                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4812                         }
4813                         else
4814                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4815
4816                         if(ent->flags & RENDER_EQUALIZE)
4817                         {
4818                                 // first fix up ambient lighting...
4819                                 if(r_equalize_entities_minambient.value > 0)
4820                                 {
4821                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4822                                         if(fd > 0)
4823                                         {
4824                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4825                                                 if(fa < r_equalize_entities_minambient.value * fd)
4826                                                 {
4827                                                         // solve:
4828                                                         //   fa'/fd' = minambient
4829                                                         //   fa'+0.25*fd' = fa+0.25*fd
4830                                                         //   ...
4831                                                         //   fa' = fd' * minambient
4832                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4833                                                         //   ...
4834                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4835                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4836                                                         //   ...
4837                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4838                                                         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
4839                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4840                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4841                                                 }
4842                                         }
4843                                 }
4844
4845                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4846                                 {
4847                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4848                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4849                                         f = fa + 0.25 * fd;
4850                                         if(f > 0)
4851                                         {
4852                                                 // adjust brightness and saturation to target
4853                                                 avg[0] = avg[1] = avg[2] = fa / f;
4854                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4855                                                 avg[0] = avg[1] = avg[2] = fd / f;
4856                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4857                                         }
4858                                 }
4859                         }
4860                 }
4861                 else // highly rare
4862                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4863
4864                 // move the light direction into modelspace coordinates for lighting code
4865                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4866                 if(VectorLength2(ent->modellight_lightdir) == 0)
4867                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4868                 VectorNormalize(ent->modellight_lightdir);
4869         }
4870 }
4871
4872 #define MAX_LINEOFSIGHTTRACES 64
4873
4874 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4875 {
4876         int i;
4877         vec3_t boxmins, boxmaxs;
4878         vec3_t start;
4879         vec3_t end;
4880         dp_model_t *model = r_refdef.scene.worldmodel;
4881
4882         if (!model || !model->brush.TraceLineOfSight)
4883                 return true;
4884
4885         // expand the box a little
4886         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4887         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4888         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4889         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4890         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4891         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4892
4893         // return true if eye is inside enlarged box
4894         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4895                 return true;
4896
4897         // try center
4898         VectorCopy(eye, start);
4899         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4900         if (model->brush.TraceLineOfSight(model, start, end))
4901                 return true;
4902
4903         // try various random positions
4904         for (i = 0;i < numsamples;i++)
4905         {
4906                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4907                 if (model->brush.TraceLineOfSight(model, start, end))
4908                         return true;
4909         }
4910
4911         return false;
4912 }
4913
4914
4915 static void R_View_UpdateEntityVisible (void)
4916 {
4917         int i;
4918         int renderimask;
4919         int samples;
4920         entity_render_t *ent;
4921
4922         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4923                 : r_waterstate.renderingrefraction                       ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4924                 : (chase_active.integer || r_waterstate.renderingscene)  ? RENDER_VIEWMODEL
4925                 :                                                          RENDER_EXTERIORMODEL;
4926         if (!r_drawviewmodel.integer)
4927                 renderimask |= RENDER_VIEWMODEL;
4928         if (!r_drawexteriormodel.integer)
4929                 renderimask |= RENDER_EXTERIORMODEL;
4930         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4931         {
4932                 // worldmodel can check visibility
4933                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4934                 for (i = 0;i < r_refdef.scene.numentities;i++)
4935                 {
4936                         ent = r_refdef.scene.entities[i];
4937                         if (!(ent->flags & renderimask))
4938                         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)))
4939                         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))
4940                                 r_refdef.viewcache.entityvisible[i] = true;
4941                 }
4942         }
4943         else
4944         {
4945                 // no worldmodel or it can't check visibility
4946                 for (i = 0;i < r_refdef.scene.numentities;i++)
4947                 {
4948                         ent = r_refdef.scene.entities[i];
4949                         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));
4950                 }
4951         }
4952         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4953                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4954         {
4955                 for (i = 0;i < r_refdef.scene.numentities;i++)
4956                 {
4957                         if (!r_refdef.viewcache.entityvisible[i])
4958                                 continue;
4959                         ent = r_refdef.scene.entities[i];
4960                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_NOCULL | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4961                         {
4962                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4963                                 if (samples < 0)
4964                                         continue; // temp entities do pvs only
4965                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4966                                         ent->last_trace_visibility = realtime;
4967                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4968                                         r_refdef.viewcache.entityvisible[i] = 0;
4969                         }
4970                 }
4971         }
4972 }
4973
4974 /// only used if skyrendermasked, and normally returns false
4975 int R_DrawBrushModelsSky (void)
4976 {
4977         int i, sky;
4978         entity_render_t *ent;
4979
4980         sky = false;
4981         for (i = 0;i < r_refdef.scene.numentities;i++)
4982         {
4983                 if (!r_refdef.viewcache.entityvisible[i])
4984                         continue;
4985                 ent = r_refdef.scene.entities[i];
4986                 if (!ent->model || !ent->model->DrawSky)
4987                         continue;
4988                 ent->model->DrawSky(ent);
4989                 sky = true;
4990         }
4991         return sky;
4992 }
4993
4994 static void R_DrawNoModel(entity_render_t *ent);
4995 static void R_DrawModels(void)
4996 {
4997         int i;
4998         entity_render_t *ent;
4999
5000         for (i = 0;i < r_refdef.scene.numentities;i++)
5001         {
5002                 if (!r_refdef.viewcache.entityvisible[i])
5003                         continue;
5004                 ent = r_refdef.scene.entities[i];
5005                 r_refdef.stats.entities++;
5006                 /*
5007                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5008                 {
5009                         vec3_t f, l, u, o;
5010                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5011                         Con_Printf("R_DrawModels\n");
5012                         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]);
5013                         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);
5014                         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);
5015                 }
5016                 */
5017                 if (ent->model && ent->model->Draw != NULL)
5018                         ent->model->Draw(ent);
5019                 else
5020                         R_DrawNoModel(ent);
5021         }
5022 }
5023
5024 static void R_DrawModelsDepth(void)
5025 {
5026         int i;
5027         entity_render_t *ent;
5028
5029         for (i = 0;i < r_refdef.scene.numentities;i++)
5030         {
5031                 if (!r_refdef.viewcache.entityvisible[i])
5032                         continue;
5033                 ent = r_refdef.scene.entities[i];
5034                 if (ent->model && ent->model->DrawDepth != NULL)
5035                         ent->model->DrawDepth(ent);
5036         }
5037 }
5038
5039 static void R_DrawModelsDebug(void)
5040 {
5041         int i;
5042         entity_render_t *ent;
5043
5044         for (i = 0;i < r_refdef.scene.numentities;i++)
5045         {
5046                 if (!r_refdef.viewcache.entityvisible[i])
5047                         continue;
5048                 ent = r_refdef.scene.entities[i];
5049                 if (ent->model && ent->model->DrawDebug != NULL)
5050                         ent->model->DrawDebug(ent);
5051         }
5052 }
5053
5054 static void R_DrawModelsAddWaterPlanes(void)
5055 {
5056         int i;
5057         entity_render_t *ent;
5058
5059         for (i = 0;i < r_refdef.scene.numentities;i++)
5060         {
5061                 if (!r_refdef.viewcache.entityvisible[i])
5062                         continue;
5063                 ent = r_refdef.scene.entities[i];
5064                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5065                         ent->model->DrawAddWaterPlanes(ent);
5066         }
5067 }
5068
5069 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5070 {
5071         if (r_hdr_irisadaptation.integer)
5072         {
5073                 vec3_t ambient;
5074                 vec3_t diffuse;
5075                 vec3_t diffusenormal;
5076                 vec_t brightness;
5077                 vec_t goal;
5078                 vec_t current;
5079                 R_CompleteLightPoint(ambient, diffuse, diffusenormal, point, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5080                 brightness = (ambient[0] + ambient[1] + ambient[2] + diffuse[0] + diffuse[1] + diffuse[2]) * (1.0f / 3.0f);
5081                 brightness = max(0.0000001f, brightness);
5082                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5083                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5084                 current = r_hdr_irisadaptation_value.value;
5085                 if (current < goal)
5086                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5087                 else if (current > goal)
5088                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5089                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5090                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5091         }
5092         else if (r_hdr_irisadaptation_value.value != 1.0f)
5093                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5094 }
5095
5096 static void R_View_SetFrustum(const int *scissor)
5097 {
5098         int i;
5099         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5100         vec3_t forward, left, up, origin, v;
5101
5102         if(scissor)
5103         {
5104                 // flipped x coordinates (because x points left here)
5105                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5106                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5107
5108                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5109                 switch(vid.renderpath)
5110                 {
5111                         case RENDERPATH_D3D9:
5112                         case RENDERPATH_D3D10:
5113                         case RENDERPATH_D3D11:
5114                                 // non-flipped y coordinates
5115                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5116                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5117                                 break;
5118                         case RENDERPATH_SOFT:
5119                         case RENDERPATH_GL11:
5120                         case RENDERPATH_GL13:
5121                         case RENDERPATH_GL20:
5122                         case RENDERPATH_GLES1:
5123                         case RENDERPATH_GLES2:
5124                                 // non-flipped y coordinates
5125                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5126                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5127                                 break;
5128                 }
5129         }
5130
5131         // we can't trust r_refdef.view.forward and friends in reflected scenes
5132         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5133
5134 #if 0
5135         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5136         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5137         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5138         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5139         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5140         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5141         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5142         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5143         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5144         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5145         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5146         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5147 #endif
5148
5149 #if 0
5150         zNear = r_refdef.nearclip;
5151         nudge = 1.0 - 1.0 / (1<<23);
5152         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5153         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5154         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5155         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5156         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5157         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5158         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5159         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5160 #endif
5161
5162
5163
5164 #if 0
5165         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5166         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5167         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5168         r_refdef.view.frustum[0].dist = m[15] - m[12];
5169
5170         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5171         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5172         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5173         r_refdef.view.frustum[1].dist = m[15] + m[12];
5174
5175         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5176         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5177         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5178         r_refdef.view.frustum[2].dist = m[15] - m[13];
5179
5180         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5181         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5182         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5183         r_refdef.view.frustum[3].dist = m[15] + m[13];
5184
5185         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5186         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5187         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5188         r_refdef.view.frustum[4].dist = m[15] - m[14];
5189
5190         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5191         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5192         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5193         r_refdef.view.frustum[5].dist = m[15] + m[14];
5194 #endif
5195
5196         if (r_refdef.view.useperspective)
5197         {
5198                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5199                 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]);
5200                 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]);
5201                 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]);
5202                 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]);
5203
5204                 // then the normals from the corners relative to origin
5205                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5206                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5207                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5208                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5209
5210                 // in a NORMAL view, forward cross left == up
5211                 // in a REFLECTED view, forward cross left == down
5212                 // so our cross products above need to be adjusted for a left handed coordinate system
5213                 CrossProduct(forward, left, v);
5214                 if(DotProduct(v, up) < 0)
5215                 {
5216                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5217                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5218                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5219                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5220                 }
5221
5222                 // Leaving those out was a mistake, those were in the old code, and they
5223                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5224                 // I couldn't reproduce it after adding those normalizations. --blub
5225                 VectorNormalize(r_refdef.view.frustum[0].normal);
5226                 VectorNormalize(r_refdef.view.frustum[1].normal);
5227                 VectorNormalize(r_refdef.view.frustum[2].normal);
5228                 VectorNormalize(r_refdef.view.frustum[3].normal);
5229
5230                 // make the corners absolute
5231                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5232                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5233                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5234                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5235
5236                 // one more normal
5237                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5238
5239                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5240                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5241                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5242                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5243                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5244         }
5245         else
5246         {
5247                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5248                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5249                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5250                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5251                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5252                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5253                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5254                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5255                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5256                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5257         }
5258         r_refdef.view.numfrustumplanes = 5;
5259
5260         if (r_refdef.view.useclipplane)
5261         {
5262                 r_refdef.view.numfrustumplanes = 6;
5263                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5264         }
5265
5266         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5267                 PlaneClassify(r_refdef.view.frustum + i);
5268
5269         // LordHavoc: note to all quake engine coders, Quake had a special case
5270         // for 90 degrees which assumed a square view (wrong), so I removed it,
5271         // Quake2 has it disabled as well.
5272
5273         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5274         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5275         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5276         //PlaneClassify(&frustum[0]);
5277
5278         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5279         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5280         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5281         //PlaneClassify(&frustum[1]);
5282
5283         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5284         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5285         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5286         //PlaneClassify(&frustum[2]);
5287
5288         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5289         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5290         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5291         //PlaneClassify(&frustum[3]);
5292
5293         // nearclip plane
5294         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5295         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5296         //PlaneClassify(&frustum[4]);
5297 }
5298
5299 void R_View_UpdateWithScissor(const int *myscissor)
5300 {
5301         R_Main_ResizeViewCache();
5302         R_View_SetFrustum(myscissor);
5303         R_View_WorldVisibility(r_refdef.view.useclipplane);
5304         R_View_UpdateEntityVisible();
5305         R_View_UpdateEntityLighting();
5306 }
5307
5308 void R_View_Update(void)
5309 {
5310         R_Main_ResizeViewCache();
5311         R_View_SetFrustum(NULL);
5312         R_View_WorldVisibility(r_refdef.view.useclipplane);
5313         R_View_UpdateEntityVisible();
5314         R_View_UpdateEntityLighting();
5315 }
5316
5317 float viewscalefpsadjusted = 1.0f;
5318
5319 void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5320 {
5321         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5322         scale = bound(0.03125f, scale, 1.0f);
5323         *outwidth = (int)ceil(width * scale);
5324         *outheight = (int)ceil(height * scale);
5325 }
5326
5327 void R_Mesh_SetMainRenderTargets(void)
5328 {
5329         if (r_bloomstate.fbo_framebuffer)
5330                 R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
5331         else
5332                 R_Mesh_ResetRenderTargets();
5333 }
5334
5335 void R_SetupView(qboolean allowwaterclippingplane)
5336 {
5337         const float *customclipplane = NULL;
5338         float plane[4];
5339         int scaledwidth, scaledheight;
5340         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5341         {
5342                 // LordHavoc: couldn't figure out how to make this approach the
5343                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5344                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5345                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5346                         dist = r_refdef.view.clipplane.dist;
5347                 plane[0] = r_refdef.view.clipplane.normal[0];
5348                 plane[1] = r_refdef.view.clipplane.normal[1];
5349                 plane[2] = r_refdef.view.clipplane.normal[2];
5350                 plane[3] = -dist;
5351                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5352         }
5353
5354         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5355         if (!r_refdef.view.useperspective)
5356                 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);
5357         else if (vid.stencil && r_useinfinitefarclip.integer)
5358                 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);
5359         else
5360                 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);
5361         R_Mesh_SetMainRenderTargets();
5362         R_SetViewport(&r_refdef.view.viewport);
5363         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5364         {
5365                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5366                 float screenplane[4];
5367                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5368                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5369                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5370                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5371                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5372         }
5373 }
5374
5375 void R_EntityMatrix(const matrix4x4_t *matrix)
5376 {
5377         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5378         {
5379                 gl_modelmatrixchanged = false;
5380                 gl_modelmatrix = *matrix;
5381                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5382                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5383                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5384                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5385                 CHECKGLERROR
5386                 switch(vid.renderpath)
5387                 {
5388                 case RENDERPATH_D3D9:
5389 #ifdef SUPPORTD3D
5390                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5391                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5392 #endif
5393                         break;
5394                 case RENDERPATH_D3D10:
5395                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5396                         break;
5397                 case RENDERPATH_D3D11:
5398                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5399                         break;
5400                 case RENDERPATH_GL11:
5401                 case RENDERPATH_GL13:
5402                 case RENDERPATH_GLES1:
5403                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5404                         break;
5405                 case RENDERPATH_SOFT:
5406                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5407                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5408                         break;
5409                 case RENDERPATH_GL20:
5410                 case RENDERPATH_GLES2:
5411                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5412                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5413                         break;
5414                 }
5415         }
5416 }
5417
5418 void R_ResetViewRendering2D(void)
5419 {
5420         r_viewport_t viewport;
5421         DrawQ_Finish();
5422
5423         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5424         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);
5425         R_Mesh_ResetRenderTargets();
5426         R_SetViewport(&viewport);
5427         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5428         GL_Color(1, 1, 1, 1);
5429         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5430         GL_BlendFunc(GL_ONE, GL_ZERO);
5431         GL_ScissorTest(false);
5432         GL_DepthMask(false);
5433         GL_DepthRange(0, 1);
5434         GL_DepthTest(false);
5435         GL_DepthFunc(GL_LEQUAL);
5436         R_EntityMatrix(&identitymatrix);
5437         R_Mesh_ResetTextureState();
5438         GL_PolygonOffset(0, 0);
5439         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5440         switch(vid.renderpath)
5441         {
5442         case RENDERPATH_GL11:
5443         case RENDERPATH_GL13:
5444         case RENDERPATH_GL20:
5445         case RENDERPATH_GLES1:
5446         case RENDERPATH_GLES2:
5447                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5448                 break;
5449         case RENDERPATH_D3D9:
5450         case RENDERPATH_D3D10:
5451         case RENDERPATH_D3D11:
5452         case RENDERPATH_SOFT:
5453                 break;
5454         }
5455         GL_CullFace(GL_NONE);
5456 }
5457
5458 void R_ResetViewRendering3D(void)
5459 {
5460         DrawQ_Finish();
5461
5462         R_SetupView(true);
5463         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5464         GL_Color(1, 1, 1, 1);
5465         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5466         GL_BlendFunc(GL_ONE, GL_ZERO);
5467         GL_ScissorTest(true);
5468         GL_DepthMask(true);
5469         GL_DepthRange(0, 1);
5470         GL_DepthTest(true);
5471         GL_DepthFunc(GL_LEQUAL);
5472         R_EntityMatrix(&identitymatrix);
5473         R_Mesh_ResetTextureState();
5474         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5475         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5476         switch(vid.renderpath)
5477         {
5478         case RENDERPATH_GL11:
5479         case RENDERPATH_GL13:
5480         case RENDERPATH_GL20:
5481         case RENDERPATH_GLES1:
5482         case RENDERPATH_GLES2:
5483                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5484                 break;
5485         case RENDERPATH_D3D9:
5486         case RENDERPATH_D3D10:
5487         case RENDERPATH_D3D11:
5488         case RENDERPATH_SOFT:
5489                 break;
5490         }
5491         GL_CullFace(r_refdef.view.cullface_back);
5492 }
5493
5494 /*
5495 ================
5496 R_RenderView_UpdateViewVectors
5497 ================
5498 */
5499 static void R_RenderView_UpdateViewVectors(void)
5500 {
5501         // break apart the view matrix into vectors for various purposes
5502         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5503         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5504         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5505         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5506         // make an inverted copy of the view matrix for tracking sprites
5507         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5508 }
5509
5510 void R_RenderScene(void);
5511 void R_RenderWaterPlanes(void);
5512
5513 static void R_Water_StartFrame(void)
5514 {
5515         int i;
5516         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5517         r_waterstate_waterplane_t *p;
5518
5519         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5520                 return;
5521
5522         switch(vid.renderpath)
5523         {
5524         case RENDERPATH_GL20:
5525         case RENDERPATH_D3D9:
5526         case RENDERPATH_D3D10:
5527         case RENDERPATH_D3D11:
5528         case RENDERPATH_SOFT:
5529         case RENDERPATH_GLES2:
5530                 break;
5531         case RENDERPATH_GL11:
5532         case RENDERPATH_GL13:
5533         case RENDERPATH_GLES1:
5534                 return;
5535         }
5536
5537         // set waterwidth and waterheight to the water resolution that will be
5538         // used (often less than the screen resolution for faster rendering)
5539         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5540
5541         // calculate desired texture sizes
5542         // can't use water if the card does not support the texture size
5543         if (!r_water.integer || r_showsurfaces.integer)
5544                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5545         else if (vid.support.arb_texture_non_power_of_two)
5546         {
5547                 texturewidth = waterwidth;
5548                 textureheight = waterheight;
5549                 camerawidth = waterwidth;
5550                 cameraheight = waterheight;
5551         }
5552         else
5553         {
5554                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5555                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5556                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5557                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5558         }
5559
5560         // allocate textures as needed
5561         if (r_waterstate.texturewidth != texturewidth || r_waterstate.textureheight != textureheight || r_waterstate.camerawidth != camerawidth || r_waterstate.cameraheight != cameraheight)
5562         {
5563                 r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5564                 for (i = 0, p = r_waterstate.waterplanes;i < r_waterstate.maxwaterplanes;i++, p++)
5565                 {
5566                         if (p->texture_refraction)
5567                                 R_FreeTexture(p->texture_refraction);
5568                         p->texture_refraction = NULL;
5569                         if (p->texture_reflection)
5570                                 R_FreeTexture(p->texture_reflection);
5571                         p->texture_reflection = NULL;
5572                         if (p->texture_camera)
5573                                 R_FreeTexture(p->texture_camera);
5574                         p->texture_camera = NULL;
5575                 }
5576                 memset(&r_waterstate, 0, sizeof(r_waterstate));
5577                 r_waterstate.texturewidth = texturewidth;
5578                 r_waterstate.textureheight = textureheight;
5579                 r_waterstate.camerawidth = camerawidth;
5580                 r_waterstate.cameraheight = cameraheight;
5581         }
5582
5583         if (r_waterstate.texturewidth)
5584         {
5585                 int scaledwidth, scaledheight;
5586
5587                 r_waterstate.enabled = true;
5588
5589                 // when doing a reduced render (HDR) we want to use a smaller area
5590                 r_waterstate.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5591                 r_waterstate.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5592                 R_GetScaledViewSize(r_waterstate.waterwidth, r_waterstate.waterheight, &scaledwidth, &scaledheight);
5593
5594                 // set up variables that will be used in shader setup
5595                 r_waterstate.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5596                 r_waterstate.screenscale[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5597                 r_waterstate.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_waterstate.texturewidth;
5598                 r_waterstate.screencenter[1] = 0.5f * (float)scaledheight / (float)r_waterstate.textureheight;
5599         }
5600
5601         r_waterstate.maxwaterplanes = MAX_WATERPLANES;
5602         r_waterstate.numwaterplanes = 0;
5603 }
5604
5605 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5606 {
5607         int triangleindex, planeindex;
5608         const int *e;
5609         vec3_t vert[3];
5610         vec3_t normal;
5611         vec3_t center;
5612         mplane_t plane;
5613         r_waterstate_waterplane_t *p;
5614         texture_t *t = R_GetCurrentTexture(surface->texture);
5615
5616         // just use the first triangle with a valid normal for any decisions
5617         VectorClear(normal);
5618         for (triangleindex = 0, e = rsurface.modelelement3i + surface->num_firsttriangle * 3;triangleindex < surface->num_triangles;triangleindex++, e += 3)
5619         {
5620                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[0]*3, vert[0]);
5621                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[1]*3, vert[1]);
5622                 Matrix4x4_Transform(&rsurface.matrix, rsurface.modelvertex3f + e[2]*3, vert[2]);
5623                 TriangleNormal(vert[0], vert[1], vert[2], normal);
5624                 if (VectorLength2(normal) >= 0.001)
5625                         break;
5626         }
5627
5628         VectorCopy(normal, plane.normal);
5629         VectorNormalize(plane.normal);
5630         plane.dist = DotProduct(vert[0], plane.normal);
5631         PlaneClassify(&plane);
5632         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5633         {
5634                 // skip backfaces (except if nocullface is set)
5635                 if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5636                         return;
5637                 VectorNegate(plane.normal, plane.normal);
5638                 plane.dist *= -1;
5639                 PlaneClassify(&plane);
5640         }
5641
5642
5643         // find a matching plane if there is one
5644         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5645                 if(p->camera_entity == t->camera_entity)
5646                         if (fabs(PlaneDiff(vert[0], &p->plane)) < 1 && fabs(PlaneDiff(vert[1], &p->plane)) < 1 && fabs(PlaneDiff(vert[2], &p->plane)) < 1)
5647                                 break;
5648         if (planeindex >= r_waterstate.maxwaterplanes)
5649                 return; // nothing we can do, out of planes
5650
5651         // if this triangle does not fit any known plane rendered this frame, add one
5652         if (planeindex >= r_waterstate.numwaterplanes)
5653         {
5654                 // store the new plane
5655                 r_waterstate.numwaterplanes++;
5656                 p->plane = plane;
5657                 // clear materialflags and pvs
5658                 p->materialflags = 0;
5659                 p->pvsvalid = false;
5660                 p->camera_entity = t->camera_entity;
5661                 VectorCopy(surface->mins, p->mins);
5662                 VectorCopy(surface->maxs, p->maxs);
5663         }
5664         else
5665         {
5666                 // merge mins/maxs
5667                 p->mins[0] = min(p->mins[0], surface->mins[0]);
5668                 p->mins[1] = min(p->mins[1], surface->mins[1]);
5669                 p->mins[2] = min(p->mins[2], surface->mins[2]);
5670                 p->maxs[0] = max(p->maxs[0], surface->maxs[0]);
5671                 p->maxs[1] = max(p->maxs[1], surface->maxs[1]);
5672                 p->maxs[2] = max(p->maxs[2], surface->maxs[2]);
5673         }
5674         // merge this surface's materialflags into the waterplane
5675         p->materialflags |= t->currentmaterialflags;
5676         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5677         {
5678                 // merge this surface's PVS into the waterplane
5679                 VectorMAM(0.5f, surface->mins, 0.5f, surface->maxs, center);
5680                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5681                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5682                 {
5683                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5684                         p->pvsvalid = true;
5685                 }
5686         }
5687 }
5688
5689 extern cvar_t r_drawparticles;
5690 extern cvar_t r_drawdecals;
5691
5692 static void R_Water_ProcessPlanes(void)
5693 {
5694         int myscissor[4];
5695         r_refdef_view_t originalview;
5696         r_refdef_view_t myview;
5697         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;
5698         r_waterstate_waterplane_t *p;
5699         vec3_t visorigin;
5700
5701         originalview = r_refdef.view;
5702
5703         // lowquality hack, temporarily shut down some cvars and restore afterwards
5704         qualityreduction = r_water_lowquality.integer;
5705         if (qualityreduction > 0)
5706         {
5707                 if (qualityreduction >= 1)
5708                 {
5709                         old_r_shadows = r_shadows.integer;
5710                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5711                         old_r_dlight = r_shadow_realtime_dlight.integer;
5712                         Cvar_SetValueQuick(&r_shadows, 0);
5713                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5714                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5715                 }
5716                 if (qualityreduction >= 2)
5717                 {
5718                         old_r_dynamic = r_dynamic.integer;
5719                         old_r_particles = r_drawparticles.integer;
5720                         old_r_decals = r_drawdecals.integer;
5721                         Cvar_SetValueQuick(&r_dynamic, 0);
5722                         Cvar_SetValueQuick(&r_drawparticles, 0);
5723                         Cvar_SetValueQuick(&r_drawdecals, 0);
5724                 }
5725         }
5726
5727         // make sure enough textures are allocated
5728         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5729         {
5730                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5731                 {
5732                         if (!p->texture_refraction)
5733                                 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);
5734                         if (!p->texture_refraction)
5735                                 goto error;
5736                 }
5737                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5738                 {
5739                         if (!p->texture_camera)
5740                                 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);
5741                         if (!p->texture_camera)
5742                                 goto error;
5743                 }
5744
5745                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5746                 {
5747                         if (!p->texture_reflection)
5748                                 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);
5749                         if (!p->texture_reflection)
5750                                 goto error;
5751                 }
5752         }
5753
5754         // render views
5755         r_refdef.view = originalview;
5756         r_refdef.view.showdebug = false;
5757         r_refdef.view.width = r_waterstate.waterwidth;
5758         r_refdef.view.height = r_waterstate.waterheight;
5759         r_refdef.view.useclipplane = true;
5760         myview = r_refdef.view;
5761         r_waterstate.renderingscene = true;
5762         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
5763         {
5764                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5765                 {
5766                         r_refdef.view = myview;
5767                         if(r_water_scissormode.integer)
5768                         {
5769                                 R_SetupView(true);
5770                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5771                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5772                         }
5773
5774                         // render reflected scene and copy into texture
5775                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5776                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5777                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5778                         r_refdef.view.clipplane = p->plane;
5779                         // reverse the cullface settings for this render
5780                         r_refdef.view.cullface_front = GL_FRONT;
5781                         r_refdef.view.cullface_back = GL_BACK;
5782                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5783                         {
5784                                 r_refdef.view.usecustompvs = true;
5785                                 if (p->pvsvalid)
5786                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5787                                 else
5788                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5789                         }
5790
5791                         R_ResetViewRendering3D();
5792                         R_ClearScreen(r_refdef.fogenabled);
5793                         if(r_water_scissormode.integer & 2)
5794                                 R_View_UpdateWithScissor(myscissor);
5795                         else
5796                                 R_View_Update();
5797                         if(r_water_scissormode.integer & 1)
5798                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5799                         R_RenderScene();
5800
5801                         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);
5802                 }
5803
5804                 // render the normal view scene and copy into texture
5805                 // (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)
5806                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5807                 {
5808                         r_refdef.view = myview;
5809                         if(r_water_scissormode.integer)
5810                         {
5811                                 R_SetupView(true);
5812                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5813                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5814                         }
5815
5816                         r_waterstate.renderingrefraction = true;
5817
5818                         r_refdef.view.clipplane = p->plane;
5819                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5820                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5821
5822                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5823                         {
5824                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5825                                 r_waterstate.renderingrefraction = false; // we don't want to hide the player model from these ones
5826                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5827                                 R_RenderView_UpdateViewVectors();
5828                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5829                                 {
5830                                         r_refdef.view.usecustompvs = true;
5831                                         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);
5832                                 }
5833                         }
5834
5835                         PlaneClassify(&r_refdef.view.clipplane);
5836
5837                         R_ResetViewRendering3D();
5838                         R_ClearScreen(r_refdef.fogenabled);
5839                         if(r_water_scissormode.integer & 2)
5840                                 R_View_UpdateWithScissor(myscissor);
5841                         else
5842                                 R_View_Update();
5843                         if(r_water_scissormode.integer & 1)
5844                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5845                         R_RenderScene();
5846
5847                         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);
5848                         r_waterstate.renderingrefraction = false;
5849                 }
5850                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5851                 {
5852                         r_refdef.view = myview;
5853
5854                         r_refdef.view.clipplane = p->plane;
5855                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5856                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5857
5858                         r_refdef.view.width = r_waterstate.camerawidth;
5859                         r_refdef.view.height = r_waterstate.cameraheight;
5860                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5861                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5862
5863                         if(p->camera_entity)
5864                         {
5865                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5866                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5867                         }
5868
5869                         // note: all of the view is used for displaying... so
5870                         // there is no use in scissoring
5871
5872                         // reverse the cullface settings for this render
5873                         r_refdef.view.cullface_front = GL_FRONT;
5874                         r_refdef.view.cullface_back = GL_BACK;
5875                         // also reverse the view matrix
5876                         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
5877                         R_RenderView_UpdateViewVectors();
5878                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5879                         {
5880                                 r_refdef.view.usecustompvs = true;
5881                                 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);
5882                         }
5883                         
5884                         // camera needs no clipplane
5885                         r_refdef.view.useclipplane = false;
5886
5887                         PlaneClassify(&r_refdef.view.clipplane);
5888
5889                         R_ResetViewRendering3D();
5890                         R_ClearScreen(r_refdef.fogenabled);
5891                         R_View_Update();
5892                         R_RenderScene();
5893
5894                         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);
5895                         r_waterstate.renderingrefraction = false;
5896                 }
5897
5898         }
5899         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5900         r_waterstate.renderingscene = false;
5901         r_refdef.view = originalview;
5902         R_ResetViewRendering3D();
5903         R_ClearScreen(r_refdef.fogenabled);
5904         R_View_Update();
5905         goto finish;
5906 error:
5907         r_refdef.view = originalview;
5908         r_waterstate.renderingscene = false;
5909         Cvar_SetValueQuick(&r_water, 0);
5910         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5911 finish:
5912         // lowquality hack, restore cvars
5913         if (qualityreduction > 0)
5914         {
5915                 if (qualityreduction >= 1)
5916                 {
5917                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5918                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5919                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5920                 }
5921                 if (qualityreduction >= 2)
5922                 {
5923                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5924                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5925                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5926                 }
5927         }
5928 }
5929
5930 void R_Bloom_StartFrame(void)
5931 {
5932         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5933         int viewwidth, viewheight;
5934         textype_t textype;
5935
5936         if (r_viewscale_fpsscaling.integer)
5937         {
5938                 double actualframetime;
5939                 double targetframetime;
5940                 double adjust;
5941                 actualframetime = r_refdef.lastdrawscreentime;
5942                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
5943                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
5944                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
5945                 if (r_viewscale_fpsscaling_stepsize.value > 0)
5946                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
5947                 viewscalefpsadjusted += adjust;
5948                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
5949         }
5950         else
5951                 viewscalefpsadjusted = 1.0f;
5952
5953         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
5954
5955         switch(vid.renderpath)
5956         {
5957         case RENDERPATH_GL20:
5958         case RENDERPATH_D3D9:
5959         case RENDERPATH_D3D10:
5960         case RENDERPATH_D3D11:
5961         case RENDERPATH_SOFT:
5962         case RENDERPATH_GLES2:
5963                 break;
5964         case RENDERPATH_GL11:
5965         case RENDERPATH_GL13:
5966         case RENDERPATH_GLES1:
5967                 return;
5968         }
5969
5970         // set bloomwidth and bloomheight to the bloom resolution that will be
5971         // used (often less than the screen resolution for faster rendering)
5972         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
5973         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * vid.height / vid.width;
5974         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, vid.height);
5975         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, (int)vid.maxtexturesize_2d);
5976         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, (int)vid.maxtexturesize_2d);
5977
5978         // calculate desired texture sizes
5979         if (vid.support.arb_texture_non_power_of_two)
5980         {
5981                 screentexturewidth = vid.width;
5982                 screentextureheight = vid.height;
5983                 bloomtexturewidth = r_bloomstate.bloomwidth;
5984                 bloomtextureheight = r_bloomstate.bloomheight;
5985         }
5986         else
5987         {
5988                 for (screentexturewidth  = 1;screentexturewidth  < vid.width               ;screentexturewidth  *= 2);
5989                 for (screentextureheight = 1;screentextureheight < vid.height              ;screentextureheight *= 2);
5990                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_bloomstate.bloomwidth ;bloomtexturewidth   *= 2);
5991                 for (bloomtextureheight  = 1;bloomtextureheight  < r_bloomstate.bloomheight;bloomtextureheight  *= 2);
5992         }
5993
5994         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))
5995         {
5996                 Cvar_SetValueQuick(&r_hdr, 0);
5997                 Cvar_SetValueQuick(&r_bloom, 0);
5998                 Cvar_SetValueQuick(&r_motionblur, 0);
5999                 Cvar_SetValueQuick(&r_damageblur, 0);
6000         }
6001
6002         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)
6003                 screentexturewidth = screentextureheight = 0;
6004         if (!r_hdr.integer && !r_bloom.integer)
6005                 bloomtexturewidth = bloomtextureheight = 0;
6006
6007         textype = TEXTYPE_COLORBUFFER;
6008         switch (vid.renderpath)
6009         {
6010         case RENDERPATH_GL20:
6011         case RENDERPATH_GLES2:
6012                 if (vid.support.ext_framebuffer_object)
6013                 {
6014                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6015                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6016                 }
6017                 break;
6018         case RENDERPATH_GL11:
6019         case RENDERPATH_GL13:
6020         case RENDERPATH_GLES1:
6021         case RENDERPATH_D3D9:
6022         case RENDERPATH_D3D10:
6023         case RENDERPATH_D3D11:
6024         case RENDERPATH_SOFT:
6025                 break;
6026         }
6027
6028         // allocate textures as needed
6029         if (r_bloomstate.screentexturewidth != screentexturewidth
6030          || r_bloomstate.screentextureheight != screentextureheight
6031          || r_bloomstate.bloomtexturewidth != bloomtexturewidth
6032          || r_bloomstate.bloomtextureheight != bloomtextureheight
6033          || r_bloomstate.texturetype != textype
6034          || r_bloomstate.viewfbo != r_viewfbo.integer)
6035         {
6036                 if (r_bloomstate.texture_bloom)
6037                         R_FreeTexture(r_bloomstate.texture_bloom);
6038                 r_bloomstate.texture_bloom = NULL;
6039                 if (r_bloomstate.texture_screen)
6040                         R_FreeTexture(r_bloomstate.texture_screen);
6041                 r_bloomstate.texture_screen = NULL;
6042                 if (r_bloomstate.fbo_framebuffer)
6043                         R_Mesh_DestroyFramebufferObject(r_bloomstate.fbo_framebuffer);
6044                 r_bloomstate.fbo_framebuffer = 0;
6045                 if (r_bloomstate.texture_framebuffercolor)
6046                         R_FreeTexture(r_bloomstate.texture_framebuffercolor);
6047                 r_bloomstate.texture_framebuffercolor = NULL;
6048                 if (r_bloomstate.texture_framebufferdepth)
6049                         R_FreeTexture(r_bloomstate.texture_framebufferdepth);
6050                 r_bloomstate.texture_framebufferdepth = NULL;
6051                 r_bloomstate.screentexturewidth = screentexturewidth;
6052                 r_bloomstate.screentextureheight = screentextureheight;
6053                 if (r_bloomstate.screentexturewidth && r_bloomstate.screentextureheight)
6054                         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);
6055                 if (r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object)
6056                 {
6057                         // FIXME: choose depth bits based on a cvar
6058                         r_bloomstate.texture_framebufferdepth = R_LoadTextureShadowMap2D(r_main_texturepool, "framebufferdepth", r_bloomstate.screentexturewidth, r_bloomstate.screentextureheight, 24, false);
6059                         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);
6060                         r_bloomstate.fbo_framebuffer = R_Mesh_CreateFramebufferObject(r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6061                         R_Mesh_SetRenderTargets(r_bloomstate.fbo_framebuffer, r_bloomstate.texture_framebufferdepth, r_bloomstate.texture_framebuffercolor, NULL, NULL, NULL);
6062 #ifndef USE_GLES2
6063                         // render depth into one texture and normalmap into the other
6064                         if (qglDrawBuffer)
6065                         {
6066                                 int status;
6067                                 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6068                                 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
6069                                 status = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER);CHECKGLERROR
6070                                 if (status != GL_FRAMEBUFFER_COMPLETE)
6071                                         Con_Printf("R_Bloom_StartFrame: glCheckFramebufferStatusEXT returned %i\n", status);
6072                         }
6073 #endif
6074                 }
6075                 r_bloomstate.bloomtexturewidth = bloomtexturewidth;
6076                 r_bloomstate.bloomtextureheight = bloomtextureheight;
6077                 if (r_bloomstate.bloomtexturewidth && r_bloomstate.bloomtextureheight)
6078                         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);
6079                 r_bloomstate.viewfbo = r_viewfbo.integer;
6080                 r_bloomstate.texturetype = textype;
6081         }
6082
6083         // when doing a reduced render (HDR) we want to use a smaller area
6084         r_bloomstate.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6085         r_bloomstate.bloomheight = r_bloomstate.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6086         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_refdef.view.height);
6087         r_bloomstate.bloomwidth = bound(1, r_bloomstate.bloomwidth, r_bloomstate.bloomtexturewidth);
6088         r_bloomstate.bloomheight = bound(1, r_bloomstate.bloomheight, r_bloomstate.bloomtextureheight);
6089
6090         // set up a texcoord array for the full resolution screen image
6091         // (we have to keep this around to copy back during final render)
6092         r_bloomstate.screentexcoord2f[0] = 0;
6093         r_bloomstate.screentexcoord2f[1] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6094         r_bloomstate.screentexcoord2f[2] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6095         r_bloomstate.screentexcoord2f[3] = (float)viewheight    / (float)r_bloomstate.screentextureheight;
6096         r_bloomstate.screentexcoord2f[4] = (float)viewwidth     / (float)r_bloomstate.screentexturewidth;
6097         r_bloomstate.screentexcoord2f[5] = 0;
6098         r_bloomstate.screentexcoord2f[6] = 0;
6099         r_bloomstate.screentexcoord2f[7] = 0;
6100
6101         // set up a texcoord array for the reduced resolution bloom image
6102         // (which will be additive blended over the screen image)
6103         r_bloomstate.bloomtexcoord2f[0] = 0;
6104         r_bloomstate.bloomtexcoord2f[1] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6105         r_bloomstate.bloomtexcoord2f[2] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6106         r_bloomstate.bloomtexcoord2f[3] = (float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6107         r_bloomstate.bloomtexcoord2f[4] = (float)r_bloomstate.bloomwidth  / (float)r_bloomstate.bloomtexturewidth;
6108         r_bloomstate.bloomtexcoord2f[5] = 0;
6109         r_bloomstate.bloomtexcoord2f[6] = 0;
6110         r_bloomstate.bloomtexcoord2f[7] = 0;
6111
6112         switch(vid.renderpath)
6113         {
6114         case RENDERPATH_GL11:
6115         case RENDERPATH_GL13:
6116         case RENDERPATH_GL20:
6117         case RENDERPATH_SOFT:
6118         case RENDERPATH_GLES1:
6119         case RENDERPATH_GLES2:
6120                 break;
6121         case RENDERPATH_D3D9:
6122         case RENDERPATH_D3D10:
6123         case RENDERPATH_D3D11:
6124                 {
6125                         int i;
6126                         for (i = 0;i < 4;i++)
6127                         {
6128                                 r_bloomstate.screentexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.screentexturewidth;
6129                                 r_bloomstate.screentexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.screentextureheight;
6130                                 r_bloomstate.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_bloomstate.bloomtexturewidth;
6131                                 r_bloomstate.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_bloomstate.bloomtextureheight;
6132                         }
6133                 }
6134                 break;
6135         }
6136
6137         if ((r_hdr.integer || r_bloom.integer) && r_bloomstate.bloomwidth)
6138         {
6139                 r_bloomstate.enabled = true;
6140                 r_bloomstate.hdr = r_hdr.integer != 0 && !r_bloomstate.fbo_framebuffer;
6141         }
6142
6143         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);
6144
6145         if (r_bloomstate.fbo_framebuffer)
6146                 r_refdef.view.clear = true;
6147 }
6148
6149 void R_Bloom_CopyBloomTexture(float colorscale)
6150 {
6151         r_refdef.stats.bloom++;
6152
6153         // scale down screen texture to the bloom texture size
6154         CHECKGLERROR
6155         R_Mesh_SetMainRenderTargets();
6156         R_SetViewport(&r_bloomstate.viewport);
6157         GL_BlendFunc(GL_ONE, GL_ZERO);
6158         GL_Color(colorscale, colorscale, colorscale, 1);
6159         // 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...
6160         switch(vid.renderpath)
6161         {
6162         case RENDERPATH_GL11:
6163         case RENDERPATH_GL13:
6164         case RENDERPATH_GL20:
6165         case RENDERPATH_GLES1:
6166         case RENDERPATH_GLES2:
6167         case RENDERPATH_SOFT:
6168                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6169                 break;
6170         case RENDERPATH_D3D9:
6171         case RENDERPATH_D3D10:
6172         case RENDERPATH_D3D11:
6173                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6174                 break;
6175         }
6176         // TODO: do boxfilter scale-down in shader?
6177         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6178         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6179         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6180
6181         // we now have a bloom image in the framebuffer
6182         // copy it into the bloom image texture for later processing
6183         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);
6184         r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6185 }
6186
6187 void R_Bloom_CopyHDRTexture(void)
6188 {
6189         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);
6190         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6191 }
6192
6193 void R_Bloom_MakeTexture(void)
6194 {
6195         int x, range, dir;
6196         float xoffset, yoffset, r, brighten;
6197
6198         r_refdef.stats.bloom++;
6199
6200         R_ResetViewRendering2D();
6201
6202         // we have a bloom image in the framebuffer
6203         CHECKGLERROR
6204         R_SetViewport(&r_bloomstate.viewport);
6205
6206         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6207         {
6208                 x *= 2;
6209                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6210                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6211                 GL_Color(r,r,r,1);
6212                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.bloomtexcoord2f);
6213                 R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6214                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6215                 r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6216
6217                 // copy the vertically blurred bloom view to a texture
6218                 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);
6219                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6220         }
6221
6222         range = r_bloom_blur.integer * r_bloomstate.bloomwidth / 320;
6223         brighten = r_bloom_brighten.value;
6224         if (r_bloomstate.hdr)
6225                 brighten *= r_hdr_range.value;
6226         brighten = sqrt(brighten);
6227         if(range >= 1)
6228                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6229         R_SetupShader_Generic(r_bloomstate.texture_bloom, NULL, GL_MODULATE, 1, false, true);
6230
6231         for (dir = 0;dir < 2;dir++)
6232         {
6233                 // blend on at multiple vertical offsets to achieve a vertical blur
6234                 // TODO: do offset blends using GLSL
6235                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6236                 GL_BlendFunc(GL_ONE, GL_ZERO);
6237                 for (x = -range;x <= range;x++)
6238                 {
6239                         if (!dir){xoffset = 0;yoffset = x;}
6240                         else {xoffset = x;yoffset = 0;}
6241                         xoffset /= (float)r_bloomstate.bloomtexturewidth;
6242                         yoffset /= (float)r_bloomstate.bloomtextureheight;
6243                         // compute a texcoord array with the specified x and y offset
6244                         r_bloomstate.offsettexcoord2f[0] = xoffset+0;
6245                         r_bloomstate.offsettexcoord2f[1] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6246                         r_bloomstate.offsettexcoord2f[2] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6247                         r_bloomstate.offsettexcoord2f[3] = yoffset+(float)r_bloomstate.bloomheight / (float)r_bloomstate.bloomtextureheight;
6248                         r_bloomstate.offsettexcoord2f[4] = xoffset+(float)r_bloomstate.bloomwidth / (float)r_bloomstate.bloomtexturewidth;
6249                         r_bloomstate.offsettexcoord2f[5] = yoffset+0;
6250                         r_bloomstate.offsettexcoord2f[6] = xoffset+0;
6251                         r_bloomstate.offsettexcoord2f[7] = yoffset+0;
6252                         // this r value looks like a 'dot' particle, fading sharply to
6253                         // black at the edges
6254                         // (probably not realistic but looks good enough)
6255                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6256                         //r = brighten/(range*2+1);
6257                         r = brighten / (range * 2 + 1);
6258                         if(range >= 1)
6259                                 r *= (1 - x*x/(float)(range*range));
6260                         GL_Color(r, r, r, 1);
6261                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.offsettexcoord2f);
6262                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6263                         r_refdef.stats.bloom_drawpixels += r_bloomstate.bloomwidth * r_bloomstate.bloomheight;
6264                         GL_BlendFunc(GL_ONE, GL_ONE);
6265                 }
6266
6267                 // copy the vertically blurred bloom view to a texture
6268                 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);
6269                 r_refdef.stats.bloom_copypixels += r_bloomstate.viewport.width * r_bloomstate.viewport.height;
6270         }
6271 }
6272
6273 void R_HDR_RenderBloomTexture(void)
6274 {
6275         int oldwidth, oldheight;
6276         float oldcolorscale;
6277         qboolean oldwaterstate;
6278
6279         oldwaterstate = r_waterstate.enabled;
6280         oldcolorscale = r_refdef.view.colorscale;
6281         oldwidth = r_refdef.view.width;
6282         oldheight = r_refdef.view.height;
6283         r_refdef.view.width = r_bloomstate.bloomwidth;
6284         r_refdef.view.height = r_bloomstate.bloomheight;
6285
6286         if(r_hdr.integer < 2)
6287                 r_waterstate.enabled = false;
6288
6289         // TODO: support GL_EXT_framebuffer_object rather than reusing the framebuffer?  it might improve SLI performance.
6290         // TODO: add exposure compensation features
6291         // TODO: add fp16 framebuffer support (using GL_EXT_framebuffer_object)
6292
6293         r_refdef.view.showdebug = false;
6294         r_refdef.view.colorscale *= r_bloom_colorscale.value / bound(1, r_hdr_range.value, 16);
6295
6296         R_ResetViewRendering3D();
6297
6298         R_ClearScreen(r_refdef.fogenabled);
6299         if (r_timereport_active)
6300                 R_TimeReport("HDRclear");
6301
6302         R_View_Update();
6303         if (r_timereport_active)
6304                 R_TimeReport("visibility");
6305
6306         // only do secondary renders with HDR if r_hdr is 2 or higher
6307         r_waterstate.numwaterplanes = 0;
6308         if (r_waterstate.enabled)
6309                 R_RenderWaterPlanes();
6310
6311         r_refdef.view.showdebug = true;
6312         R_RenderScene();
6313         r_waterstate.numwaterplanes = 0;
6314
6315         R_ResetViewRendering2D();
6316
6317         R_Bloom_CopyHDRTexture();
6318         R_Bloom_MakeTexture();
6319
6320         // restore the view settings
6321         r_waterstate.enabled = oldwaterstate;
6322         r_refdef.view.width = oldwidth;
6323         r_refdef.view.height = oldheight;
6324         r_refdef.view.colorscale = oldcolorscale;
6325
6326         R_ResetViewRendering3D();
6327
6328         R_ClearScreen(r_refdef.fogenabled);
6329         if (r_timereport_active)
6330                 R_TimeReport("viewclear");
6331 }
6332
6333 static void R_BlendView(void)
6334 {
6335         unsigned int permutation;
6336         float uservecs[4][4];
6337
6338         switch (vid.renderpath)
6339         {
6340         case RENDERPATH_GL20:
6341         case RENDERPATH_D3D9:
6342         case RENDERPATH_D3D10:
6343         case RENDERPATH_D3D11:
6344         case RENDERPATH_SOFT:
6345         case RENDERPATH_GLES2:
6346                 permutation =
6347                           (r_bloomstate.texture_bloom ? SHADERPERMUTATION_BLOOM : 0)
6348                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6349                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6350                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6351                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6352
6353                 if (r_bloomstate.texture_screen)
6354                 {
6355                         // make sure the buffer is available
6356                         if (r_bloom_blur.value < 1) { Cvar_SetValueQuick(&r_bloom_blur, 1); }
6357
6358                         R_ResetViewRendering2D();
6359                         R_Mesh_SetMainRenderTargets();
6360
6361                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0))
6362                         {
6363                                 // declare variables
6364                                 float blur_factor, blur_mouseaccel, blur_velocity;
6365                                 static float blur_average; 
6366                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6367
6368                                 // set a goal for the factoring
6369                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6370                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6371                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6372                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6373                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6374                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6375
6376                                 // from the goal, pick an averaged value between goal and last value
6377                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6378                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6379                                 
6380                                 // enforce minimum amount of blur 
6381                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6382                                 
6383                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6384
6385                                 // calculate values into a standard alpha
6386                                 cl.motionbluralpha = 1 - exp(-
6387                                                 (
6388                                                  (r_motionblur.value * blur_factor / 80)
6389                                                  +
6390                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6391                                                 )
6392                                                 /
6393                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6394                                           );
6395                                 
6396                                 // randomization for the blur value to combat persistent ghosting
6397                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6398                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6399                                 
6400                                 // apply the blur
6401                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap)
6402                                 {
6403                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6404                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6405                                         switch(vid.renderpath)
6406                                         {
6407                                         case RENDERPATH_GL11:
6408                                         case RENDERPATH_GL13:
6409                                         case RENDERPATH_GL20:
6410                                         case RENDERPATH_GLES1:
6411                                         case RENDERPATH_GLES2:
6412                                         case RENDERPATH_SOFT:
6413                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6414                                                 break;
6415                                         case RENDERPATH_D3D9:
6416                                         case RENDERPATH_D3D10:
6417                                         case RENDERPATH_D3D11:
6418                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_bloomstate.screentexcoord2f);
6419                                                 break;
6420                                         }
6421                                         R_SetupShader_Generic(r_bloomstate.texture_screen, NULL, GL_MODULATE, 1, false, true);
6422                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6423                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6424                                 }
6425                                 
6426                                 // updates old view angles for next pass 
6427                                 VectorCopy(cl.viewangles, blur_oldangles);
6428                         }
6429
6430                         // copy view into the screen texture
6431                         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);
6432                         r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6433                 }
6434                 else if (!r_bloomstate.texture_bloom)
6435                 {
6436                         // we may still have to do view tint...
6437                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6438                         {
6439                                 // apply a color tint to the whole view
6440                                 R_ResetViewRendering2D();
6441                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6442                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6443                                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6444                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6445                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6446                         }
6447                         break; // no screen processing, no bloom, skip it
6448                 }
6449
6450                 if (r_bloomstate.texture_bloom && !r_bloomstate.hdr)
6451                 {
6452                         // render simple bloom effect
6453                         // copy the screen and shrink it and darken it for the bloom process
6454                         R_Bloom_CopyBloomTexture(r_bloom_colorscale.value);
6455                         // make the bloom texture
6456                         R_Bloom_MakeTexture();
6457                 }
6458
6459 #if _MSC_VER >= 1400
6460 #define sscanf sscanf_s
6461 #endif
6462                 memset(uservecs, 0, sizeof(uservecs));
6463                 if (r_glsl_postprocess_uservec1_enable.integer)
6464                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6465                 if (r_glsl_postprocess_uservec2_enable.integer)
6466                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6467                 if (r_glsl_postprocess_uservec3_enable.integer)
6468                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6469                 if (r_glsl_postprocess_uservec4_enable.integer)
6470                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6471
6472                 R_ResetViewRendering2D();
6473                 GL_Color(1, 1, 1, 1);
6474                 GL_BlendFunc(GL_ONE, GL_ZERO);
6475
6476                 switch(vid.renderpath)
6477                 {
6478                 case RENDERPATH_GL20:
6479                 case RENDERPATH_GLES2:
6480                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6481                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6482                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_bloomstate.texture_screen);
6483                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_bloomstate.texture_bloom );
6484                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6485                         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]);
6486                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6487                         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]);
6488                         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]);
6489                         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]);
6490                         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]);
6491                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6492                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6493                         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);
6494                         break;
6495                 case RENDERPATH_D3D9:
6496 #ifdef SUPPORTD3D
6497                         // 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...
6498                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6499                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6500                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6501                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6502                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6503                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6504                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6505                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6506                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6507                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6508                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6509                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6510                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6511                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6512 #endif
6513                         break;
6514                 case RENDERPATH_D3D10:
6515                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6516                         break;
6517                 case RENDERPATH_D3D11:
6518                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6519                         break;
6520                 case RENDERPATH_SOFT:
6521                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_bloomstate.screentexcoord2f, r_bloomstate.bloomtexcoord2f);
6522                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6523                         R_Mesh_TexBind(GL20TU_FIRST     , r_bloomstate.texture_screen);
6524                         R_Mesh_TexBind(GL20TU_SECOND    , r_bloomstate.texture_bloom );
6525                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6526                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6527                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_bloomstate.screentexturewidth, 1.0/r_bloomstate.screentextureheight);
6528                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6529                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6530                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6531                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6532                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6533                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6534                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6535                         break;
6536                 default:
6537                         break;
6538                 }
6539                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6540                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6541                 break;
6542         case RENDERPATH_GL11:
6543         case RENDERPATH_GL13:
6544         case RENDERPATH_GLES1:
6545                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6546                 {
6547                         // apply a color tint to the whole view
6548                         R_ResetViewRendering2D();
6549                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6550                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6551                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, true);
6552                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6553                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6554                 }
6555                 break;
6556         }
6557 }
6558
6559 matrix4x4_t r_waterscrollmatrix;
6560
6561 void R_UpdateFogColor(void) // needs to be called before HDR subrender too, as that changes colorscale!
6562 {
6563         if (r_refdef.fog_density)
6564         {
6565                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6566                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6567                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6568
6569                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6570                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6571                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6572                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6573
6574                 {
6575                         vec3_t fogvec;
6576                         VectorCopy(r_refdef.fogcolor, fogvec);
6577                         //   color.rgb *= ContrastBoost * SceneBrightness;
6578                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6579                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6580                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6581                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6582                 }
6583         }
6584 }
6585
6586 void R_UpdateVariables(void)
6587 {
6588         R_Textures_Frame();
6589
6590         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6591
6592         r_refdef.farclip = r_farclip_base.value;
6593         if (r_refdef.scene.worldmodel)
6594                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6595         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6596
6597         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6598                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6599         r_refdef.polygonfactor = 0;
6600         r_refdef.polygonoffset = 0;
6601         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6602         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6603
6604         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6605         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6606         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6607         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6608         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6609         if (FAKELIGHT_ENABLED)
6610         {
6611                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6612         }
6613         if (r_showsurfaces.integer)
6614         {
6615                 r_refdef.scene.rtworld = false;
6616                 r_refdef.scene.rtworldshadows = false;
6617                 r_refdef.scene.rtdlight = false;
6618                 r_refdef.scene.rtdlightshadows = false;
6619                 r_refdef.lightmapintensity = 0;
6620         }
6621
6622         if (gamemode == GAME_NEHAHRA)
6623         {
6624                 if (gl_fogenable.integer)
6625                 {
6626                         r_refdef.oldgl_fogenable = true;
6627                         r_refdef.fog_density = gl_fogdensity.value;
6628                         r_refdef.fog_red = gl_fogred.value;
6629                         r_refdef.fog_green = gl_foggreen.value;
6630                         r_refdef.fog_blue = gl_fogblue.value;
6631                         r_refdef.fog_alpha = 1;
6632                         r_refdef.fog_start = 0;
6633                         r_refdef.fog_end = gl_skyclip.value;
6634                         r_refdef.fog_height = 1<<30;
6635                         r_refdef.fog_fadedepth = 128;
6636                 }
6637                 else if (r_refdef.oldgl_fogenable)
6638                 {
6639                         r_refdef.oldgl_fogenable = false;
6640                         r_refdef.fog_density = 0;
6641                         r_refdef.fog_red = 0;
6642                         r_refdef.fog_green = 0;
6643                         r_refdef.fog_blue = 0;
6644                         r_refdef.fog_alpha = 0;
6645                         r_refdef.fog_start = 0;
6646                         r_refdef.fog_end = 0;
6647                         r_refdef.fog_height = 1<<30;
6648                         r_refdef.fog_fadedepth = 128;
6649                 }
6650         }
6651
6652         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6653         r_refdef.fog_start = max(0, r_refdef.fog_start);
6654         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6655
6656         // R_UpdateFogColor(); // why? R_RenderScene does it anyway
6657
6658         if (r_refdef.fog_density && r_drawfog.integer)
6659         {
6660                 r_refdef.fogenabled = true;
6661                 // this is the point where the fog reaches 0.9986 alpha, which we
6662                 // consider a good enough cutoff point for the texture
6663                 // (0.9986 * 256 == 255.6)
6664                 if (r_fog_exp2.integer)
6665                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6666                 else
6667                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6668                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6669                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6670                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6671                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6672                         R_BuildFogHeightTexture();
6673                 // fog color was already set
6674                 // update the fog texture
6675                 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)
6676                         R_BuildFogTexture();
6677                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6678                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6679         }
6680         else
6681                 r_refdef.fogenabled = false;
6682
6683         switch(vid.renderpath)
6684         {
6685         case RENDERPATH_GL20:
6686         case RENDERPATH_D3D9:
6687         case RENDERPATH_D3D10:
6688         case RENDERPATH_D3D11:
6689         case RENDERPATH_SOFT:
6690         case RENDERPATH_GLES2:
6691                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6692                 {
6693                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6694                         {
6695                                 // build GLSL gamma texture
6696 #define RAMPWIDTH 256
6697                                 unsigned short ramp[RAMPWIDTH * 3];
6698                                 unsigned char rampbgr[RAMPWIDTH][4];
6699                                 int i;
6700
6701                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6702
6703                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6704                                 for(i = 0; i < RAMPWIDTH; ++i)
6705                                 {
6706                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6707                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6708                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6709                                         rampbgr[i][3] = 0;
6710                                 }
6711                                 if (r_texture_gammaramps)
6712                                 {
6713                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6714                                 }
6715                                 else
6716                                 {
6717                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6718                                 }
6719                         }
6720                 }
6721                 else
6722                 {
6723                         // remove GLSL gamma texture
6724                 }
6725                 break;
6726         case RENDERPATH_GL11:
6727         case RENDERPATH_GL13:
6728         case RENDERPATH_GLES1:
6729                 break;
6730         }
6731 }
6732
6733 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6734 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6735 /*
6736 ================
6737 R_SelectScene
6738 ================
6739 */
6740 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6741         if( scenetype != r_currentscenetype ) {
6742                 // store the old scenetype
6743                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6744                 r_currentscenetype = scenetype;
6745                 // move in the new scene
6746                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6747         }
6748 }
6749
6750 /*
6751 ================
6752 R_GetScenePointer
6753 ================
6754 */
6755 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6756 {
6757         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6758         if( scenetype == r_currentscenetype ) {
6759                 return &r_refdef.scene;
6760         } else {
6761                 return &r_scenes_store[ scenetype ];
6762         }
6763 }
6764
6765 int R_SortEntities_Compare(const void *ap, const void *bp)
6766 {
6767         const entity_render_t *a = *(const entity_render_t **)ap;
6768         const entity_render_t *b = *(const entity_render_t **)bp;
6769
6770         // 1. compare model
6771         if(a->model < b->model)
6772                 return -1;
6773         if(a->model > b->model)
6774                 return +1;
6775
6776         // 2. compare skin
6777         // TODO possibly calculate the REAL skinnum here first using
6778         // skinscenes?
6779         if(a->skinnum < b->skinnum)
6780                 return -1;
6781         if(a->skinnum > b->skinnum)
6782                 return +1;
6783
6784         // everything we compared is equal
6785         return 0;
6786 }
6787 void R_SortEntities(void)
6788 {
6789         // below or equal 2 ents, sorting never gains anything
6790         if(r_refdef.scene.numentities <= 2)
6791                 return;
6792         // sort
6793         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6794 }
6795
6796 /*
6797 ================
6798 R_RenderView
6799 ================
6800 */
6801 int dpsoftrast_test;
6802 extern void R_Shadow_UpdateBounceGridTexture(void);
6803 extern cvar_t r_shadow_bouncegrid;
6804 void R_RenderView(void)
6805 {
6806         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6807
6808         dpsoftrast_test = r_test.integer;
6809
6810         if (r_timereport_active)
6811                 R_TimeReport("start");
6812         r_textureframe++; // used only by R_GetCurrentTexture
6813         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6814
6815         if(R_CompileShader_CheckStaticParms())
6816                 R_GLSL_Restart_f();
6817
6818         if (!r_drawentities.integer)
6819                 r_refdef.scene.numentities = 0;
6820         else if (r_sortentities.integer)
6821                 R_SortEntities();
6822
6823         R_AnimCache_ClearCache();
6824         R_FrameData_NewFrame();
6825
6826         /* adjust for stereo display */
6827         if(R_Stereo_Active())
6828         {
6829                 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);
6830                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6831         }
6832
6833         if (r_refdef.view.isoverlay)
6834         {
6835                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6836                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6837                 R_TimeReport("depthclear");
6838
6839                 r_refdef.view.showdebug = false;
6840
6841                 r_waterstate.enabled = false;
6842                 r_waterstate.numwaterplanes = 0;
6843
6844                 R_RenderScene();
6845
6846                 r_refdef.view.matrix = originalmatrix;
6847
6848                 CHECKGLERROR
6849                 return;
6850         }
6851
6852         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6853         {
6854                 r_refdef.view.matrix = originalmatrix;
6855                 return; //Host_Error ("R_RenderView: NULL worldmodel");
6856         }
6857
6858         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6859
6860         R_RenderView_UpdateViewVectors();
6861
6862         R_Shadow_UpdateWorldLightSelection();
6863
6864         R_Bloom_StartFrame();
6865         R_Water_StartFrame();
6866
6867         CHECKGLERROR
6868         if (r_timereport_active)
6869                 R_TimeReport("viewsetup");
6870
6871         R_ResetViewRendering3D();
6872
6873         if (r_refdef.view.clear || r_refdef.fogenabled)
6874         {
6875                 R_ClearScreen(r_refdef.fogenabled);
6876                 if (r_timereport_active)
6877                         R_TimeReport("viewclear");
6878         }
6879         r_refdef.view.clear = true;
6880
6881         // this produces a bloom texture to be used in R_BlendView() later
6882         if (r_bloomstate.hdr)
6883         {
6884                 R_HDR_RenderBloomTexture();
6885                 // we have to bump the texture frame again because r_refdef.view.colorscale is cached in the textures
6886                 r_textureframe++; // used only by R_GetCurrentTexture
6887         }
6888
6889         r_refdef.view.showdebug = true;
6890
6891         R_View_Update();
6892         if (r_timereport_active)
6893                 R_TimeReport("visibility");
6894
6895         R_Shadow_UpdateBounceGridTexture();
6896         if (r_timereport_active && r_shadow_bouncegrid.integer)
6897                 R_TimeReport("bouncegrid");
6898
6899         r_waterstate.numwaterplanes = 0;
6900         if (r_waterstate.enabled)
6901                 R_RenderWaterPlanes();
6902
6903         R_RenderScene();
6904         r_waterstate.numwaterplanes = 0;
6905
6906         R_BlendView();
6907         if (r_timereport_active)
6908                 R_TimeReport("blendview");
6909
6910         GL_Scissor(0, 0, vid.width, vid.height);
6911         GL_ScissorTest(false);
6912
6913         r_refdef.view.matrix = originalmatrix;
6914
6915         CHECKGLERROR
6916 }
6917
6918 void R_RenderWaterPlanes(void)
6919 {
6920         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6921         {
6922                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6923                 if (r_timereport_active)
6924                         R_TimeReport("waterworld");
6925         }
6926
6927         // don't let sound skip if going slow
6928         if (r_refdef.scene.extraupdate)
6929                 S_ExtraUpdate ();
6930
6931         R_DrawModelsAddWaterPlanes();
6932         if (r_timereport_active)
6933                 R_TimeReport("watermodels");
6934
6935         if (r_waterstate.numwaterplanes)
6936         {
6937                 R_Water_ProcessPlanes();
6938                 if (r_timereport_active)
6939                         R_TimeReport("waterscenes");
6940         }
6941 }
6942
6943 extern void R_DrawLightningBeams (void);
6944 extern void VM_CL_AddPolygonsToMeshQueue (void);
6945 extern void R_DrawPortals (void);
6946 extern cvar_t cl_locs_show;
6947 static void R_DrawLocs(void);
6948 static void R_DrawEntityBBoxes(void);
6949 static void R_DrawModelDecals(void);
6950 extern void R_DrawModelShadows(void);
6951 extern void R_DrawModelShadowMaps(void);
6952 extern cvar_t cl_decals_newsystem;
6953 extern qboolean r_shadow_usingdeferredprepass;
6954 void R_RenderScene(void)
6955 {
6956         qboolean shadowmapping = false;
6957
6958         if (r_timereport_active)
6959                 R_TimeReport("beginscene");
6960
6961         r_refdef.stats.renders++;
6962
6963         R_UpdateFogColor();
6964
6965         // don't let sound skip if going slow
6966         if (r_refdef.scene.extraupdate)
6967                 S_ExtraUpdate ();
6968
6969         R_MeshQueue_BeginScene();
6970
6971         R_SkyStartFrame();
6972
6973         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);
6974
6975         if (r_timereport_active)
6976                 R_TimeReport("skystartframe");
6977
6978         if (cl.csqc_vidvars.drawworld)
6979         {
6980                 // don't let sound skip if going slow
6981                 if (r_refdef.scene.extraupdate)
6982                         S_ExtraUpdate ();
6983
6984                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6985                 {
6986                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6987                         if (r_timereport_active)
6988                                 R_TimeReport("worldsky");
6989                 }
6990
6991                 if (R_DrawBrushModelsSky() && r_timereport_active)
6992                         R_TimeReport("bmodelsky");
6993
6994                 if (skyrendermasked && skyrenderlater)
6995                 {
6996                         // we have to force off the water clipping plane while rendering sky
6997                         R_SetupView(false);
6998                         R_Sky();
6999                         R_SetupView(true);
7000                         if (r_timereport_active)
7001                                 R_TimeReport("sky");
7002                 }
7003         }
7004
7005         R_AnimCache_CacheVisibleEntities();
7006         if (r_timereport_active)
7007                 R_TimeReport("animation");
7008
7009         R_Shadow_PrepareLights();
7010         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7011                 R_Shadow_PrepareModelShadows();
7012         if (r_timereport_active)
7013                 R_TimeReport("preparelights");
7014
7015         if (R_Shadow_ShadowMappingEnabled())
7016                 shadowmapping = true;
7017
7018         if (r_shadow_usingdeferredprepass)
7019                 R_Shadow_DrawPrepass();
7020
7021         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7022         {
7023                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7024                 if (r_timereport_active)
7025                         R_TimeReport("worlddepth");
7026         }
7027         if (r_depthfirst.integer >= 2)
7028         {
7029                 R_DrawModelsDepth();
7030                 if (r_timereport_active)
7031                         R_TimeReport("modeldepth");
7032         }
7033
7034         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7035         {
7036                 R_DrawModelShadowMaps();
7037                 R_ResetViewRendering3D();
7038                 // don't let sound skip if going slow
7039                 if (r_refdef.scene.extraupdate)
7040                         S_ExtraUpdate ();
7041         }
7042
7043         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7044         {
7045                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7046                 if (r_timereport_active)
7047                         R_TimeReport("world");
7048         }
7049
7050         // don't let sound skip if going slow
7051         if (r_refdef.scene.extraupdate)
7052                 S_ExtraUpdate ();
7053
7054         R_DrawModels();
7055         if (r_timereport_active)
7056                 R_TimeReport("models");
7057
7058         // don't let sound skip if going slow
7059         if (r_refdef.scene.extraupdate)
7060                 S_ExtraUpdate ();
7061
7062         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7063         {
7064                 R_DrawModelShadows();
7065                 R_ResetViewRendering3D();
7066                 // don't let sound skip if going slow
7067                 if (r_refdef.scene.extraupdate)
7068                         S_ExtraUpdate ();
7069         }
7070
7071         if (!r_shadow_usingdeferredprepass)
7072         {
7073                 R_Shadow_DrawLights();
7074                 if (r_timereport_active)
7075                         R_TimeReport("rtlights");
7076         }
7077
7078         // don't let sound skip if going slow
7079         if (r_refdef.scene.extraupdate)
7080                 S_ExtraUpdate ();
7081
7082         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7083         {
7084                 R_DrawModelShadows();
7085                 R_ResetViewRendering3D();
7086                 // don't let sound skip if going slow
7087                 if (r_refdef.scene.extraupdate)
7088                         S_ExtraUpdate ();
7089         }
7090
7091         if (cl.csqc_vidvars.drawworld)
7092         {
7093                 if (cl_decals_newsystem.integer)
7094                 {
7095                         R_DrawModelDecals();
7096                         if (r_timereport_active)
7097                                 R_TimeReport("modeldecals");
7098                 }
7099                 else
7100                 {
7101                         R_DrawDecals();
7102                         if (r_timereport_active)
7103                                 R_TimeReport("decals");
7104                 }
7105
7106                 R_DrawParticles();
7107                 if (r_timereport_active)
7108                         R_TimeReport("particles");
7109
7110                 R_DrawExplosions();
7111                 if (r_timereport_active)
7112                         R_TimeReport("explosions");
7113
7114                 R_DrawLightningBeams();
7115                 if (r_timereport_active)
7116                         R_TimeReport("lightning");
7117         }
7118
7119         VM_CL_AddPolygonsToMeshQueue();
7120
7121         if (r_refdef.view.showdebug)
7122         {
7123                 if (cl_locs_show.integer)
7124                 {
7125                         R_DrawLocs();
7126                         if (r_timereport_active)
7127                                 R_TimeReport("showlocs");
7128                 }
7129
7130                 if (r_drawportals.integer)
7131                 {
7132                         R_DrawPortals();
7133                         if (r_timereport_active)
7134                                 R_TimeReport("portals");
7135                 }
7136
7137                 if (r_showbboxes.value > 0)
7138                 {
7139                         R_DrawEntityBBoxes();
7140                         if (r_timereport_active)
7141                                 R_TimeReport("bboxes");
7142                 }
7143         }
7144
7145         if (r_transparent.integer)
7146         {
7147                 R_MeshQueue_RenderTransparent();
7148                 if (r_timereport_active)
7149                         R_TimeReport("drawtrans");
7150         }
7151
7152         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))
7153         {
7154                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7155                 if (r_timereport_active)
7156                         R_TimeReport("worlddebug");
7157                 R_DrawModelsDebug();
7158                 if (r_timereport_active)
7159                         R_TimeReport("modeldebug");
7160         }
7161
7162         if (cl.csqc_vidvars.drawworld)
7163         {
7164                 R_Shadow_DrawCoronas();
7165                 if (r_timereport_active)
7166                         R_TimeReport("coronas");
7167         }
7168
7169 #if 0
7170         {
7171                 GL_DepthTest(false);
7172                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7173                 GL_Color(1, 1, 1, 1);
7174                 qglBegin(GL_POLYGON);
7175                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7176                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7177                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7178                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7179                 qglEnd();
7180                 qglBegin(GL_POLYGON);
7181                 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]);
7182                 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]);
7183                 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]);
7184                 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]);
7185                 qglEnd();
7186                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7187         }
7188 #endif
7189
7190         // don't let sound skip if going slow
7191         if (r_refdef.scene.extraupdate)
7192                 S_ExtraUpdate ();
7193
7194         R_ResetViewRendering2D();
7195 }
7196
7197 static const unsigned short bboxelements[36] =
7198 {
7199         5, 1, 3, 5, 3, 7,
7200         6, 2, 0, 6, 0, 4,
7201         7, 3, 2, 7, 2, 6,
7202         4, 0, 1, 4, 1, 5,
7203         4, 5, 7, 4, 7, 6,
7204         1, 0, 2, 1, 2, 3,
7205 };
7206
7207 void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7208 {
7209         int i;
7210         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7211
7212         RSurf_ActiveWorldEntity();
7213
7214         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7215         GL_DepthMask(false);
7216         GL_DepthRange(0, 1);
7217         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7218 //      R_Mesh_ResetTextureState();
7219
7220         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7221         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7222         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7223         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7224         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7225         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7226         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7227         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7228         R_FillColors(color4f, 8, cr, cg, cb, ca);
7229         if (r_refdef.fogenabled)
7230         {
7231                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7232                 {
7233                         f1 = RSurf_FogVertex(v);
7234                         f2 = 1 - f1;
7235                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7236                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7237                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7238                 }
7239         }
7240         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7241         R_Mesh_ResetTextureState();
7242         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7243         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7244 }
7245
7246 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7247 {
7248         int i;
7249         float color[4];
7250         prvm_edict_t *edict;
7251         prvm_prog_t *prog_save = prog;
7252
7253         // this function draws bounding boxes of server entities
7254         if (!sv.active)
7255                 return;
7256
7257         GL_CullFace(GL_NONE);
7258         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7259
7260         prog = 0;
7261         SV_VM_Begin();
7262         for (i = 0;i < numsurfaces;i++)
7263         {
7264                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7265                 switch ((int)PRVM_serveredictfloat(edict, solid))
7266                 {
7267                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7268                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7269                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7270                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7271                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7272                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7273                 }
7274                 color[3] *= r_showbboxes.value;
7275                 color[3] = bound(0, color[3], 1);
7276                 GL_DepthTest(!r_showdisabledepthtest.integer);
7277                 GL_CullFace(r_refdef.view.cullface_front);
7278                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7279         }
7280         SV_VM_End();
7281         prog = prog_save;
7282 }
7283
7284 static void R_DrawEntityBBoxes(void)
7285 {
7286         int i;
7287         prvm_edict_t *edict;
7288         vec3_t center;
7289         prvm_prog_t *prog_save = prog;
7290
7291         // this function draws bounding boxes of server entities
7292         if (!sv.active)
7293                 return;
7294
7295         prog = 0;
7296         SV_VM_Begin();
7297         for (i = 0;i < prog->num_edicts;i++)
7298         {
7299                 edict = PRVM_EDICT_NUM(i);
7300                 if (edict->priv.server->free)
7301                         continue;
7302                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7303                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7304                         continue;
7305                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7306                         continue;
7307                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7308                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7309         }
7310         SV_VM_End();
7311         prog = prog_save;
7312 }
7313
7314 static const int nomodelelement3i[24] =
7315 {
7316         5, 2, 0,
7317         5, 1, 2,
7318         5, 0, 3,
7319         5, 3, 1,
7320         0, 2, 4,
7321         2, 1, 4,
7322         3, 0, 4,
7323         1, 3, 4
7324 };
7325
7326 static const unsigned short nomodelelement3s[24] =
7327 {
7328         5, 2, 0,
7329         5, 1, 2,
7330         5, 0, 3,
7331         5, 3, 1,
7332         0, 2, 4,
7333         2, 1, 4,
7334         3, 0, 4,
7335         1, 3, 4
7336 };
7337
7338 static const float nomodelvertex3f[6*3] =
7339 {
7340         -16,   0,   0,
7341          16,   0,   0,
7342           0, -16,   0,
7343           0,  16,   0,
7344           0,   0, -16,
7345           0,   0,  16
7346 };
7347
7348 static const float nomodelcolor4f[6*4] =
7349 {
7350         0.0f, 0.0f, 0.5f, 1.0f,
7351         0.0f, 0.0f, 0.5f, 1.0f,
7352         0.0f, 0.5f, 0.0f, 1.0f,
7353         0.0f, 0.5f, 0.0f, 1.0f,
7354         0.5f, 0.0f, 0.0f, 1.0f,
7355         0.5f, 0.0f, 0.0f, 1.0f
7356 };
7357
7358 void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7359 {
7360         int i;
7361         float f1, f2, *c;
7362         float color4f[6*4];
7363
7364         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);
7365
7366         // this is only called once per entity so numsurfaces is always 1, and
7367         // surfacelist is always {0}, so this code does not handle batches
7368
7369         if (rsurface.ent_flags & RENDER_ADDITIVE)
7370         {
7371                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7372                 GL_DepthMask(false);
7373         }
7374         else if (rsurface.colormod[3] < 1)
7375         {
7376                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7377                 GL_DepthMask(false);
7378         }
7379         else
7380         {
7381                 GL_BlendFunc(GL_ONE, GL_ZERO);
7382                 GL_DepthMask(true);
7383         }
7384         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7385         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7386         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7387         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7388         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7389         for (i = 0, c = color4f;i < 6;i++, c += 4)
7390         {
7391                 c[0] *= rsurface.colormod[0];
7392                 c[1] *= rsurface.colormod[1];
7393                 c[2] *= rsurface.colormod[2];
7394                 c[3] *= rsurface.colormod[3];
7395         }
7396         if (r_refdef.fogenabled)
7397         {
7398                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7399                 {
7400                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7401                         f2 = 1 - f1;
7402                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7403                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7404                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7405                 }
7406         }
7407 //      R_Mesh_ResetTextureState();
7408         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
7409         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7410         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7411 }
7412
7413 void R_DrawNoModel(entity_render_t *ent)
7414 {
7415         vec3_t org;
7416         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7417         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7418                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7419         else
7420                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7421 }
7422
7423 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7424 {
7425         vec3_t right1, right2, diff, normal;
7426
7427         VectorSubtract (org2, org1, normal);
7428
7429         // calculate 'right' vector for start
7430         VectorSubtract (r_refdef.view.origin, org1, diff);
7431         CrossProduct (normal, diff, right1);
7432         VectorNormalize (right1);
7433
7434         // calculate 'right' vector for end
7435         VectorSubtract (r_refdef.view.origin, org2, diff);
7436         CrossProduct (normal, diff, right2);
7437         VectorNormalize (right2);
7438
7439         vert[ 0] = org1[0] + width * right1[0];
7440         vert[ 1] = org1[1] + width * right1[1];
7441         vert[ 2] = org1[2] + width * right1[2];
7442         vert[ 3] = org1[0] - width * right1[0];
7443         vert[ 4] = org1[1] - width * right1[1];
7444         vert[ 5] = org1[2] - width * right1[2];
7445         vert[ 6] = org2[0] - width * right2[0];
7446         vert[ 7] = org2[1] - width * right2[1];
7447         vert[ 8] = org2[2] - width * right2[2];
7448         vert[ 9] = org2[0] + width * right2[0];
7449         vert[10] = org2[1] + width * right2[1];
7450         vert[11] = org2[2] + width * right2[2];
7451 }
7452
7453 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)
7454 {
7455         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7456         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7457         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7458         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7459         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7460         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7461         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7462         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7463         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7464         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7465         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7466         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7467 }
7468
7469 int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7470 {
7471         int i;
7472         float *vertex3f;
7473         float v[3];
7474         VectorSet(v, x, y, z);
7475         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7476                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7477                         break;
7478         if (i == mesh->numvertices)
7479         {
7480                 if (mesh->numvertices < mesh->maxvertices)
7481                 {
7482                         VectorCopy(v, vertex3f);
7483                         mesh->numvertices++;
7484                 }
7485                 return mesh->numvertices;
7486         }
7487         else
7488                 return i;
7489 }
7490
7491 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7492 {
7493         int i;
7494         int *e, element[3];
7495         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7496         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7497         e = mesh->element3i + mesh->numtriangles * 3;
7498         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7499         {
7500                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7501                 if (mesh->numtriangles < mesh->maxtriangles)
7502                 {
7503                         *e++ = element[0];
7504                         *e++ = element[1];
7505                         *e++ = element[2];
7506                         mesh->numtriangles++;
7507                 }
7508                 element[1] = element[2];
7509         }
7510 }
7511
7512 void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7513 {
7514         int i;
7515         int *e, element[3];
7516         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7517         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7518         e = mesh->element3i + mesh->numtriangles * 3;
7519         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7520         {
7521                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7522                 if (mesh->numtriangles < mesh->maxtriangles)
7523                 {
7524                         *e++ = element[0];
7525                         *e++ = element[1];
7526                         *e++ = element[2];
7527                         mesh->numtriangles++;
7528                 }
7529                 element[1] = element[2];
7530         }
7531 }
7532
7533 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7534 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7535 {
7536         int planenum, planenum2;
7537         int w;
7538         int tempnumpoints;
7539         mplane_t *plane, *plane2;
7540         double maxdist;
7541         double temppoints[2][256*3];
7542         // figure out how large a bounding box we need to properly compute this brush
7543         maxdist = 0;
7544         for (w = 0;w < numplanes;w++)
7545                 maxdist = max(maxdist, fabs(planes[w].dist));
7546         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7547         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7548         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7549         {
7550                 w = 0;
7551                 tempnumpoints = 4;
7552                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7553                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7554                 {
7555                         if (planenum2 == planenum)
7556                                 continue;
7557                         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);
7558                         w = !w;
7559                 }
7560                 if (tempnumpoints < 3)
7561                         continue;
7562                 // generate elements forming a triangle fan for this polygon
7563                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7564         }
7565 }
7566
7567 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)
7568 {
7569         texturelayer_t *layer;
7570         layer = t->currentlayers + t->currentnumlayers++;
7571         layer->type = type;
7572         layer->depthmask = depthmask;
7573         layer->blendfunc1 = blendfunc1;
7574         layer->blendfunc2 = blendfunc2;
7575         layer->texture = texture;
7576         layer->texmatrix = *matrix;
7577         layer->color[0] = r;
7578         layer->color[1] = g;
7579         layer->color[2] = b;
7580         layer->color[3] = a;
7581 }
7582
7583 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7584 {
7585         if(parms[0] == 0 && parms[1] == 0)
7586                 return false;
7587         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7588                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7589                         return false;
7590         return true;
7591 }
7592
7593 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7594 {
7595         double index, f;
7596         index = parms[2] + rsurface.shadertime * parms[3];
7597         index -= floor(index);
7598         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7599         {
7600         default:
7601         case Q3WAVEFUNC_NONE:
7602         case Q3WAVEFUNC_NOISE:
7603         case Q3WAVEFUNC_COUNT:
7604                 f = 0;
7605                 break;
7606         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7607         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7608         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7609         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7610         case Q3WAVEFUNC_TRIANGLE:
7611                 index *= 4;
7612                 f = index - floor(index);
7613                 if (index < 1)
7614                 {
7615                         // f = f;
7616                 }
7617                 else if (index < 2)
7618                         f = 1 - f;
7619                 else if (index < 3)
7620                         f = -f;
7621                 else
7622                         f = -(1 - f);
7623                 break;
7624         }
7625         f = parms[0] + parms[1] * f;
7626         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7627                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7628         return (float) f;
7629 }
7630
7631 void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7632 {
7633         int w, h, idx;
7634         double f;
7635         double offsetd[2];
7636         float tcmat[12];
7637         matrix4x4_t matrix, temp;
7638         switch(tcmod->tcmod)
7639         {
7640                 case Q3TCMOD_COUNT:
7641                 case Q3TCMOD_NONE:
7642                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7643                                 matrix = r_waterscrollmatrix;
7644                         else
7645                                 matrix = identitymatrix;
7646                         break;
7647                 case Q3TCMOD_ENTITYTRANSLATE:
7648                         // this is used in Q3 to allow the gamecode to control texcoord
7649                         // scrolling on the entity, which is not supported in darkplaces yet.
7650                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7651                         break;
7652                 case Q3TCMOD_ROTATE:
7653                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7654                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
7655                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7656                         break;
7657                 case Q3TCMOD_SCALE:
7658                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7659                         break;
7660                 case Q3TCMOD_SCROLL:
7661                         // extra care is needed because of precision breakdown with large values of time
7662                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7663                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7664                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7665                         break;
7666                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7667                         w = (int) tcmod->parms[0];
7668                         h = (int) tcmod->parms[1];
7669                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7670                         f = f - floor(f);
7671                         idx = (int) floor(f * w * h);
7672                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7673                         break;
7674                 case Q3TCMOD_STRETCH:
7675                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7676                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7677                         break;
7678                 case Q3TCMOD_TRANSFORM:
7679                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7680                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7681                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7682                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7683                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7684                         break;
7685                 case Q3TCMOD_TURBULENT:
7686                         // this is handled in the RSurf_PrepareVertices function
7687                         matrix = identitymatrix;
7688                         break;
7689         }
7690         temp = *texmatrix;
7691         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7692 }
7693
7694 void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7695 {
7696         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7697         char name[MAX_QPATH];
7698         skinframe_t *skinframe;
7699         unsigned char pixels[296*194];
7700         strlcpy(cache->name, skinname, sizeof(cache->name));
7701         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7702         if (developer_loading.integer)
7703                 Con_Printf("loading %s\n", name);
7704         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7705         if (!skinframe || !skinframe->base)
7706         {
7707                 unsigned char *f;
7708                 fs_offset_t filesize;
7709                 skinframe = NULL;
7710                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7711                 if (f)
7712                 {
7713                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7714                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7715                         Mem_Free(f);
7716                 }
7717         }
7718         cache->skinframe = skinframe;
7719 }
7720
7721 texture_t *R_GetCurrentTexture(texture_t *t)
7722 {
7723         int i;
7724         const entity_render_t *ent = rsurface.entity;
7725         dp_model_t *model = ent->model;
7726         q3shaderinfo_layer_tcmod_t *tcmod;
7727
7728         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7729                 return t->currentframe;
7730         t->update_lastrenderframe = r_textureframe;
7731         t->update_lastrenderentity = (void *)ent;
7732
7733         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7734                 t->camera_entity = ent->entitynumber;
7735         else
7736                 t->camera_entity = 0;
7737
7738         // switch to an alternate material if this is a q1bsp animated material
7739         {
7740                 texture_t *texture = t;
7741                 int s = rsurface.ent_skinnum;
7742                 if ((unsigned int)s >= (unsigned int)model->numskins)
7743                         s = 0;
7744                 if (model->skinscenes)
7745                 {
7746                         if (model->skinscenes[s].framecount > 1)
7747                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7748                         else
7749                                 s = model->skinscenes[s].firstframe;
7750                 }
7751                 if (s > 0)
7752                         t = t + s * model->num_surfaces;
7753                 if (t->animated)
7754                 {
7755                         // use an alternate animation if the entity's frame is not 0,
7756                         // and only if the texture has an alternate animation
7757                         if (rsurface.ent_alttextures && t->anim_total[1])
7758                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7759                         else
7760                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7761                 }
7762                 texture->currentframe = t;
7763         }
7764
7765         // update currentskinframe to be a qw skin or animation frame
7766         if (rsurface.ent_qwskin >= 0)
7767         {
7768                 i = rsurface.ent_qwskin;
7769                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7770                 {
7771                         r_qwskincache_size = cl.maxclients;
7772                         if (r_qwskincache)
7773                                 Mem_Free(r_qwskincache);
7774                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7775                 }
7776                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7777                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7778                 t->currentskinframe = r_qwskincache[i].skinframe;
7779                 if (t->currentskinframe == NULL)
7780                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7781         }
7782         else if (t->numskinframes >= 2)
7783                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7784         if (t->backgroundnumskinframes >= 2)
7785                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7786
7787         t->currentmaterialflags = t->basematerialflags;
7788         t->currentalpha = rsurface.colormod[3];
7789         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7790                 t->currentalpha *= r_wateralpha.value;
7791         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_waterstate.enabled && !r_refdef.view.isoverlay)
7792                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7793         if(!r_waterstate.enabled || r_refdef.view.isoverlay)
7794                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7795         if (!(rsurface.ent_flags & RENDER_LIGHT))
7796                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7797         else if (FAKELIGHT_ENABLED)
7798         {
7799                 // no modellight if using fakelight for the map
7800         }
7801         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7802         {
7803                 // pick a model lighting mode
7804                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7805                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7806                 else
7807                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7808         }
7809         if (rsurface.ent_flags & RENDER_ADDITIVE)
7810                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7811         else if (t->currentalpha < 1)
7812                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7813         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7814                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7815         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7816                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7817         if (t->backgroundnumskinframes)
7818                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7819         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7820         {
7821                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7822                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7823         }
7824         else
7825                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7826         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7827         {
7828                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7829                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7830         }
7831         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7832                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7833
7834         // there is no tcmod
7835         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7836         {
7837                 t->currenttexmatrix = r_waterscrollmatrix;
7838                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7839         }
7840         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7841         {
7842                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7843                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7844         }
7845
7846         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7847                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7848         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7849                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7850
7851         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7852         if (t->currentskinframe->qpixels)
7853                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7854         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7855         if (!t->basetexture)
7856                 t->basetexture = r_texture_notexture;
7857         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7858         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7859         t->nmaptexture = t->currentskinframe->nmap;
7860         if (!t->nmaptexture)
7861                 t->nmaptexture = r_texture_blanknormalmap;
7862         t->glosstexture = r_texture_black;
7863         t->glowtexture = t->currentskinframe->glow;
7864         t->fogtexture = t->currentskinframe->fog;
7865         t->reflectmasktexture = t->currentskinframe->reflect;
7866         if (t->backgroundnumskinframes)
7867         {
7868                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7869                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7870                 t->backgroundglosstexture = r_texture_black;
7871                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7872                 if (!t->backgroundnmaptexture)
7873                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7874         }
7875         else
7876         {
7877                 t->backgroundbasetexture = r_texture_white;
7878                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7879                 t->backgroundglosstexture = r_texture_black;
7880                 t->backgroundglowtexture = NULL;
7881         }
7882         t->specularpower = r_shadow_glossexponent.value;
7883         // TODO: store reference values for these in the texture?
7884         t->specularscale = 0;
7885         if (r_shadow_gloss.integer > 0)
7886         {
7887                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7888                 {
7889                         if (r_shadow_glossintensity.value > 0)
7890                         {
7891                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7892                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7893                                 t->specularscale = r_shadow_glossintensity.value;
7894                         }
7895                 }
7896                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7897                 {
7898                         t->glosstexture = r_texture_white;
7899                         t->backgroundglosstexture = r_texture_white;
7900                         t->specularscale = r_shadow_gloss2intensity.value;
7901                         t->specularpower = r_shadow_gloss2exponent.value;
7902                 }
7903         }
7904         t->specularscale *= t->specularscalemod;
7905         t->specularpower *= t->specularpowermod;
7906         t->rtlightambient = 0;
7907
7908         // lightmaps mode looks bad with dlights using actual texturing, so turn
7909         // off the colormap and glossmap, but leave the normalmap on as it still
7910         // accurately represents the shading involved
7911         if (gl_lightmaps.integer)
7912         {
7913                 t->basetexture = r_texture_grey128;
7914                 t->pantstexture = r_texture_black;
7915                 t->shirttexture = r_texture_black;
7916                 t->nmaptexture = r_texture_blanknormalmap;
7917                 t->glosstexture = r_texture_black;
7918                 t->glowtexture = NULL;
7919                 t->fogtexture = NULL;
7920                 t->reflectmasktexture = NULL;
7921                 t->backgroundbasetexture = NULL;
7922                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7923                 t->backgroundglosstexture = r_texture_black;
7924                 t->backgroundglowtexture = NULL;
7925                 t->specularscale = 0;
7926                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7927         }
7928
7929         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7930         VectorClear(t->dlightcolor);
7931         t->currentnumlayers = 0;
7932         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7933         {
7934                 int blendfunc1, blendfunc2;
7935                 qboolean depthmask;
7936                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7937                 {
7938                         blendfunc1 = GL_SRC_ALPHA;
7939                         blendfunc2 = GL_ONE;
7940                 }
7941                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7942                 {
7943                         blendfunc1 = GL_SRC_ALPHA;
7944                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7945                 }
7946                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7947                 {
7948                         blendfunc1 = t->customblendfunc[0];
7949                         blendfunc2 = t->customblendfunc[1];
7950                 }
7951                 else
7952                 {
7953                         blendfunc1 = GL_ONE;
7954                         blendfunc2 = GL_ZERO;
7955                 }
7956                 // don't colormod evilblend textures
7957                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7958                         VectorSet(t->lightmapcolor, 1, 1, 1);
7959                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7960                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7961                 {
7962                         // fullbright is not affected by r_refdef.lightmapintensity
7963                         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]);
7964                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7965                                 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]);
7966                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7967                                 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]);
7968                 }
7969                 else
7970                 {
7971                         vec3_t ambientcolor;
7972                         float colorscale;
7973                         // set the color tint used for lights affecting this surface
7974                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7975                         colorscale = 2;
7976                         // q3bsp has no lightmap updates, so the lightstylevalue that
7977                         // would normally be baked into the lightmap must be
7978                         // applied to the color
7979                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7980                         if (model->type == mod_brushq3)
7981                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7982                         colorscale *= r_refdef.lightmapintensity;
7983                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7984                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7985                         // basic lit geometry
7986                         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]);
7987                         // add pants/shirt if needed
7988                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7989                                 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]);
7990                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7991                                 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]);
7992                         // now add ambient passes if needed
7993                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7994                         {
7995                                 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]);
7996                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7997                                         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]);
7998                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7999                                         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]);
8000                         }
8001                 }
8002                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8003                         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]);
8004                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8005                 {
8006                         // if this is opaque use alpha blend which will darken the earlier
8007                         // passes cheaply.
8008                         //
8009                         // if this is an alpha blended material, all the earlier passes
8010                         // were darkened by fog already, so we only need to add the fog
8011                         // color ontop through the fog mask texture
8012                         //
8013                         // if this is an additive blended material, all the earlier passes
8014                         // were darkened by fog already, and we should not add fog color
8015                         // (because the background was not darkened, there is no fog color
8016                         // that was lost behind it).
8017                         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]);
8018                 }
8019         }
8020
8021         return t->currentframe;
8022 }
8023
8024 rsurfacestate_t rsurface;
8025
8026 void RSurf_ActiveWorldEntity(void)
8027 {
8028         dp_model_t *model = r_refdef.scene.worldmodel;
8029         //if (rsurface.entity == r_refdef.scene.worldentity)
8030         //      return;
8031         rsurface.entity = r_refdef.scene.worldentity;
8032         rsurface.skeleton = NULL;
8033         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8034         rsurface.ent_skinnum = 0;
8035         rsurface.ent_qwskin = -1;
8036         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8037         rsurface.shadertime = r_refdef.scene.time;
8038         rsurface.matrix = identitymatrix;
8039         rsurface.inversematrix = identitymatrix;
8040         rsurface.matrixscale = 1;
8041         rsurface.inversematrixscale = 1;
8042         R_EntityMatrix(&identitymatrix);
8043         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8044         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8045         rsurface.fograngerecip = r_refdef.fograngerecip;
8046         rsurface.fogheightfade = r_refdef.fogheightfade;
8047         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8048         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8049         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8050         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8051         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8052         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8053         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8054         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8055         rsurface.colormod[3] = 1;
8056         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);
8057         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8058         rsurface.frameblend[0].lerp = 1;
8059         rsurface.ent_alttextures = false;
8060         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8061         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8062         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8063         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8064         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8065         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8066         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8067         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8068         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8069         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8070         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8071         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8072         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8073         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8074         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8075         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8076         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8077         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8078         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8079         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8080         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8081         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8082         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8083         rsurface.modelelement3i = model->surfmesh.data_element3i;
8084         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8085         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8086         rsurface.modelelement3s = model->surfmesh.data_element3s;
8087         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8088         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8089         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8090         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8091         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8092         rsurface.modelsurfaces = model->data_surfaces;
8093         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8094         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8095         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8096         rsurface.modelgeneratedvertex = false;
8097         rsurface.batchgeneratedvertex = false;
8098         rsurface.batchfirstvertex = 0;
8099         rsurface.batchnumvertices = 0;
8100         rsurface.batchfirsttriangle = 0;
8101         rsurface.batchnumtriangles = 0;
8102         rsurface.batchvertex3f  = NULL;
8103         rsurface.batchvertex3f_vertexbuffer = NULL;
8104         rsurface.batchvertex3f_bufferoffset = 0;
8105         rsurface.batchsvector3f = NULL;
8106         rsurface.batchsvector3f_vertexbuffer = NULL;
8107         rsurface.batchsvector3f_bufferoffset = 0;
8108         rsurface.batchtvector3f = NULL;
8109         rsurface.batchtvector3f_vertexbuffer = NULL;
8110         rsurface.batchtvector3f_bufferoffset = 0;
8111         rsurface.batchnormal3f  = NULL;
8112         rsurface.batchnormal3f_vertexbuffer = NULL;
8113         rsurface.batchnormal3f_bufferoffset = 0;
8114         rsurface.batchlightmapcolor4f = NULL;
8115         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8116         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8117         rsurface.batchtexcoordtexture2f = NULL;
8118         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8119         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8120         rsurface.batchtexcoordlightmap2f = NULL;
8121         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8122         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8123         rsurface.batchvertexmesh = NULL;
8124         rsurface.batchvertexmeshbuffer = NULL;
8125         rsurface.batchvertex3fbuffer = NULL;
8126         rsurface.batchelement3i = NULL;
8127         rsurface.batchelement3i_indexbuffer = NULL;
8128         rsurface.batchelement3i_bufferoffset = 0;
8129         rsurface.batchelement3s = NULL;
8130         rsurface.batchelement3s_indexbuffer = NULL;
8131         rsurface.batchelement3s_bufferoffset = 0;
8132         rsurface.passcolor4f = NULL;
8133         rsurface.passcolor4f_vertexbuffer = NULL;
8134         rsurface.passcolor4f_bufferoffset = 0;
8135 }
8136
8137 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8138 {
8139         dp_model_t *model = ent->model;
8140         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8141         //      return;
8142         rsurface.entity = (entity_render_t *)ent;
8143         rsurface.skeleton = ent->skeleton;
8144         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8145         rsurface.ent_skinnum = ent->skinnum;
8146         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;
8147         rsurface.ent_flags = ent->flags;
8148         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8149         rsurface.matrix = ent->matrix;
8150         rsurface.inversematrix = ent->inversematrix;
8151         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8152         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8153         R_EntityMatrix(&rsurface.matrix);
8154         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8155         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8156         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8157         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8158         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8159         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8160         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8161         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8162         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8163         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8164         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8165         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8166         rsurface.colormod[3] = ent->alpha;
8167         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8168         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8169         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8170         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8171         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8172         if (ent->model->brush.submodel && !prepass)
8173         {
8174                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8175                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8176         }
8177         if (model->surfmesh.isanimated && model->AnimateVertices)
8178         {
8179                 if (ent->animcache_vertex3f)
8180                 {
8181                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8182                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8183                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8184                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8185                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8186                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8187                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8188                 }
8189                 else if (wanttangents)
8190                 {
8191                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8192                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8193                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8194                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8195                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8196                         rsurface.modelvertexmesh = NULL;
8197                         rsurface.modelvertexmeshbuffer = NULL;
8198                         rsurface.modelvertex3fbuffer = NULL;
8199                 }
8200                 else if (wantnormals)
8201                 {
8202                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8203                         rsurface.modelsvector3f = NULL;
8204                         rsurface.modeltvector3f = NULL;
8205                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8206                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8207                         rsurface.modelvertexmesh = NULL;
8208                         rsurface.modelvertexmeshbuffer = NULL;
8209                         rsurface.modelvertex3fbuffer = NULL;
8210                 }
8211                 else
8212                 {
8213                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8214                         rsurface.modelsvector3f = NULL;
8215                         rsurface.modeltvector3f = NULL;
8216                         rsurface.modelnormal3f = NULL;
8217                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8218                         rsurface.modelvertexmesh = NULL;
8219                         rsurface.modelvertexmeshbuffer = NULL;
8220                         rsurface.modelvertex3fbuffer = NULL;
8221                 }
8222                 rsurface.modelvertex3f_vertexbuffer = 0;
8223                 rsurface.modelvertex3f_bufferoffset = 0;
8224                 rsurface.modelsvector3f_vertexbuffer = 0;
8225                 rsurface.modelsvector3f_bufferoffset = 0;
8226                 rsurface.modeltvector3f_vertexbuffer = 0;
8227                 rsurface.modeltvector3f_bufferoffset = 0;
8228                 rsurface.modelnormal3f_vertexbuffer = 0;
8229                 rsurface.modelnormal3f_bufferoffset = 0;
8230                 rsurface.modelgeneratedvertex = true;
8231         }
8232         else
8233         {
8234                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8235                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8236                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8237                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8238                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8239                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8240                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8241                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8242                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8243                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8244                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8245                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8246                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8247                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8248                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8249                 rsurface.modelgeneratedvertex = false;
8250         }
8251         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8252         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8253         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8254         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8255         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8256         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8257         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8258         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8259         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8260         rsurface.modelelement3i = model->surfmesh.data_element3i;
8261         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8262         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8263         rsurface.modelelement3s = model->surfmesh.data_element3s;
8264         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8265         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8266         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8267         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8268         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8269         rsurface.modelsurfaces = model->data_surfaces;
8270         rsurface.batchgeneratedvertex = false;
8271         rsurface.batchfirstvertex = 0;
8272         rsurface.batchnumvertices = 0;
8273         rsurface.batchfirsttriangle = 0;
8274         rsurface.batchnumtriangles = 0;
8275         rsurface.batchvertex3f  = NULL;
8276         rsurface.batchvertex3f_vertexbuffer = NULL;
8277         rsurface.batchvertex3f_bufferoffset = 0;
8278         rsurface.batchsvector3f = NULL;
8279         rsurface.batchsvector3f_vertexbuffer = NULL;
8280         rsurface.batchsvector3f_bufferoffset = 0;
8281         rsurface.batchtvector3f = NULL;
8282         rsurface.batchtvector3f_vertexbuffer = NULL;
8283         rsurface.batchtvector3f_bufferoffset = 0;
8284         rsurface.batchnormal3f  = NULL;
8285         rsurface.batchnormal3f_vertexbuffer = NULL;
8286         rsurface.batchnormal3f_bufferoffset = 0;
8287         rsurface.batchlightmapcolor4f = NULL;
8288         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8289         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8290         rsurface.batchtexcoordtexture2f = NULL;
8291         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8292         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8293         rsurface.batchtexcoordlightmap2f = NULL;
8294         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8295         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8296         rsurface.batchvertexmesh = NULL;
8297         rsurface.batchvertexmeshbuffer = NULL;
8298         rsurface.batchvertex3fbuffer = NULL;
8299         rsurface.batchelement3i = NULL;
8300         rsurface.batchelement3i_indexbuffer = NULL;
8301         rsurface.batchelement3i_bufferoffset = 0;
8302         rsurface.batchelement3s = NULL;
8303         rsurface.batchelement3s_indexbuffer = NULL;
8304         rsurface.batchelement3s_bufferoffset = 0;
8305         rsurface.passcolor4f = NULL;
8306         rsurface.passcolor4f_vertexbuffer = NULL;
8307         rsurface.passcolor4f_bufferoffset = 0;
8308 }
8309
8310 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)
8311 {
8312         rsurface.entity = r_refdef.scene.worldentity;
8313         rsurface.skeleton = NULL;
8314         rsurface.ent_skinnum = 0;
8315         rsurface.ent_qwskin = -1;
8316         rsurface.ent_flags = entflags;
8317         rsurface.shadertime = r_refdef.scene.time - shadertime;
8318         rsurface.modelnumvertices = numvertices;
8319         rsurface.modelnumtriangles = numtriangles;
8320         rsurface.matrix = *matrix;
8321         rsurface.inversematrix = *inversematrix;
8322         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8323         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8324         R_EntityMatrix(&rsurface.matrix);
8325         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8326         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8327         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8328         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8329         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8330         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8331         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8332         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8333         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8334         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8335         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8336         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8337         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);
8338         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8339         rsurface.frameblend[0].lerp = 1;
8340         rsurface.ent_alttextures = false;
8341         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8342         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8343         if (wanttangents)
8344         {
8345                 rsurface.modelvertex3f = (float *)vertex3f;
8346                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8347                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8348                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8349         }
8350         else if (wantnormals)
8351         {
8352                 rsurface.modelvertex3f = (float *)vertex3f;
8353                 rsurface.modelsvector3f = NULL;
8354                 rsurface.modeltvector3f = NULL;
8355                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8356         }
8357         else
8358         {
8359                 rsurface.modelvertex3f = (float *)vertex3f;
8360                 rsurface.modelsvector3f = NULL;
8361                 rsurface.modeltvector3f = NULL;
8362                 rsurface.modelnormal3f = NULL;
8363         }
8364         rsurface.modelvertexmesh = NULL;
8365         rsurface.modelvertexmeshbuffer = NULL;
8366         rsurface.modelvertex3fbuffer = NULL;
8367         rsurface.modelvertex3f_vertexbuffer = 0;
8368         rsurface.modelvertex3f_bufferoffset = 0;
8369         rsurface.modelsvector3f_vertexbuffer = 0;
8370         rsurface.modelsvector3f_bufferoffset = 0;
8371         rsurface.modeltvector3f_vertexbuffer = 0;
8372         rsurface.modeltvector3f_bufferoffset = 0;
8373         rsurface.modelnormal3f_vertexbuffer = 0;
8374         rsurface.modelnormal3f_bufferoffset = 0;
8375         rsurface.modelgeneratedvertex = true;
8376         rsurface.modellightmapcolor4f  = (float *)color4f;
8377         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8378         rsurface.modellightmapcolor4f_bufferoffset = 0;
8379         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8380         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8381         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8382         rsurface.modeltexcoordlightmap2f  = NULL;
8383         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8384         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8385         rsurface.modelelement3i = (int *)element3i;
8386         rsurface.modelelement3i_indexbuffer = NULL;
8387         rsurface.modelelement3i_bufferoffset = 0;
8388         rsurface.modelelement3s = (unsigned short *)element3s;
8389         rsurface.modelelement3s_indexbuffer = NULL;
8390         rsurface.modelelement3s_bufferoffset = 0;
8391         rsurface.modellightmapoffsets = NULL;
8392         rsurface.modelsurfaces = NULL;
8393         rsurface.batchgeneratedvertex = false;
8394         rsurface.batchfirstvertex = 0;
8395         rsurface.batchnumvertices = 0;
8396         rsurface.batchfirsttriangle = 0;
8397         rsurface.batchnumtriangles = 0;
8398         rsurface.batchvertex3f  = NULL;
8399         rsurface.batchvertex3f_vertexbuffer = NULL;
8400         rsurface.batchvertex3f_bufferoffset = 0;
8401         rsurface.batchsvector3f = NULL;
8402         rsurface.batchsvector3f_vertexbuffer = NULL;
8403         rsurface.batchsvector3f_bufferoffset = 0;
8404         rsurface.batchtvector3f = NULL;
8405         rsurface.batchtvector3f_vertexbuffer = NULL;
8406         rsurface.batchtvector3f_bufferoffset = 0;
8407         rsurface.batchnormal3f  = NULL;
8408         rsurface.batchnormal3f_vertexbuffer = NULL;
8409         rsurface.batchnormal3f_bufferoffset = 0;
8410         rsurface.batchlightmapcolor4f = NULL;
8411         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8412         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8413         rsurface.batchtexcoordtexture2f = NULL;
8414         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8415         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8416         rsurface.batchtexcoordlightmap2f = NULL;
8417         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8418         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8419         rsurface.batchvertexmesh = NULL;
8420         rsurface.batchvertexmeshbuffer = NULL;
8421         rsurface.batchvertex3fbuffer = NULL;
8422         rsurface.batchelement3i = NULL;
8423         rsurface.batchelement3i_indexbuffer = NULL;
8424         rsurface.batchelement3i_bufferoffset = 0;
8425         rsurface.batchelement3s = NULL;
8426         rsurface.batchelement3s_indexbuffer = NULL;
8427         rsurface.batchelement3s_bufferoffset = 0;
8428         rsurface.passcolor4f = NULL;
8429         rsurface.passcolor4f_vertexbuffer = NULL;
8430         rsurface.passcolor4f_bufferoffset = 0;
8431
8432         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8433         {
8434                 if ((wantnormals || wanttangents) && !normal3f)
8435                 {
8436                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8437                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8438                 }
8439                 if (wanttangents && !svector3f)
8440                 {
8441                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8442                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8443                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8444                 }
8445         }
8446 }
8447
8448 float RSurf_FogPoint(const float *v)
8449 {
8450         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8451         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8452         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8453         float FogHeightFade = r_refdef.fogheightfade;
8454         float fogfrac;
8455         unsigned int fogmasktableindex;
8456         if (r_refdef.fogplaneviewabove)
8457                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8458         else
8459                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8460         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8461         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8462 }
8463
8464 float RSurf_FogVertex(const float *v)
8465 {
8466         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8467         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8468         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8469         float FogHeightFade = rsurface.fogheightfade;
8470         float fogfrac;
8471         unsigned int fogmasktableindex;
8472         if (r_refdef.fogplaneviewabove)
8473                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8474         else
8475                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8476         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8477         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8478 }
8479
8480 void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8481 {
8482         int i;
8483         for (i = 0;i < numelements;i++)
8484                 outelement3i[i] = inelement3i[i] + adjust;
8485 }
8486
8487 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8488 extern cvar_t gl_vbo;
8489 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8490 {
8491         int deformindex;
8492         int firsttriangle;
8493         int numtriangles;
8494         int firstvertex;
8495         int endvertex;
8496         int numvertices;
8497         int surfacefirsttriangle;
8498         int surfacenumtriangles;
8499         int surfacefirstvertex;
8500         int surfaceendvertex;
8501         int surfacenumvertices;
8502         int batchnumvertices;
8503         int batchnumtriangles;
8504         int needsupdate;
8505         int i, j;
8506         qboolean gaps;
8507         qboolean dynamicvertex;
8508         float amplitude;
8509         float animpos;
8510         float scale;
8511         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8512         float waveparms[4];
8513         q3shaderinfo_deform_t *deform;
8514         const msurface_t *surface, *firstsurface;
8515         r_vertexmesh_t *vertexmesh;
8516         if (!texturenumsurfaces)
8517                 return;
8518         // find vertex range of this surface batch
8519         gaps = false;
8520         firstsurface = texturesurfacelist[0];
8521         firsttriangle = firstsurface->num_firsttriangle;
8522         batchnumvertices = 0;
8523         batchnumtriangles = 0;
8524         firstvertex = endvertex = firstsurface->num_firstvertex;
8525         for (i = 0;i < texturenumsurfaces;i++)
8526         {
8527                 surface = texturesurfacelist[i];
8528                 if (surface != firstsurface + i)
8529                         gaps = true;
8530                 surfacefirstvertex = surface->num_firstvertex;
8531                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8532                 surfacenumvertices = surface->num_vertices;
8533                 surfacenumtriangles = surface->num_triangles;
8534                 if (firstvertex > surfacefirstvertex)
8535                         firstvertex = surfacefirstvertex;
8536                 if (endvertex < surfaceendvertex)
8537                         endvertex = surfaceendvertex;
8538                 batchnumvertices += surfacenumvertices;
8539                 batchnumtriangles += surfacenumtriangles;
8540         }
8541
8542         // we now know the vertex range used, and if there are any gaps in it
8543         rsurface.batchfirstvertex = firstvertex;
8544         rsurface.batchnumvertices = endvertex - firstvertex;
8545         rsurface.batchfirsttriangle = firsttriangle;
8546         rsurface.batchnumtriangles = batchnumtriangles;
8547
8548         // this variable holds flags for which properties have been updated that
8549         // may require regenerating vertexmesh array...
8550         needsupdate = 0;
8551
8552         // check if any dynamic vertex processing must occur
8553         dynamicvertex = false;
8554
8555         // if there is a chance of animated vertex colors, it's a dynamic batch
8556         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8557         {
8558                 dynamicvertex = true;
8559                 batchneed |= BATCHNEED_NOGAPS;
8560                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8561         }
8562
8563         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8564         {
8565                 switch (deform->deform)
8566                 {
8567                 default:
8568                 case Q3DEFORM_PROJECTIONSHADOW:
8569                 case Q3DEFORM_TEXT0:
8570                 case Q3DEFORM_TEXT1:
8571                 case Q3DEFORM_TEXT2:
8572                 case Q3DEFORM_TEXT3:
8573                 case Q3DEFORM_TEXT4:
8574                 case Q3DEFORM_TEXT5:
8575                 case Q3DEFORM_TEXT6:
8576                 case Q3DEFORM_TEXT7:
8577                 case Q3DEFORM_NONE:
8578                         break;
8579                 case Q3DEFORM_AUTOSPRITE:
8580                         dynamicvertex = true;
8581                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8582                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8583                         break;
8584                 case Q3DEFORM_AUTOSPRITE2:
8585                         dynamicvertex = true;
8586                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8587                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8588                         break;
8589                 case Q3DEFORM_NORMAL:
8590                         dynamicvertex = true;
8591                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8592                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8593                         break;
8594                 case Q3DEFORM_WAVE:
8595                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8596                                 break; // if wavefunc is a nop, ignore this transform
8597                         dynamicvertex = true;
8598                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8599                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8600                         break;
8601                 case Q3DEFORM_BULGE:
8602                         dynamicvertex = true;
8603                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8604                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8605                         break;
8606                 case Q3DEFORM_MOVE:
8607                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8608                                 break; // if wavefunc is a nop, ignore this transform
8609                         dynamicvertex = true;
8610                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8611                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8612                         break;
8613                 }
8614         }
8615         switch(rsurface.texture->tcgen.tcgen)
8616         {
8617         default:
8618         case Q3TCGEN_TEXTURE:
8619                 break;
8620         case Q3TCGEN_LIGHTMAP:
8621                 dynamicvertex = true;
8622                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8623                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8624                 break;
8625         case Q3TCGEN_VECTOR:
8626                 dynamicvertex = true;
8627                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8628                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8629                 break;
8630         case Q3TCGEN_ENVIRONMENT:
8631                 dynamicvertex = true;
8632                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8633                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8634                 break;
8635         }
8636         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8637         {
8638                 dynamicvertex = true;
8639                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8640                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8641         }
8642
8643         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8644         {
8645                 dynamicvertex = true;
8646                 batchneed |= BATCHNEED_NOGAPS;
8647                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8648         }
8649
8650         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8651         {
8652                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8653                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8654                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8655                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8656                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8657                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8658                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8659         }
8660
8661         // when the model data has no vertex buffer (dynamic mesh), we need to
8662         // eliminate gaps
8663         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8664                 batchneed |= BATCHNEED_NOGAPS;
8665
8666         // if needsupdate, we have to do a dynamic vertex batch for sure
8667         if (needsupdate & batchneed)
8668                 dynamicvertex = true;
8669
8670         // see if we need to build vertexmesh from arrays
8671         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8672                 dynamicvertex = true;
8673
8674         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8675         // also some drivers strongly dislike firstvertex
8676         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8677                 dynamicvertex = true;
8678
8679         rsurface.batchvertex3f = rsurface.modelvertex3f;
8680         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8681         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8682         rsurface.batchsvector3f = rsurface.modelsvector3f;
8683         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8684         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8685         rsurface.batchtvector3f = rsurface.modeltvector3f;
8686         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8687         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8688         rsurface.batchnormal3f = rsurface.modelnormal3f;
8689         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8690         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8691         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8692         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8693         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8694         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8695         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8696         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8697         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8698         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8699         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8700         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8701         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8702         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8703         rsurface.batchelement3i = rsurface.modelelement3i;
8704         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8705         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8706         rsurface.batchelement3s = rsurface.modelelement3s;
8707         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8708         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8709
8710         // if any dynamic vertex processing has to occur in software, we copy the
8711         // entire surface list together before processing to rebase the vertices
8712         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8713         //
8714         // if any gaps exist and we do not have a static vertex buffer, we have to
8715         // copy the surface list together to avoid wasting upload bandwidth on the
8716         // vertices in the gaps.
8717         //
8718         // if gaps exist and we have a static vertex buffer, we still have to
8719         // combine the index buffer ranges into one dynamic index buffer.
8720         //
8721         // in all cases we end up with data that can be drawn in one call.
8722
8723         if (!dynamicvertex)
8724         {
8725                 // static vertex data, just set pointers...
8726                 rsurface.batchgeneratedvertex = false;
8727                 // if there are gaps, we want to build a combined index buffer,
8728                 // otherwise use the original static buffer with an appropriate offset
8729                 if (gaps)
8730                 {
8731                         // build a new triangle elements array for this batch
8732                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8733                         rsurface.batchfirsttriangle = 0;
8734                         numtriangles = 0;
8735                         for (i = 0;i < texturenumsurfaces;i++)
8736                         {
8737                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8738                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8739                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8740                                 numtriangles += surfacenumtriangles;
8741                         }
8742                         rsurface.batchelement3i_indexbuffer = NULL;
8743                         rsurface.batchelement3i_bufferoffset = 0;
8744                         rsurface.batchelement3s = NULL;
8745                         rsurface.batchelement3s_indexbuffer = NULL;
8746                         rsurface.batchelement3s_bufferoffset = 0;
8747                         if (endvertex <= 65536)
8748                         {
8749                                 // make a 16bit (unsigned short) index array if possible
8750                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8751                                 for (i = 0;i < numtriangles*3;i++)
8752                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8753                         }
8754                 }
8755                 return;
8756         }
8757
8758         // something needs software processing, do it for real...
8759         // we only directly handle separate array data in this case and then
8760         // generate interleaved data if needed...
8761         rsurface.batchgeneratedvertex = true;
8762
8763         // now copy the vertex data into a combined array and make an index array
8764         // (this is what Quake3 does all the time)
8765         //if (gaps || rsurface.batchfirstvertex)
8766         {
8767                 rsurface.batchvertex3fbuffer = NULL;
8768                 rsurface.batchvertexmesh = NULL;
8769                 rsurface.batchvertexmeshbuffer = NULL;
8770                 rsurface.batchvertex3f = NULL;
8771                 rsurface.batchvertex3f_vertexbuffer = NULL;
8772                 rsurface.batchvertex3f_bufferoffset = 0;
8773                 rsurface.batchsvector3f = NULL;
8774                 rsurface.batchsvector3f_vertexbuffer = NULL;
8775                 rsurface.batchsvector3f_bufferoffset = 0;
8776                 rsurface.batchtvector3f = NULL;
8777                 rsurface.batchtvector3f_vertexbuffer = NULL;
8778                 rsurface.batchtvector3f_bufferoffset = 0;
8779                 rsurface.batchnormal3f = NULL;
8780                 rsurface.batchnormal3f_vertexbuffer = NULL;
8781                 rsurface.batchnormal3f_bufferoffset = 0;
8782                 rsurface.batchlightmapcolor4f = NULL;
8783                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8784                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8785                 rsurface.batchtexcoordtexture2f = NULL;
8786                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8787                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8788                 rsurface.batchtexcoordlightmap2f = NULL;
8789                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8790                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8791                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8792                 rsurface.batchelement3i_indexbuffer = NULL;
8793                 rsurface.batchelement3i_bufferoffset = 0;
8794                 rsurface.batchelement3s = NULL;
8795                 rsurface.batchelement3s_indexbuffer = NULL;
8796                 rsurface.batchelement3s_bufferoffset = 0;
8797                 // we'll only be setting up certain arrays as needed
8798                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8799                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8800                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8801                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8802                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8803                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8804                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8805                 {
8806                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8807                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8808                 }
8809                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8810                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8811                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8812                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8813                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8814                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8815                 numvertices = 0;
8816                 numtriangles = 0;
8817                 for (i = 0;i < texturenumsurfaces;i++)
8818                 {
8819                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8820                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8821                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8822                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8823                         // copy only the data requested
8824                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8825                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8826                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8827                         {
8828                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8829                                 {
8830                                         if (rsurface.batchvertex3f)
8831                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8832                                         else
8833                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8834                                 }
8835                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8836                                 {
8837                                         if (rsurface.modelnormal3f)
8838                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8839                                         else
8840                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8841                                 }
8842                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8843                                 {
8844                                         if (rsurface.modelsvector3f)
8845                                         {
8846                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8847                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8848                                         }
8849                                         else
8850                                         {
8851                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8852                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8853                                         }
8854                                 }
8855                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8856                                 {
8857                                         if (rsurface.modellightmapcolor4f)
8858                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8859                                         else
8860                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8861                                 }
8862                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8863                                 {
8864                                         if (rsurface.modeltexcoordtexture2f)
8865                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8866                                         else
8867                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8868                                 }
8869                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8870                                 {
8871                                         if (rsurface.modeltexcoordlightmap2f)
8872                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8873                                         else
8874                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8875                                 }
8876                         }
8877                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8878                         numvertices += surfacenumvertices;
8879                         numtriangles += surfacenumtriangles;
8880                 }
8881
8882                 // generate a 16bit index array as well if possible
8883                 // (in general, dynamic batches fit)
8884                 if (numvertices <= 65536)
8885                 {
8886                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8887                         for (i = 0;i < numtriangles*3;i++)
8888                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8889                 }
8890
8891                 // since we've copied everything, the batch now starts at 0
8892                 rsurface.batchfirstvertex = 0;
8893                 rsurface.batchnumvertices = batchnumvertices;
8894                 rsurface.batchfirsttriangle = 0;
8895                 rsurface.batchnumtriangles = batchnumtriangles;
8896         }
8897
8898         // q1bsp surfaces rendered in vertex color mode have to have colors
8899         // calculated based on lightstyles
8900         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8901         {
8902                 // generate color arrays for the surfaces in this list
8903                 int c[4];
8904                 int scale;
8905                 int size3;
8906                 const int *offsets;
8907                 const unsigned char *lm;
8908                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8909                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8910                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8911                 numvertices = 0;
8912                 for (i = 0;i < texturenumsurfaces;i++)
8913                 {
8914                         surface = texturesurfacelist[i];
8915                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8916                         surfacenumvertices = surface->num_vertices;
8917                         if (surface->lightmapinfo->samples)
8918                         {
8919                                 for (j = 0;j < surfacenumvertices;j++)
8920                                 {
8921                                         lm = surface->lightmapinfo->samples + offsets[j];
8922                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8923                                         VectorScale(lm, scale, c);
8924                                         if (surface->lightmapinfo->styles[1] != 255)
8925                                         {
8926                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8927                                                 lm += size3;
8928                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8929                                                 VectorMA(c, scale, lm, c);
8930                                                 if (surface->lightmapinfo->styles[2] != 255)
8931                                                 {
8932                                                         lm += size3;
8933                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8934                                                         VectorMA(c, scale, lm, c);
8935                                                         if (surface->lightmapinfo->styles[3] != 255)
8936                                                         {
8937                                                                 lm += size3;
8938                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8939                                                                 VectorMA(c, scale, lm, c);
8940                                                         }
8941                                                 }
8942                                         }
8943                                         c[0] >>= 7;
8944                                         c[1] >>= 7;
8945                                         c[2] >>= 7;
8946                                         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);
8947                                         numvertices++;
8948                                 }
8949                         }
8950                         else
8951                         {
8952                                 for (j = 0;j < surfacenumvertices;j++)
8953                                 {
8954                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8955                                         numvertices++;
8956                                 }
8957                         }
8958                 }
8959         }
8960
8961         // if vertices are deformed (sprite flares and things in maps, possibly
8962         // water waves, bulges and other deformations), modify the copied vertices
8963         // in place
8964         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8965         {
8966                 switch (deform->deform)
8967                 {
8968                 default:
8969                 case Q3DEFORM_PROJECTIONSHADOW:
8970                 case Q3DEFORM_TEXT0:
8971                 case Q3DEFORM_TEXT1:
8972                 case Q3DEFORM_TEXT2:
8973                 case Q3DEFORM_TEXT3:
8974                 case Q3DEFORM_TEXT4:
8975                 case Q3DEFORM_TEXT5:
8976                 case Q3DEFORM_TEXT6:
8977                 case Q3DEFORM_TEXT7:
8978                 case Q3DEFORM_NONE:
8979                         break;
8980                 case Q3DEFORM_AUTOSPRITE:
8981                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8982                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8983                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8984                         VectorNormalize(newforward);
8985                         VectorNormalize(newright);
8986                         VectorNormalize(newup);
8987 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8988 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8989 //                      rsurface.batchvertex3f_bufferoffset = 0;
8990 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8991 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8992 //                      rsurface.batchsvector3f_bufferoffset = 0;
8993 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8994 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8995 //                      rsurface.batchtvector3f_bufferoffset = 0;
8996 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8997 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8998 //                      rsurface.batchnormal3f_bufferoffset = 0;
8999                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9000                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9001                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9002                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9003                                 Mod_BuildTextureVectorsFromNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchtexcoordtexture2f, rsurface.batchnormal3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchsvector3f, rsurface.batchtvector3f, r_smoothnormals_areaweighting.integer != 0);
9004                         // a single autosprite surface can contain multiple sprites...
9005                         for (j = 0;j < batchnumvertices - 3;j += 4)
9006                         {
9007                                 VectorClear(center);
9008                                 for (i = 0;i < 4;i++)
9009                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9010                                 VectorScale(center, 0.25f, center);
9011                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9012                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9013                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9014                                 for (i = 0;i < 4;i++)
9015                                 {
9016                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9017                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9018                                 }
9019                         }
9020                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9021                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9022                         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);
9023                         break;
9024                 case Q3DEFORM_AUTOSPRITE2:
9025                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9026                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9027                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9028                         VectorNormalize(newforward);
9029                         VectorNormalize(newright);
9030                         VectorNormalize(newup);
9031 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9032 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9033 //                      rsurface.batchvertex3f_bufferoffset = 0;
9034                         {
9035                                 const float *v1, *v2;
9036                                 vec3_t start, end;
9037                                 float f, l;
9038                                 struct
9039                                 {
9040                                         float length2;
9041                                         const float *v1;
9042                                         const float *v2;
9043                                 }
9044                                 shortest[2];
9045                                 memset(shortest, 0, sizeof(shortest));
9046                                 // a single autosprite surface can contain multiple sprites...
9047                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9048                                 {
9049                                         VectorClear(center);
9050                                         for (i = 0;i < 4;i++)
9051                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9052                                         VectorScale(center, 0.25f, center);
9053                                         // find the two shortest edges, then use them to define the
9054                                         // axis vectors for rotating around the central axis
9055                                         for (i = 0;i < 6;i++)
9056                                         {
9057                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9058                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9059                                                 l = VectorDistance2(v1, v2);
9060                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9061                                                 if (v1[2] != v2[2])
9062                                                         l += (1.0f / 1024.0f);
9063                                                 if (shortest[0].length2 > l || i == 0)
9064                                                 {
9065                                                         shortest[1] = shortest[0];
9066                                                         shortest[0].length2 = l;
9067                                                         shortest[0].v1 = v1;
9068                                                         shortest[0].v2 = v2;
9069                                                 }
9070                                                 else if (shortest[1].length2 > l || i == 1)
9071                                                 {
9072                                                         shortest[1].length2 = l;
9073                                                         shortest[1].v1 = v1;
9074                                                         shortest[1].v2 = v2;
9075                                                 }
9076                                         }
9077                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9078                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9079                                         // this calculates the right vector from the shortest edge
9080                                         // and the up vector from the edge midpoints
9081                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9082                                         VectorNormalize(right);
9083                                         VectorSubtract(end, start, up);
9084                                         VectorNormalize(up);
9085                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9086                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9087                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9088                                         VectorNegate(forward, forward);
9089                                         VectorReflect(forward, 0, up, forward);
9090                                         VectorNormalize(forward);
9091                                         CrossProduct(up, forward, newright);
9092                                         VectorNormalize(newright);
9093                                         // rotate the quad around the up axis vector, this is made
9094                                         // especially easy by the fact we know the quad is flat,
9095                                         // so we only have to subtract the center position and
9096                                         // measure distance along the right vector, and then
9097                                         // multiply that by the newright vector and add back the
9098                                         // center position
9099                                         // we also need to subtract the old position to undo the
9100                                         // displacement from the center, which we do with a
9101                                         // DotProduct, the subtraction/addition of center is also
9102                                         // optimized into DotProducts here
9103                                         l = DotProduct(right, center);
9104                                         for (i = 0;i < 4;i++)
9105                                         {
9106                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9107                                                 f = DotProduct(right, v1) - l;
9108                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9109                                         }
9110                                 }
9111                         }
9112                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9113                         {
9114 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9115 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9116 //                              rsurface.batchnormal3f_bufferoffset = 0;
9117                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9118                         }
9119                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9120                         {
9121 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9122 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9123 //                              rsurface.batchsvector3f_bufferoffset = 0;
9124 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9125 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9126 //                              rsurface.batchtvector3f_bufferoffset = 0;
9127                                 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);
9128                         }
9129                         break;
9130                 case Q3DEFORM_NORMAL:
9131                         // deform the normals to make reflections wavey
9132                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9133                         rsurface.batchnormal3f_vertexbuffer = NULL;
9134                         rsurface.batchnormal3f_bufferoffset = 0;
9135                         for (j = 0;j < batchnumvertices;j++)
9136                         {
9137                                 float vertex[3];
9138                                 float *normal = rsurface.batchnormal3f + 3*j;
9139                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9140                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9141                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9142                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9143                                 VectorNormalize(normal);
9144                         }
9145                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9146                         {
9147 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9148 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9149 //                              rsurface.batchsvector3f_bufferoffset = 0;
9150 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9151 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9152 //                              rsurface.batchtvector3f_bufferoffset = 0;
9153                                 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);
9154                         }
9155                         break;
9156                 case Q3DEFORM_WAVE:
9157                         // deform vertex array to make wavey water and flags and such
9158                         waveparms[0] = deform->waveparms[0];
9159                         waveparms[1] = deform->waveparms[1];
9160                         waveparms[2] = deform->waveparms[2];
9161                         waveparms[3] = deform->waveparms[3];
9162                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9163                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9164                         // this is how a divisor of vertex influence on deformation
9165                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9166                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9167 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9168 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9169 //                      rsurface.batchvertex3f_bufferoffset = 0;
9170 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9171 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9172 //                      rsurface.batchnormal3f_bufferoffset = 0;
9173                         for (j = 0;j < batchnumvertices;j++)
9174                         {
9175                                 // if the wavefunc depends on time, evaluate it per-vertex
9176                                 if (waveparms[3])
9177                                 {
9178                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9179                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9180                                 }
9181                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9182                         }
9183                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9184                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9185                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9186                         {
9187 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9188 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9189 //                              rsurface.batchsvector3f_bufferoffset = 0;
9190 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9191 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9192 //                              rsurface.batchtvector3f_bufferoffset = 0;
9193                                 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);
9194                         }
9195                         break;
9196                 case Q3DEFORM_BULGE:
9197                         // deform vertex array to make the surface have moving bulges
9198 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9199 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9200 //                      rsurface.batchvertex3f_bufferoffset = 0;
9201 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9202 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9203 //                      rsurface.batchnormal3f_bufferoffset = 0;
9204                         for (j = 0;j < batchnumvertices;j++)
9205                         {
9206                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9207                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9208                         }
9209                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9210                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9211                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9212                         {
9213 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9214 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9215 //                              rsurface.batchsvector3f_bufferoffset = 0;
9216 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9217 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9218 //                              rsurface.batchtvector3f_bufferoffset = 0;
9219                                 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);
9220                         }
9221                         break;
9222                 case Q3DEFORM_MOVE:
9223                         // deform vertex array
9224                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9225                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9226                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9227                         VectorScale(deform->parms, scale, waveparms);
9228 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9229 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9230 //                      rsurface.batchvertex3f_bufferoffset = 0;
9231                         for (j = 0;j < batchnumvertices;j++)
9232                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9233                         break;
9234                 }
9235         }
9236
9237         // generate texcoords based on the chosen texcoord source
9238         switch(rsurface.texture->tcgen.tcgen)
9239         {
9240         default:
9241         case Q3TCGEN_TEXTURE:
9242                 break;
9243         case Q3TCGEN_LIGHTMAP:
9244 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9245 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9246 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9247                 if (rsurface.batchtexcoordlightmap2f)
9248                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9249                 break;
9250         case Q3TCGEN_VECTOR:
9251 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9252 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9253 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9254                 for (j = 0;j < batchnumvertices;j++)
9255                 {
9256                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9257                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9258                 }
9259                 break;
9260         case Q3TCGEN_ENVIRONMENT:
9261                 // make environment reflections using a spheremap
9262                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9263                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9264                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9265                 for (j = 0;j < batchnumvertices;j++)
9266                 {
9267                         // identical to Q3A's method, but executed in worldspace so
9268                         // carried models can be shiny too
9269
9270                         float viewer[3], d, reflected[3], worldreflected[3];
9271
9272                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9273                         // VectorNormalize(viewer);
9274
9275                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9276
9277                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9278                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9279                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9280                         // note: this is proportinal to viewer, so we can normalize later
9281
9282                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9283                         VectorNormalize(worldreflected);
9284
9285                         // note: this sphere map only uses world x and z!
9286                         // so positive and negative y will LOOK THE SAME.
9287                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9288                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9289                 }
9290                 break;
9291         }
9292         // the only tcmod that needs software vertex processing is turbulent, so
9293         // check for it here and apply the changes if needed
9294         // and we only support that as the first one
9295         // (handling a mixture of turbulent and other tcmods would be problematic
9296         //  without punting it entirely to a software path)
9297         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9298         {
9299                 amplitude = rsurface.texture->tcmods[0].parms[1];
9300                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9301 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9302 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9303 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9304                 for (j = 0;j < batchnumvertices;j++)
9305                 {
9306                         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);
9307                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9308                 }
9309         }
9310
9311         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9312         {
9313                 // convert the modified arrays to vertex structs
9314 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9315 //              rsurface.batchvertexmeshbuffer = NULL;
9316                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9317                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9318                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9319                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9320                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9321                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9322                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9323                 {
9324                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9325                         {
9326                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9327                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9328                         }
9329                 }
9330                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9331                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9332                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9333                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9334                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9335                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9336                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9337                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9338                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9339         }
9340 }
9341
9342 void RSurf_DrawBatch(void)
9343 {
9344         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9345         // through the pipeline, killing it earlier in the pipeline would have
9346         // per-surface overhead rather than per-batch overhead, so it's best to
9347         // reject it here, before it hits glDraw.
9348         if (rsurface.batchnumtriangles == 0)
9349                 return;
9350 #if 0
9351         // batch debugging code
9352         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9353         {
9354                 int i;
9355                 int j;
9356                 int c;
9357                 const int *e;
9358                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9359                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9360                 {
9361                         c = e[i];
9362                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9363                         {
9364                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9365                                 {
9366                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9367                                                 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);
9368                                         break;
9369                                 }
9370                         }
9371                 }
9372         }
9373 #endif
9374         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);
9375 }
9376
9377 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9378 {
9379         // pick the closest matching water plane
9380         int planeindex, vertexindex, bestplaneindex = -1;
9381         float d, bestd;
9382         vec3_t vert;
9383         const float *v;
9384         r_waterstate_waterplane_t *p;
9385         qboolean prepared = false;
9386         bestd = 0;
9387         for (planeindex = 0, p = r_waterstate.waterplanes;planeindex < r_waterstate.numwaterplanes;planeindex++, p++)
9388         {
9389                 if(p->camera_entity != rsurface.texture->camera_entity)
9390                         continue;
9391                 d = 0;
9392                 if(!prepared)
9393                 {
9394                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9395                         prepared = true;
9396                         if(rsurface.batchnumvertices == 0)
9397                                 break;
9398                 }
9399                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9400                 {
9401                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9402                         d += fabs(PlaneDiff(vert, &p->plane));
9403                 }
9404                 if (bestd > d || bestplaneindex < 0)
9405                 {
9406                         bestd = d;
9407                         bestplaneindex = planeindex;
9408                 }
9409         }
9410         return bestplaneindex;
9411         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9412         // this situation though, as it might be better to render single larger
9413         // batches with useless stuff (backface culled for example) than to
9414         // render multiple smaller batches
9415 }
9416
9417 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9418 {
9419         int i;
9420         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9421         rsurface.passcolor4f_vertexbuffer = 0;
9422         rsurface.passcolor4f_bufferoffset = 0;
9423         for (i = 0;i < rsurface.batchnumvertices;i++)
9424                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9425 }
9426
9427 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9428 {
9429         int i;
9430         float f;
9431         const float *v;
9432         const float *c;
9433         float *c2;
9434         if (rsurface.passcolor4f)
9435         {
9436                 // generate color arrays
9437                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9438                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9439                 rsurface.passcolor4f_vertexbuffer = 0;
9440                 rsurface.passcolor4f_bufferoffset = 0;
9441                 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)
9442                 {
9443                         f = RSurf_FogVertex(v);
9444                         c2[0] = c[0] * f;
9445                         c2[1] = c[1] * f;
9446                         c2[2] = c[2] * f;
9447                         c2[3] = c[3];
9448                 }
9449         }
9450         else
9451         {
9452                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9453                 rsurface.passcolor4f_vertexbuffer = 0;
9454                 rsurface.passcolor4f_bufferoffset = 0;
9455                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9456                 {
9457                         f = RSurf_FogVertex(v);
9458                         c2[0] = f;
9459                         c2[1] = f;
9460                         c2[2] = f;
9461                         c2[3] = 1;
9462                 }
9463         }
9464 }
9465
9466 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9467 {
9468         int i;
9469         float f;
9470         const float *v;
9471         const float *c;
9472         float *c2;
9473         if (!rsurface.passcolor4f)
9474                 return;
9475         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9476         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9477         rsurface.passcolor4f_vertexbuffer = 0;
9478         rsurface.passcolor4f_bufferoffset = 0;
9479         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)
9480         {
9481                 f = RSurf_FogVertex(v);
9482                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9483                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9484                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9485                 c2[3] = c[3];
9486         }
9487 }
9488
9489 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9490 {
9491         int i;
9492         const float *c;
9493         float *c2;
9494         if (!rsurface.passcolor4f)
9495                 return;
9496         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9497         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9498         rsurface.passcolor4f_vertexbuffer = 0;
9499         rsurface.passcolor4f_bufferoffset = 0;
9500         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9501         {
9502                 c2[0] = c[0] * r;
9503                 c2[1] = c[1] * g;
9504                 c2[2] = c[2] * b;
9505                 c2[3] = c[3] * a;
9506         }
9507 }
9508
9509 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9510 {
9511         int i;
9512         const float *c;
9513         float *c2;
9514         if (!rsurface.passcolor4f)
9515                 return;
9516         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9517         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9518         rsurface.passcolor4f_vertexbuffer = 0;
9519         rsurface.passcolor4f_bufferoffset = 0;
9520         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9521         {
9522                 c2[0] = c[0] + r_refdef.scene.ambient;
9523                 c2[1] = c[1] + r_refdef.scene.ambient;
9524                 c2[2] = c[2] + r_refdef.scene.ambient;
9525                 c2[3] = c[3];
9526         }
9527 }
9528
9529 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9530 {
9531         // TODO: optimize
9532         rsurface.passcolor4f = NULL;
9533         rsurface.passcolor4f_vertexbuffer = 0;
9534         rsurface.passcolor4f_bufferoffset = 0;
9535         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9536         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9537         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9538         GL_Color(r, g, b, a);
9539         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9540         RSurf_DrawBatch();
9541 }
9542
9543 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9544 {
9545         // TODO: optimize applyfog && applycolor case
9546         // just apply fog if necessary, and tint the fog color array if necessary
9547         rsurface.passcolor4f = NULL;
9548         rsurface.passcolor4f_vertexbuffer = 0;
9549         rsurface.passcolor4f_bufferoffset = 0;
9550         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9551         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9552         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9553         GL_Color(r, g, b, a);
9554         RSurf_DrawBatch();
9555 }
9556
9557 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9558 {
9559         // TODO: optimize
9560         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9561         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9562         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9563         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9564         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9565         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9566         GL_Color(r, g, b, a);
9567         RSurf_DrawBatch();
9568 }
9569
9570 static void RSurf_DrawBatch_GL11_ClampColor(void)
9571 {
9572         int i;
9573         const float *c1;
9574         float *c2;
9575         if (!rsurface.passcolor4f)
9576                 return;
9577         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9578         {
9579                 c2[0] = bound(0.0f, c1[0], 1.0f);
9580                 c2[1] = bound(0.0f, c1[1], 1.0f);
9581                 c2[2] = bound(0.0f, c1[2], 1.0f);
9582                 c2[3] = bound(0.0f, c1[3], 1.0f);
9583         }
9584 }
9585
9586 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9587 {
9588         int i;
9589         float f;
9590         const float *v;
9591         const float *n;
9592         float *c;
9593         //vec3_t eyedir;
9594
9595         // fake shading
9596         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9597         rsurface.passcolor4f_vertexbuffer = 0;
9598         rsurface.passcolor4f_bufferoffset = 0;
9599         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)
9600         {
9601                 f = -DotProduct(r_refdef.view.forward, n);
9602                 f = max(0, f);
9603                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9604                 f *= r_refdef.lightmapintensity;
9605                 Vector4Set(c, f, f, f, 1);
9606         }
9607 }
9608
9609 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9610 {
9611         RSurf_DrawBatch_GL11_ApplyFakeLight();
9612         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9613         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9614         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9615         GL_Color(r, g, b, a);
9616         RSurf_DrawBatch();
9617 }
9618
9619 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9620 {
9621         int i;
9622         float f;
9623         float alpha;
9624         const float *v;
9625         const float *n;
9626         float *c;
9627         vec3_t ambientcolor;
9628         vec3_t diffusecolor;
9629         vec3_t lightdir;
9630         // TODO: optimize
9631         // model lighting
9632         VectorCopy(rsurface.modellight_lightdir, lightdir);
9633         f = 0.5f * r_refdef.lightmapintensity;
9634         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9635         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9636         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9637         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9638         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9639         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9640         alpha = *a;
9641         if (VectorLength2(diffusecolor) > 0)
9642         {
9643                 // q3-style directional shading
9644                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9645                 rsurface.passcolor4f_vertexbuffer = 0;
9646                 rsurface.passcolor4f_bufferoffset = 0;
9647                 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)
9648                 {
9649                         if ((f = DotProduct(n, lightdir)) > 0)
9650                                 VectorMA(ambientcolor, f, diffusecolor, c);
9651                         else
9652                                 VectorCopy(ambientcolor, c);
9653                         c[3] = alpha;
9654                 }
9655                 *r = 1;
9656                 *g = 1;
9657                 *b = 1;
9658                 *a = 1;
9659                 *applycolor = false;
9660         }
9661         else
9662         {
9663                 *r = ambientcolor[0];
9664                 *g = ambientcolor[1];
9665                 *b = ambientcolor[2];
9666                 rsurface.passcolor4f = NULL;
9667                 rsurface.passcolor4f_vertexbuffer = 0;
9668                 rsurface.passcolor4f_bufferoffset = 0;
9669         }
9670 }
9671
9672 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9673 {
9674         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9675         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9676         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9677         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9678         GL_Color(r, g, b, a);
9679         RSurf_DrawBatch();
9680 }
9681
9682 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9683 {
9684         int i;
9685         float f;
9686         const float *v;
9687         float *c;
9688
9689         // fake shading
9690         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9691         rsurface.passcolor4f_vertexbuffer = 0;
9692         rsurface.passcolor4f_bufferoffset = 0;
9693
9694         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9695         {
9696                 f = 1 - RSurf_FogVertex(v);
9697                 c[0] = r;
9698                 c[1] = g;
9699                 c[2] = b;
9700                 c[3] = f * a;
9701         }
9702 }
9703
9704 void RSurf_SetupDepthAndCulling(void)
9705 {
9706         // submodels are biased to avoid z-fighting with world surfaces that they
9707         // may be exactly overlapping (avoids z-fighting artifacts on certain
9708         // doors and things in Quake maps)
9709         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9710         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9711         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9712         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9713 }
9714
9715 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9716 {
9717         // transparent sky would be ridiculous
9718         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9719                 return;
9720         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9721         skyrenderlater = true;
9722         RSurf_SetupDepthAndCulling();
9723         GL_DepthMask(true);
9724         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9725         // skymasking on them, and Quake3 never did sky masking (unlike
9726         // software Quake and software Quake2), so disable the sky masking
9727         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9728         // and skymasking also looks very bad when noclipping outside the
9729         // level, so don't use it then either.
9730         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9731         {
9732                 R_Mesh_ResetTextureState();
9733                 if (skyrendermasked)
9734                 {
9735                         R_SetupShader_DepthOrShadow(false);
9736                         // depth-only (masking)
9737                         GL_ColorMask(0,0,0,0);
9738                         // just to make sure that braindead drivers don't draw
9739                         // anything despite that colormask...
9740                         GL_BlendFunc(GL_ZERO, GL_ONE);
9741                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9742                         if (rsurface.batchvertex3fbuffer)
9743                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9744                         else
9745                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9746                 }
9747                 else
9748                 {
9749                         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
9750                         // fog sky
9751                         GL_BlendFunc(GL_ONE, GL_ZERO);
9752                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9753                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9754                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9755                 }
9756                 RSurf_DrawBatch();
9757                 if (skyrendermasked)
9758                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9759         }
9760         R_Mesh_ResetTextureState();
9761         GL_Color(1, 1, 1, 1);
9762 }
9763
9764 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9765 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9766 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9767 {
9768         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9769                 return;
9770         if (prepass)
9771         {
9772                 // render screenspace normalmap to texture
9773                 GL_DepthMask(true);
9774                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9775                 RSurf_DrawBatch();
9776         }
9777
9778         // bind lightmap texture
9779
9780         // water/refraction/reflection/camera surfaces have to be handled specially
9781         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9782         {
9783                 int start, end, startplaneindex;
9784                 for (start = 0;start < texturenumsurfaces;start = end)
9785                 {
9786                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9787                         if(startplaneindex < 0)
9788                         {
9789                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9790                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9791                                 end = start + 1;
9792                                 continue;
9793                         }
9794                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9795                                 ;
9796                         // now that we have a batch using the same planeindex, render it
9797                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9798                         {
9799                                 // render water or distortion background
9800                                 GL_DepthMask(true);
9801                                 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);
9802                                 RSurf_DrawBatch();
9803                                 // blend surface on top
9804                                 GL_DepthMask(false);
9805                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9806                                 RSurf_DrawBatch();
9807                         }
9808                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9809                         {
9810                                 // render surface with reflection texture as input
9811                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9812                                 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);
9813                                 RSurf_DrawBatch();
9814                         }
9815                 }
9816                 return;
9817         }
9818
9819         // render surface batch normally
9820         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9821         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);
9822         RSurf_DrawBatch();
9823 }
9824
9825 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9826 {
9827         // OpenGL 1.3 path - anything not completely ancient
9828         qboolean applycolor;
9829         qboolean applyfog;
9830         int layerindex;
9831         const texturelayer_t *layer;
9832         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);
9833         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9834
9835         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9836         {
9837                 vec4_t layercolor;
9838                 int layertexrgbscale;
9839                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9840                 {
9841                         if (layerindex == 0)
9842                                 GL_AlphaTest(true);
9843                         else
9844                         {
9845                                 GL_AlphaTest(false);
9846                                 GL_DepthFunc(GL_EQUAL);
9847                         }
9848                 }
9849                 GL_DepthMask(layer->depthmask && writedepth);
9850                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9851                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9852                 {
9853                         layertexrgbscale = 4;
9854                         VectorScale(layer->color, 0.25f, layercolor);
9855                 }
9856                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9857                 {
9858                         layertexrgbscale = 2;
9859                         VectorScale(layer->color, 0.5f, layercolor);
9860                 }
9861                 else
9862                 {
9863                         layertexrgbscale = 1;
9864                         VectorScale(layer->color, 1.0f, layercolor);
9865                 }
9866                 layercolor[3] = layer->color[3];
9867                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9868                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9869                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9870                 switch (layer->type)
9871                 {
9872                 case TEXTURELAYERTYPE_LITTEXTURE:
9873                         // single-pass lightmapped texture with 2x rgbscale
9874                         R_Mesh_TexBind(0, r_texture_white);
9875                         R_Mesh_TexMatrix(0, NULL);
9876                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9877                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9878                         R_Mesh_TexBind(1, layer->texture);
9879                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9880                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9881                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9882                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9883                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9884                         else if (FAKELIGHT_ENABLED)
9885                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9886                         else if (rsurface.uselightmaptexture)
9887                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9888                         else
9889                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9890                         break;
9891                 case TEXTURELAYERTYPE_TEXTURE:
9892                         // singletexture unlit texture with transparency support
9893                         R_Mesh_TexBind(0, layer->texture);
9894                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9895                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9896                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9897                         R_Mesh_TexBind(1, 0);
9898                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9899                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9900                         break;
9901                 case TEXTURELAYERTYPE_FOG:
9902                         // singletexture fogging
9903                         if (layer->texture)
9904                         {
9905                                 R_Mesh_TexBind(0, layer->texture);
9906                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9907                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9908                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9909                         }
9910                         else
9911                         {
9912                                 R_Mesh_TexBind(0, 0);
9913                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9914                         }
9915                         R_Mesh_TexBind(1, 0);
9916                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9917                         // generate a color array for the fog pass
9918                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9919                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9920                         RSurf_DrawBatch();
9921                         break;
9922                 default:
9923                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9924                 }
9925         }
9926         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9927         {
9928                 GL_DepthFunc(GL_LEQUAL);
9929                 GL_AlphaTest(false);
9930         }
9931 }
9932
9933 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9934 {
9935         // OpenGL 1.1 - crusty old voodoo path
9936         qboolean applyfog;
9937         int layerindex;
9938         const texturelayer_t *layer;
9939         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);
9940         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9941
9942         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9943         {
9944                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9945                 {
9946                         if (layerindex == 0)
9947                                 GL_AlphaTest(true);
9948                         else
9949                         {
9950                                 GL_AlphaTest(false);
9951                                 GL_DepthFunc(GL_EQUAL);
9952                         }
9953                 }
9954                 GL_DepthMask(layer->depthmask && writedepth);
9955                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9956                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9957                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9958                 switch (layer->type)
9959                 {
9960                 case TEXTURELAYERTYPE_LITTEXTURE:
9961                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9962                         {
9963                                 // two-pass lit texture with 2x rgbscale
9964                                 // first the lightmap pass
9965                                 R_Mesh_TexBind(0, r_texture_white);
9966                                 R_Mesh_TexMatrix(0, NULL);
9967                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9968                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9969                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9970                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9971                                 else if (FAKELIGHT_ENABLED)
9972                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9973                                 else if (rsurface.uselightmaptexture)
9974                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9975                                 else
9976                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9977                                 // then apply the texture to it
9978                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9979                                 R_Mesh_TexBind(0, layer->texture);
9980                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9981                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9982                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9983                                 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);
9984                         }
9985                         else
9986                         {
9987                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9988                                 R_Mesh_TexBind(0, layer->texture);
9989                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9990                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9991                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9992                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9993                                         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);
9994                                 else
9995                                         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);
9996                         }
9997                         break;
9998                 case TEXTURELAYERTYPE_TEXTURE:
9999                         // singletexture unlit texture with transparency support
10000                         R_Mesh_TexBind(0, layer->texture);
10001                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10002                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10003                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10004                         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);
10005                         break;
10006                 case TEXTURELAYERTYPE_FOG:
10007                         // singletexture fogging
10008                         if (layer->texture)
10009                         {
10010                                 R_Mesh_TexBind(0, layer->texture);
10011                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10012                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10013                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10014                         }
10015                         else
10016                         {
10017                                 R_Mesh_TexBind(0, 0);
10018                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10019                         }
10020                         // generate a color array for the fog pass
10021                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10022                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10023                         RSurf_DrawBatch();
10024                         break;
10025                 default:
10026                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10027                 }
10028         }
10029         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10030         {
10031                 GL_DepthFunc(GL_LEQUAL);
10032                 GL_AlphaTest(false);
10033         }
10034 }
10035
10036 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10037 {
10038         int vi;
10039         int j;
10040         r_vertexgeneric_t *batchvertex;
10041         float c[4];
10042
10043 //      R_Mesh_ResetTextureState();
10044         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10045
10046         if(rsurface.texture && rsurface.texture->currentskinframe)
10047         {
10048                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10049                 c[3] *= rsurface.texture->currentalpha;
10050         }
10051         else
10052         {
10053                 c[0] = 1;
10054                 c[1] = 0;
10055                 c[2] = 1;
10056                 c[3] = 1;
10057         }
10058
10059         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10060         {
10061                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10062                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10063                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10064         }
10065
10066         // brighten it up (as texture value 127 means "unlit")
10067         c[0] *= 2 * r_refdef.view.colorscale;
10068         c[1] *= 2 * r_refdef.view.colorscale;
10069         c[2] *= 2 * r_refdef.view.colorscale;
10070
10071         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10072                 c[3] *= r_wateralpha.value;
10073
10074         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10075         {
10076                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10077                 GL_DepthMask(false);
10078         }
10079         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10080         {
10081                 GL_BlendFunc(GL_ONE, GL_ONE);
10082                 GL_DepthMask(false);
10083         }
10084         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10085         {
10086                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10087                 GL_DepthMask(false);
10088         }
10089         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10090         {
10091                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10092                 GL_DepthMask(false);
10093         }
10094         else
10095         {
10096                 GL_BlendFunc(GL_ONE, GL_ZERO);
10097                 GL_DepthMask(writedepth);
10098         }
10099
10100         if (r_showsurfaces.integer == 3)
10101         {
10102                 rsurface.passcolor4f = NULL;
10103
10104                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10105                 {
10106                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10107
10108                         rsurface.passcolor4f = NULL;
10109                         rsurface.passcolor4f_vertexbuffer = 0;
10110                         rsurface.passcolor4f_bufferoffset = 0;
10111                 }
10112                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10113                 {
10114                         qboolean applycolor = true;
10115                         float one = 1.0;
10116
10117                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10118
10119                         r_refdef.lightmapintensity = 1;
10120                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10121                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10122                 }
10123                 else if (FAKELIGHT_ENABLED)
10124                 {
10125                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10126
10127                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10128                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10129                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10130                 }
10131                 else
10132                 {
10133                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10134
10135                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10136                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10137                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10138                 }
10139
10140                 if(!rsurface.passcolor4f)
10141                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10142
10143                 RSurf_DrawBatch_GL11_ApplyAmbient();
10144                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10145                 if(r_refdef.fogenabled)
10146                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10147                 RSurf_DrawBatch_GL11_ClampColor();
10148
10149                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10150                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10151                 RSurf_DrawBatch();
10152         }
10153         else if (!r_refdef.view.showdebug)
10154         {
10155                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10156                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10157                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10158                 {
10159                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10160                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10161                 }
10162                 R_Mesh_PrepareVertices_Generic_Unlock();
10163                 RSurf_DrawBatch();
10164         }
10165         else if (r_showsurfaces.integer == 4)
10166         {
10167                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10168                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10169                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10170                 {
10171                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10172                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10173                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10174                 }
10175                 R_Mesh_PrepareVertices_Generic_Unlock();
10176                 RSurf_DrawBatch();
10177         }
10178         else if (r_showsurfaces.integer == 2)
10179         {
10180                 const int *e;
10181                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10182                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10183                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10184                 {
10185                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10186                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10187                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10188                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10189                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10190                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10191                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10192                 }
10193                 R_Mesh_PrepareVertices_Generic_Unlock();
10194                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10195         }
10196         else
10197         {
10198                 int texturesurfaceindex;
10199                 int k;
10200                 const msurface_t *surface;
10201                 float surfacecolor4f[4];
10202                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10203                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10204                 vi = 0;
10205                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10206                 {
10207                         surface = texturesurfacelist[texturesurfaceindex];
10208                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10209                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10210                         for (j = 0;j < surface->num_vertices;j++)
10211                         {
10212                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10213                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10214                                 vi++;
10215                         }
10216                 }
10217                 R_Mesh_PrepareVertices_Generic_Unlock();
10218                 RSurf_DrawBatch();
10219         }
10220 }
10221
10222 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10223 {
10224         CHECKGLERROR
10225         RSurf_SetupDepthAndCulling();
10226         if (r_showsurfaces.integer)
10227         {
10228                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10229                 return;
10230         }
10231         switch (vid.renderpath)
10232         {
10233         case RENDERPATH_GL20:
10234         case RENDERPATH_D3D9:
10235         case RENDERPATH_D3D10:
10236         case RENDERPATH_D3D11:
10237         case RENDERPATH_SOFT:
10238         case RENDERPATH_GLES2:
10239                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10240                 break;
10241         case RENDERPATH_GL13:
10242         case RENDERPATH_GLES1:
10243                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10244                 break;
10245         case RENDERPATH_GL11:
10246                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10247                 break;
10248         }
10249         CHECKGLERROR
10250 }
10251
10252 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10253 {
10254         CHECKGLERROR
10255         RSurf_SetupDepthAndCulling();
10256         if (r_showsurfaces.integer)
10257         {
10258                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10259                 return;
10260         }
10261         switch (vid.renderpath)
10262         {
10263         case RENDERPATH_GL20:
10264         case RENDERPATH_D3D9:
10265         case RENDERPATH_D3D10:
10266         case RENDERPATH_D3D11:
10267         case RENDERPATH_SOFT:
10268         case RENDERPATH_GLES2:
10269                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10270                 break;
10271         case RENDERPATH_GL13:
10272         case RENDERPATH_GLES1:
10273                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10274                 break;
10275         case RENDERPATH_GL11:
10276                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10277                 break;
10278         }
10279         CHECKGLERROR
10280 }
10281
10282 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10283 {
10284         int i, j;
10285         int texturenumsurfaces, endsurface;
10286         texture_t *texture;
10287         const msurface_t *surface;
10288         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10289
10290         // if the model is static it doesn't matter what value we give for
10291         // wantnormals and wanttangents, so this logic uses only rules applicable
10292         // to a model, knowing that they are meaningless otherwise
10293         if (ent == r_refdef.scene.worldentity)
10294                 RSurf_ActiveWorldEntity();
10295         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10296                 RSurf_ActiveModelEntity(ent, false, false, false);
10297         else
10298         {
10299                 switch (vid.renderpath)
10300                 {
10301                 case RENDERPATH_GL20:
10302                 case RENDERPATH_D3D9:
10303                 case RENDERPATH_D3D10:
10304                 case RENDERPATH_D3D11:
10305                 case RENDERPATH_SOFT:
10306                 case RENDERPATH_GLES2:
10307                         RSurf_ActiveModelEntity(ent, true, true, false);
10308                         break;
10309                 case RENDERPATH_GL11:
10310                 case RENDERPATH_GL13:
10311                 case RENDERPATH_GLES1:
10312                         RSurf_ActiveModelEntity(ent, true, false, false);
10313                         break;
10314                 }
10315         }
10316
10317         if (r_transparentdepthmasking.integer)
10318         {
10319                 qboolean setup = false;
10320                 for (i = 0;i < numsurfaces;i = j)
10321                 {
10322                         j = i + 1;
10323                         surface = rsurface.modelsurfaces + surfacelist[i];
10324                         texture = surface->texture;
10325                         rsurface.texture = R_GetCurrentTexture(texture);
10326                         rsurface.lightmaptexture = NULL;
10327                         rsurface.deluxemaptexture = NULL;
10328                         rsurface.uselightmaptexture = false;
10329                         // scan ahead until we find a different texture
10330                         endsurface = min(i + 1024, numsurfaces);
10331                         texturenumsurfaces = 0;
10332                         texturesurfacelist[texturenumsurfaces++] = surface;
10333                         for (;j < endsurface;j++)
10334                         {
10335                                 surface = rsurface.modelsurfaces + surfacelist[j];
10336                                 if (texture != surface->texture)
10337                                         break;
10338                                 texturesurfacelist[texturenumsurfaces++] = surface;
10339                         }
10340                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10341                                 continue;
10342                         // render the range of surfaces as depth
10343                         if (!setup)
10344                         {
10345                                 setup = true;
10346                                 GL_ColorMask(0,0,0,0);
10347                                 GL_Color(1,1,1,1);
10348                                 GL_DepthTest(true);
10349                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10350                                 GL_DepthMask(true);
10351 //                              R_Mesh_ResetTextureState();
10352                                 R_SetupShader_DepthOrShadow(false);
10353                         }
10354                         RSurf_SetupDepthAndCulling();
10355                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10356                         if (rsurface.batchvertex3fbuffer)
10357                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10358                         else
10359                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10360                         RSurf_DrawBatch();
10361                 }
10362                 if (setup)
10363                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10364         }
10365
10366         for (i = 0;i < numsurfaces;i = j)
10367         {
10368                 j = i + 1;
10369                 surface = rsurface.modelsurfaces + surfacelist[i];
10370                 texture = surface->texture;
10371                 rsurface.texture = R_GetCurrentTexture(texture);
10372                 // scan ahead until we find a different texture
10373                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10374                 texturenumsurfaces = 0;
10375                 texturesurfacelist[texturenumsurfaces++] = surface;
10376                 if(FAKELIGHT_ENABLED)
10377                 {
10378                         rsurface.lightmaptexture = NULL;
10379                         rsurface.deluxemaptexture = NULL;
10380                         rsurface.uselightmaptexture = false;
10381                         for (;j < endsurface;j++)
10382                         {
10383                                 surface = rsurface.modelsurfaces + surfacelist[j];
10384                                 if (texture != surface->texture)
10385                                         break;
10386                                 texturesurfacelist[texturenumsurfaces++] = surface;
10387                         }
10388                 }
10389                 else
10390                 {
10391                         rsurface.lightmaptexture = surface->lightmaptexture;
10392                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10393                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10394                         for (;j < endsurface;j++)
10395                         {
10396                                 surface = rsurface.modelsurfaces + surfacelist[j];
10397                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10398                                         break;
10399                                 texturesurfacelist[texturenumsurfaces++] = surface;
10400                         }
10401                 }
10402                 // render the range of surfaces
10403                 if (ent == r_refdef.scene.worldentity)
10404                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10405                 else
10406                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10407         }
10408         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10409 }
10410
10411 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10412 {
10413         // transparent surfaces get pushed off into the transparent queue
10414         int surfacelistindex;
10415         const msurface_t *surface;
10416         vec3_t tempcenter, center;
10417         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10418         {
10419                 surface = texturesurfacelist[surfacelistindex];
10420                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10421                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10422                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10423                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10424                 if (queueentity->transparent_offset) // transparent offset
10425                 {
10426                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10427                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10428                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10429                 }
10430                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10431         }
10432 }
10433
10434 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10435 {
10436         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10437                 return;
10438         if (r_waterstate.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10439                 return;
10440         RSurf_SetupDepthAndCulling();
10441         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10442         if (rsurface.batchvertex3fbuffer)
10443                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10444         else
10445                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10446         RSurf_DrawBatch();
10447 }
10448
10449 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10450 {
10451         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10452         CHECKGLERROR
10453         if (depthonly)
10454                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10455         else if (prepass)
10456         {
10457                 if (!rsurface.texture->currentnumlayers)
10458                         return;
10459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10460                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10461                 else
10462                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10463         }
10464         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10465                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10466         else if (!rsurface.texture->currentnumlayers)
10467                 return;
10468         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10469         {
10470                 // in the deferred case, transparent surfaces were queued during prepass
10471                 if (!r_shadow_usingdeferredprepass)
10472                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10473         }
10474         else
10475         {
10476                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10477                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10478         }
10479         CHECKGLERROR
10480 }
10481
10482 void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10483 {
10484         int i, j;
10485         texture_t *texture;
10486         R_FrameData_SetMark();
10487         // break the surface list down into batches by texture and use of lightmapping
10488         for (i = 0;i < numsurfaces;i = j)
10489         {
10490                 j = i + 1;
10491                 // texture is the base texture pointer, rsurface.texture is the
10492                 // current frame/skin the texture is directing us to use (for example
10493                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10494                 // use skin 1 instead)
10495                 texture = surfacelist[i]->texture;
10496                 rsurface.texture = R_GetCurrentTexture(texture);
10497                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10498                 {
10499                         // if this texture is not the kind we want, skip ahead to the next one
10500                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10501                                 ;
10502                         continue;
10503                 }
10504                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10505                 {
10506                         rsurface.lightmaptexture = NULL;
10507                         rsurface.deluxemaptexture = NULL;
10508                         rsurface.uselightmaptexture = false;
10509                         // simply scan ahead until we find a different texture or lightmap state
10510                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10511                                 ;
10512                 }
10513                 else
10514                 {
10515                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10516                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10517                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10518                         // simply scan ahead until we find a different texture or lightmap state
10519                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10520                                 ;
10521                 }
10522                 // render the range of surfaces
10523                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10524         }
10525         R_FrameData_ReturnToMark();
10526 }
10527
10528 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10529 {
10530         CHECKGLERROR
10531         if (depthonly)
10532                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10533         else if (prepass)
10534         {
10535                 if (!rsurface.texture->currentnumlayers)
10536                         return;
10537                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10538                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10539                 else
10540                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10541         }
10542         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10543                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10544         else if (!rsurface.texture->currentnumlayers)
10545                 return;
10546         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10547         {
10548                 // in the deferred case, transparent surfaces were queued during prepass
10549                 if (!r_shadow_usingdeferredprepass)
10550                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10551         }
10552         else
10553         {
10554                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10555                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10556         }
10557         CHECKGLERROR
10558 }
10559
10560 void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10561 {
10562         int i, j;
10563         texture_t *texture;
10564         R_FrameData_SetMark();
10565         // break the surface list down into batches by texture and use of lightmapping
10566         for (i = 0;i < numsurfaces;i = j)
10567         {
10568                 j = i + 1;
10569                 // texture is the base texture pointer, rsurface.texture is the
10570                 // current frame/skin the texture is directing us to use (for example
10571                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10572                 // use skin 1 instead)
10573                 texture = surfacelist[i]->texture;
10574                 rsurface.texture = R_GetCurrentTexture(texture);
10575                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10576                 {
10577                         // if this texture is not the kind we want, skip ahead to the next one
10578                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10579                                 ;
10580                         continue;
10581                 }
10582                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10583                 {
10584                         rsurface.lightmaptexture = NULL;
10585                         rsurface.deluxemaptexture = NULL;
10586                         rsurface.uselightmaptexture = false;
10587                         // simply scan ahead until we find a different texture or lightmap state
10588                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10589                                 ;
10590                 }
10591                 else
10592                 {
10593                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10594                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10595                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10596                         // simply scan ahead until we find a different texture or lightmap state
10597                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10598                                 ;
10599                 }
10600                 // render the range of surfaces
10601                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10602         }
10603         R_FrameData_ReturnToMark();
10604 }
10605
10606 float locboxvertex3f[6*4*3] =
10607 {
10608         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10609         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10610         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10611         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10612         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10613         1,0,0, 0,0,0, 0,1,0, 1,1,0
10614 };
10615
10616 unsigned short locboxelements[6*2*3] =
10617 {
10618          0, 1, 2, 0, 2, 3,
10619          4, 5, 6, 4, 6, 7,
10620          8, 9,10, 8,10,11,
10621         12,13,14, 12,14,15,
10622         16,17,18, 16,18,19,
10623         20,21,22, 20,22,23
10624 };
10625
10626 void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10627 {
10628         int i, j;
10629         cl_locnode_t *loc = (cl_locnode_t *)ent;
10630         vec3_t mins, size;
10631         float vertex3f[6*4*3];
10632         CHECKGLERROR
10633         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10634         GL_DepthMask(false);
10635         GL_DepthRange(0, 1);
10636         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10637         GL_DepthTest(true);
10638         GL_CullFace(GL_NONE);
10639         R_EntityMatrix(&identitymatrix);
10640
10641 //      R_Mesh_ResetTextureState();
10642
10643         i = surfacelist[0];
10644         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10645                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10646                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10647                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10648
10649         if (VectorCompare(loc->mins, loc->maxs))
10650         {
10651                 VectorSet(size, 2, 2, 2);
10652                 VectorMA(loc->mins, -0.5f, size, mins);
10653         }
10654         else
10655         {
10656                 VectorCopy(loc->mins, mins);
10657                 VectorSubtract(loc->maxs, loc->mins, size);
10658         }
10659
10660         for (i = 0;i < 6*4*3;)
10661                 for (j = 0;j < 3;j++, i++)
10662                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10663
10664         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10665         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
10666         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10667 }
10668
10669 void R_DrawLocs(void)
10670 {
10671         int index;
10672         cl_locnode_t *loc, *nearestloc;
10673         vec3_t center;
10674         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10675         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10676         {
10677                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10678                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10679         }
10680 }
10681
10682 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10683 {
10684         if (decalsystem->decals)
10685                 Mem_Free(decalsystem->decals);
10686         memset(decalsystem, 0, sizeof(*decalsystem));
10687 }
10688
10689 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)
10690 {
10691         tridecal_t *decal;
10692         tridecal_t *decals;
10693         int i;
10694
10695         // expand or initialize the system
10696         if (decalsystem->maxdecals <= decalsystem->numdecals)
10697         {
10698                 decalsystem_t old = *decalsystem;
10699                 qboolean useshortelements;
10700                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10701                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10702                 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)));
10703                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10704                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10705                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10706                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10707                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10708                 if (decalsystem->numdecals)
10709                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10710                 if (old.decals)
10711                         Mem_Free(old.decals);
10712                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10713                         decalsystem->element3i[i] = i;
10714                 if (useshortelements)
10715                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10716                                 decalsystem->element3s[i] = i;
10717         }
10718
10719         // grab a decal and search for another free slot for the next one
10720         decals = decalsystem->decals;
10721         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10722         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10723                 ;
10724         decalsystem->freedecal = i;
10725         if (decalsystem->numdecals <= i)
10726                 decalsystem->numdecals = i + 1;
10727
10728         // initialize the decal
10729         decal->lived = 0;
10730         decal->triangleindex = triangleindex;
10731         decal->surfaceindex = surfaceindex;
10732         decal->decalsequence = decalsequence;
10733         decal->color4f[0][0] = c0[0];
10734         decal->color4f[0][1] = c0[1];
10735         decal->color4f[0][2] = c0[2];
10736         decal->color4f[0][3] = 1;
10737         decal->color4f[1][0] = c1[0];
10738         decal->color4f[1][1] = c1[1];
10739         decal->color4f[1][2] = c1[2];
10740         decal->color4f[1][3] = 1;
10741         decal->color4f[2][0] = c2[0];
10742         decal->color4f[2][1] = c2[1];
10743         decal->color4f[2][2] = c2[2];
10744         decal->color4f[2][3] = 1;
10745         decal->vertex3f[0][0] = v0[0];
10746         decal->vertex3f[0][1] = v0[1];
10747         decal->vertex3f[0][2] = v0[2];
10748         decal->vertex3f[1][0] = v1[0];
10749         decal->vertex3f[1][1] = v1[1];
10750         decal->vertex3f[1][2] = v1[2];
10751         decal->vertex3f[2][0] = v2[0];
10752         decal->vertex3f[2][1] = v2[1];
10753         decal->vertex3f[2][2] = v2[2];
10754         decal->texcoord2f[0][0] = t0[0];
10755         decal->texcoord2f[0][1] = t0[1];
10756         decal->texcoord2f[1][0] = t1[0];
10757         decal->texcoord2f[1][1] = t1[1];
10758         decal->texcoord2f[2][0] = t2[0];
10759         decal->texcoord2f[2][1] = t2[1];
10760         TriangleNormal(v0, v1, v2, decal->plane);
10761         VectorNormalize(decal->plane);
10762         decal->plane[3] = DotProduct(v0, decal->plane);
10763 }
10764
10765 extern cvar_t cl_decals_bias;
10766 extern cvar_t cl_decals_models;
10767 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10768 // baseparms, parms, temps
10769 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)
10770 {
10771         int cornerindex;
10772         int index;
10773         float v[9][3];
10774         const float *vertex3f;
10775         const float *normal3f;
10776         int numpoints;
10777         float points[2][9][3];
10778         float temp[3];
10779         float tc[9][2];
10780         float f;
10781         float c[9][4];
10782         const int *e;
10783
10784         e = rsurface.modelelement3i + 3*triangleindex;
10785
10786         vertex3f = rsurface.modelvertex3f;
10787         normal3f = rsurface.modelnormal3f;
10788
10789         if (normal3f)
10790         {
10791                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10792                 {
10793                         index = 3*e[cornerindex];
10794                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10795                 }
10796         }
10797         else
10798         {
10799                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10800                 {
10801                         index = 3*e[cornerindex];
10802                         VectorCopy(vertex3f + index, v[cornerindex]);
10803                 }
10804         }
10805
10806         // cull backfaces
10807         //TriangleNormal(v[0], v[1], v[2], normal);
10808         //if (DotProduct(normal, localnormal) < 0.0f)
10809         //      continue;
10810         // clip by each of the box planes formed from the projection matrix
10811         // if anything survives, we emit the decal
10812         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]);
10813         if (numpoints < 3)
10814                 return;
10815         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]);
10816         if (numpoints < 3)
10817                 return;
10818         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]);
10819         if (numpoints < 3)
10820                 return;
10821         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]);
10822         if (numpoints < 3)
10823                 return;
10824         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]);
10825         if (numpoints < 3)
10826                 return;
10827         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]);
10828         if (numpoints < 3)
10829                 return;
10830         // some part of the triangle survived, so we have to accept it...
10831         if (dynamic)
10832         {
10833                 // dynamic always uses the original triangle
10834                 numpoints = 3;
10835                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10836                 {
10837                         index = 3*e[cornerindex];
10838                         VectorCopy(vertex3f + index, v[cornerindex]);
10839                 }
10840         }
10841         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10842         {
10843                 // convert vertex positions to texcoords
10844                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10845                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10846                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10847                 // calculate distance fade from the projection origin
10848                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10849                 f = bound(0.0f, f, 1.0f);
10850                 c[cornerindex][0] = r * f;
10851                 c[cornerindex][1] = g * f;
10852                 c[cornerindex][2] = b * f;
10853                 c[cornerindex][3] = 1.0f;
10854                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10855         }
10856         if (dynamic)
10857                 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);
10858         else
10859                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10860                         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);
10861 }
10862 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)
10863 {
10864         matrix4x4_t projection;
10865         decalsystem_t *decalsystem;
10866         qboolean dynamic;
10867         dp_model_t *model;
10868         const msurface_t *surface;
10869         const msurface_t *surfaces;
10870         const int *surfacelist;
10871         const texture_t *texture;
10872         int numtriangles;
10873         int numsurfacelist;
10874         int surfacelistindex;
10875         int surfaceindex;
10876         int triangleindex;
10877         float localorigin[3];
10878         float localnormal[3];
10879         float localmins[3];
10880         float localmaxs[3];
10881         float localsize;
10882         //float normal[3];
10883         float planes[6][4];
10884         float angles[3];
10885         bih_t *bih;
10886         int bih_triangles_count;
10887         int bih_triangles[256];
10888         int bih_surfaces[256];
10889
10890         decalsystem = &ent->decalsystem;
10891         model = ent->model;
10892         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10893         {
10894                 R_DecalSystem_Reset(&ent->decalsystem);
10895                 return;
10896         }
10897
10898         if (!model->brush.data_leafs && !cl_decals_models.integer)
10899         {
10900                 if (decalsystem->model)
10901                         R_DecalSystem_Reset(decalsystem);
10902                 return;
10903         }
10904
10905         if (decalsystem->model != model)
10906                 R_DecalSystem_Reset(decalsystem);
10907         decalsystem->model = model;
10908
10909         RSurf_ActiveModelEntity(ent, true, false, false);
10910
10911         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10912         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10913         VectorNormalize(localnormal);
10914         localsize = worldsize*rsurface.inversematrixscale;
10915         localmins[0] = localorigin[0] - localsize;
10916         localmins[1] = localorigin[1] - localsize;
10917         localmins[2] = localorigin[2] - localsize;
10918         localmaxs[0] = localorigin[0] + localsize;
10919         localmaxs[1] = localorigin[1] + localsize;
10920         localmaxs[2] = localorigin[2] + localsize;
10921
10922         //VectorCopy(localnormal, planes[4]);
10923         //VectorVectors(planes[4], planes[2], planes[0]);
10924         AnglesFromVectors(angles, localnormal, NULL, false);
10925         AngleVectors(angles, planes[0], planes[2], planes[4]);
10926         VectorNegate(planes[0], planes[1]);
10927         VectorNegate(planes[2], planes[3]);
10928         VectorNegate(planes[4], planes[5]);
10929         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10930         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10931         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10932         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10933         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10934         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10935
10936 #if 1
10937 // works
10938 {
10939         matrix4x4_t forwardprojection;
10940         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10941         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10942 }
10943 #else
10944 // broken
10945 {
10946         float projectionvector[4][3];
10947         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10948         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10949         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10950         projectionvector[0][0] = planes[0][0] * ilocalsize;
10951         projectionvector[0][1] = planes[1][0] * ilocalsize;
10952         projectionvector[0][2] = planes[2][0] * ilocalsize;
10953         projectionvector[1][0] = planes[0][1] * ilocalsize;
10954         projectionvector[1][1] = planes[1][1] * ilocalsize;
10955         projectionvector[1][2] = planes[2][1] * ilocalsize;
10956         projectionvector[2][0] = planes[0][2] * ilocalsize;
10957         projectionvector[2][1] = planes[1][2] * ilocalsize;
10958         projectionvector[2][2] = planes[2][2] * ilocalsize;
10959         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10960         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10961         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10962         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10963 }
10964 #endif
10965
10966         dynamic = model->surfmesh.isanimated;
10967         numsurfacelist = model->nummodelsurfaces;
10968         surfacelist = model->sortedmodelsurfaces;
10969         surfaces = model->data_surfaces;
10970
10971         bih = NULL;
10972         bih_triangles_count = -1;
10973         if(!dynamic)
10974         {
10975                 if(model->render_bih.numleafs)
10976                         bih = &model->render_bih;
10977                 else if(model->collision_bih.numleafs)
10978                         bih = &model->collision_bih;
10979         }
10980         if(bih)
10981                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10982         if(bih_triangles_count == 0)
10983                 return;
10984         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10985                 return;
10986         if(bih_triangles_count > 0)
10987         {
10988                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10989                 {
10990                         surfaceindex = bih_surfaces[triangleindex];
10991                         surface = surfaces + surfaceindex;
10992                         texture = surface->texture;
10993                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10994                                 continue;
10995                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10996                                 continue;
10997                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
10998                 }
10999         }
11000         else
11001         {
11002                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11003                 {
11004                         surfaceindex = surfacelist[surfacelistindex];
11005                         surface = surfaces + surfaceindex;
11006                         // check cull box first because it rejects more than any other check
11007                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11008                                 continue;
11009                         // skip transparent surfaces
11010                         texture = surface->texture;
11011                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11012                                 continue;
11013                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11014                                 continue;
11015                         numtriangles = surface->num_triangles;
11016                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11017                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11018                 }
11019         }
11020 }
11021
11022 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11023 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)
11024 {
11025         int renderentityindex;
11026         float worldmins[3];
11027         float worldmaxs[3];
11028         entity_render_t *ent;
11029
11030         if (!cl_decals_newsystem.integer)
11031                 return;
11032
11033         worldmins[0] = worldorigin[0] - worldsize;
11034         worldmins[1] = worldorigin[1] - worldsize;
11035         worldmins[2] = worldorigin[2] - worldsize;
11036         worldmaxs[0] = worldorigin[0] + worldsize;
11037         worldmaxs[1] = worldorigin[1] + worldsize;
11038         worldmaxs[2] = worldorigin[2] + worldsize;
11039
11040         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11041
11042         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11043         {
11044                 ent = r_refdef.scene.entities[renderentityindex];
11045                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11046                         continue;
11047
11048                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11049         }
11050 }
11051
11052 typedef struct r_decalsystem_splatqueue_s
11053 {
11054         vec3_t worldorigin;
11055         vec3_t worldnormal;
11056         float color[4];
11057         float tcrange[4];
11058         float worldsize;
11059         int decalsequence;
11060 }
11061 r_decalsystem_splatqueue_t;
11062
11063 int r_decalsystem_numqueued = 0;
11064 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11065
11066 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)
11067 {
11068         r_decalsystem_splatqueue_t *queue;
11069
11070         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11071                 return;
11072
11073         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11074         VectorCopy(worldorigin, queue->worldorigin);
11075         VectorCopy(worldnormal, queue->worldnormal);
11076         Vector4Set(queue->color, r, g, b, a);
11077         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11078         queue->worldsize = worldsize;
11079         queue->decalsequence = cl.decalsequence++;
11080 }
11081
11082 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11083 {
11084         int i;
11085         r_decalsystem_splatqueue_t *queue;
11086
11087         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11088                 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);
11089         r_decalsystem_numqueued = 0;
11090 }
11091
11092 extern cvar_t cl_decals_max;
11093 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11094 {
11095         int i;
11096         decalsystem_t *decalsystem = &ent->decalsystem;
11097         int numdecals;
11098         int killsequence;
11099         tridecal_t *decal;
11100         float frametime;
11101         float lifetime;
11102
11103         if (!decalsystem->numdecals)
11104                 return;
11105
11106         if (r_showsurfaces.integer)
11107                 return;
11108
11109         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11110         {
11111                 R_DecalSystem_Reset(decalsystem);
11112                 return;
11113         }
11114
11115         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11116         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11117
11118         if (decalsystem->lastupdatetime)
11119                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11120         else
11121                 frametime = 0;
11122         decalsystem->lastupdatetime = r_refdef.scene.time;
11123         decal = decalsystem->decals;
11124         numdecals = decalsystem->numdecals;
11125
11126         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11127         {
11128                 if (decal->color4f[0][3])
11129                 {
11130                         decal->lived += frametime;
11131                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11132                         {
11133                                 memset(decal, 0, sizeof(*decal));
11134                                 if (decalsystem->freedecal > i)
11135                                         decalsystem->freedecal = i;
11136                         }
11137                 }
11138         }
11139         decal = decalsystem->decals;
11140         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11141                 numdecals--;
11142
11143         // collapse the array by shuffling the tail decals into the gaps
11144         for (;;)
11145         {
11146                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11147                         decalsystem->freedecal++;
11148                 if (decalsystem->freedecal == numdecals)
11149                         break;
11150                 decal[decalsystem->freedecal] = decal[--numdecals];
11151         }
11152
11153         decalsystem->numdecals = numdecals;
11154
11155         if (numdecals <= 0)
11156         {
11157                 // if there are no decals left, reset decalsystem
11158                 R_DecalSystem_Reset(decalsystem);
11159         }
11160 }
11161
11162 extern skinframe_t *decalskinframe;
11163 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11164 {
11165         int i;
11166         decalsystem_t *decalsystem = &ent->decalsystem;
11167         int numdecals;
11168         tridecal_t *decal;
11169         float faderate;
11170         float alpha;
11171         float *v3f;
11172         float *c4f;
11173         float *t2f;
11174         const int *e;
11175         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11176         int numtris = 0;
11177
11178         numdecals = decalsystem->numdecals;
11179         if (!numdecals)
11180                 return;
11181
11182         if (r_showsurfaces.integer)
11183                 return;
11184
11185         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11186         {
11187                 R_DecalSystem_Reset(decalsystem);
11188                 return;
11189         }
11190
11191         // if the model is static it doesn't matter what value we give for
11192         // wantnormals and wanttangents, so this logic uses only rules applicable
11193         // to a model, knowing that they are meaningless otherwise
11194         if (ent == r_refdef.scene.worldentity)
11195                 RSurf_ActiveWorldEntity();
11196         else
11197                 RSurf_ActiveModelEntity(ent, false, false, false);
11198
11199         decalsystem->lastupdatetime = r_refdef.scene.time;
11200         decal = decalsystem->decals;
11201
11202         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11203
11204         // update vertex positions for animated models
11205         v3f = decalsystem->vertex3f;
11206         c4f = decalsystem->color4f;
11207         t2f = decalsystem->texcoord2f;
11208         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11209         {
11210                 if (!decal->color4f[0][3])
11211                         continue;
11212
11213                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11214                         continue;
11215
11216                 // skip backfaces
11217                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11218                         continue;
11219
11220                 // update color values for fading decals
11221                 if (decal->lived >= cl_decals_time.value)
11222                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11223                 else
11224                         alpha = 1.0f;
11225
11226                 c4f[ 0] = decal->color4f[0][0] * alpha;
11227                 c4f[ 1] = decal->color4f[0][1] * alpha;
11228                 c4f[ 2] = decal->color4f[0][2] * alpha;
11229                 c4f[ 3] = 1;
11230                 c4f[ 4] = decal->color4f[1][0] * alpha;
11231                 c4f[ 5] = decal->color4f[1][1] * alpha;
11232                 c4f[ 6] = decal->color4f[1][2] * alpha;
11233                 c4f[ 7] = 1;
11234                 c4f[ 8] = decal->color4f[2][0] * alpha;
11235                 c4f[ 9] = decal->color4f[2][1] * alpha;
11236                 c4f[10] = decal->color4f[2][2] * alpha;
11237                 c4f[11] = 1;
11238
11239                 t2f[0] = decal->texcoord2f[0][0];
11240                 t2f[1] = decal->texcoord2f[0][1];
11241                 t2f[2] = decal->texcoord2f[1][0];
11242                 t2f[3] = decal->texcoord2f[1][1];
11243                 t2f[4] = decal->texcoord2f[2][0];
11244                 t2f[5] = decal->texcoord2f[2][1];
11245
11246                 // update vertex positions for animated models
11247                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11248                 {
11249                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11250                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11251                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11252                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11253                 }
11254                 else
11255                 {
11256                         VectorCopy(decal->vertex3f[0], v3f);
11257                         VectorCopy(decal->vertex3f[1], v3f + 3);
11258                         VectorCopy(decal->vertex3f[2], v3f + 6);
11259                 }
11260
11261                 if (r_refdef.fogenabled)
11262                 {
11263                         alpha = RSurf_FogVertex(v3f);
11264                         VectorScale(c4f, alpha, c4f);
11265                         alpha = RSurf_FogVertex(v3f + 3);
11266                         VectorScale(c4f + 4, alpha, c4f + 4);
11267                         alpha = RSurf_FogVertex(v3f + 6);
11268                         VectorScale(c4f + 8, alpha, c4f + 8);
11269                 }
11270
11271                 v3f += 9;
11272                 c4f += 12;
11273                 t2f += 6;
11274                 numtris++;
11275         }
11276
11277         if (numtris > 0)
11278         {
11279                 r_refdef.stats.drawndecals += numtris;
11280
11281                 // now render the decals all at once
11282                 // (this assumes they all use one particle font texture!)
11283                 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);
11284 //              R_Mesh_ResetTextureState();
11285                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11286                 GL_DepthMask(false);
11287                 GL_DepthRange(0, 1);
11288                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11289                 GL_DepthTest(true);
11290                 GL_CullFace(GL_NONE);
11291                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11292                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false);
11293                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11294         }
11295 }
11296
11297 static void R_DrawModelDecals(void)
11298 {
11299         int i, numdecals;
11300
11301         // fade faster when there are too many decals
11302         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11303         for (i = 0;i < r_refdef.scene.numentities;i++)
11304                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11305
11306         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11307         for (i = 0;i < r_refdef.scene.numentities;i++)
11308                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11309                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11310
11311         R_DecalSystem_ApplySplatEntitiesQueue();
11312
11313         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11314         for (i = 0;i < r_refdef.scene.numentities;i++)
11315                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11316
11317         r_refdef.stats.totaldecals += numdecals;
11318
11319         if (r_showsurfaces.integer)
11320                 return;
11321
11322         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11323
11324         for (i = 0;i < r_refdef.scene.numentities;i++)
11325         {
11326                 if (!r_refdef.viewcache.entityvisible[i])
11327                         continue;
11328                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11329                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11330         }
11331 }
11332
11333 extern cvar_t mod_collision_bih;
11334 void R_DrawDebugModel(void)
11335 {
11336         entity_render_t *ent = rsurface.entity;
11337         int i, j, k, l, flagsmask;
11338         const msurface_t *surface;
11339         dp_model_t *model = ent->model;
11340         vec3_t v;
11341
11342         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11343                 return;
11344
11345         if (r_showoverdraw.value > 0)
11346         {
11347                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11348                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11349                 R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11350                 GL_DepthTest(false);
11351                 GL_DepthMask(false);
11352                 GL_DepthRange(0, 1);
11353                 GL_BlendFunc(GL_ONE, GL_ONE);
11354                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11355                 {
11356                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11357                                 continue;
11358                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11359                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11360                         {
11361                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11362                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11363                                 if (!rsurface.texture->currentlayers->depthmask)
11364                                         GL_Color(c, 0, 0, 1.0f);
11365                                 else if (ent == r_refdef.scene.worldentity)
11366                                         GL_Color(c, c, c, 1.0f);
11367                                 else
11368                                         GL_Color(0, c, 0, 1.0f);
11369                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11370                                 RSurf_DrawBatch();
11371                         }
11372                 }
11373                 rsurface.texture = NULL;
11374         }
11375
11376         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11377
11378 //      R_Mesh_ResetTextureState();
11379         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, false, false);
11380         GL_DepthRange(0, 1);
11381         GL_DepthTest(!r_showdisabledepthtest.integer);
11382         GL_DepthMask(false);
11383         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11384
11385         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11386         {
11387                 int triangleindex;
11388                 int bihleafindex;
11389                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11390                 const q3mbrush_t *brush;
11391                 const bih_t *bih = &model->collision_bih;
11392                 const bih_leaf_t *bihleaf;
11393                 float vertex3f[3][3];
11394                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11395                 cullbox = false;
11396                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11397                 {
11398                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11399                                 continue;
11400                         switch (bihleaf->type)
11401                         {
11402                         case BIH_BRUSH:
11403                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11404                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11405                                 {
11406                                         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);
11407                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11408                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11409                                 }
11410                                 break;
11411                         case BIH_COLLISIONTRIANGLE:
11412                                 triangleindex = bihleaf->itemindex;
11413                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11414                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11415                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11416                                 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);
11417                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11418                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11419                                 break;
11420                         case BIH_RENDERTRIANGLE:
11421                                 triangleindex = bihleaf->itemindex;
11422                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11423                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11424                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11425                                 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);
11426                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11427                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11428                                 break;
11429                         }
11430                 }
11431         }
11432
11433         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11434
11435 #ifndef USE_GLES2
11436         if (r_showtris.integer && qglPolygonMode)
11437         {
11438                 if (r_showdisabledepthtest.integer)
11439                 {
11440                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11441                         GL_DepthMask(false);
11442                 }
11443                 else
11444                 {
11445                         GL_BlendFunc(GL_ONE, GL_ZERO);
11446                         GL_DepthMask(true);
11447                 }
11448                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11449                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11450                 {
11451                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11452                                 continue;
11453                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11454                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11455                         {
11456                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11457                                 if (!rsurface.texture->currentlayers->depthmask)
11458                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11459                                 else if (ent == r_refdef.scene.worldentity)
11460                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11461                                 else
11462                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11463                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11464                                 RSurf_DrawBatch();
11465                         }
11466                 }
11467                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11468                 rsurface.texture = NULL;
11469         }
11470
11471         if (r_shownormals.value != 0 && qglBegin)
11472         {
11473                 if (r_showdisabledepthtest.integer)
11474                 {
11475                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11476                         GL_DepthMask(false);
11477                 }
11478                 else
11479                 {
11480                         GL_BlendFunc(GL_ONE, GL_ZERO);
11481                         GL_DepthMask(true);
11482                 }
11483                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11484                 {
11485                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11486                                 continue;
11487                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11488                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11489                         {
11490                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11491                                 qglBegin(GL_LINES);
11492                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11493                                 {
11494                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11495                                         {
11496                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11497                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11498                                                 qglVertex3f(v[0], v[1], v[2]);
11499                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11500                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11501                                                 qglVertex3f(v[0], v[1], v[2]);
11502                                         }
11503                                 }
11504                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11505                                 {
11506                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11507                                         {
11508                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11509                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11510                                                 qglVertex3f(v[0], v[1], v[2]);
11511                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11512                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11513                                                 qglVertex3f(v[0], v[1], v[2]);
11514                                         }
11515                                 }
11516                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11517                                 {
11518                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11519                                         {
11520                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11521                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11522                                                 qglVertex3f(v[0], v[1], v[2]);
11523                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11524                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11525                                                 qglVertex3f(v[0], v[1], v[2]);
11526                                         }
11527                                 }
11528                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11529                                 {
11530                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11531                                         {
11532                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11533                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11534                                                 qglVertex3f(v[0], v[1], v[2]);
11535                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11536                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11537                                                 qglVertex3f(v[0], v[1], v[2]);
11538                                         }
11539                                 }
11540                                 qglEnd();
11541                                 CHECKGLERROR
11542                         }
11543                 }
11544                 rsurface.texture = NULL;
11545         }
11546 #endif
11547 }
11548
11549 extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
11550 int r_maxsurfacelist = 0;
11551 const msurface_t **r_surfacelist = NULL;
11552 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11553 {
11554         int i, j, endj, flagsmask;
11555         dp_model_t *model = r_refdef.scene.worldmodel;
11556         msurface_t *surfaces;
11557         unsigned char *update;
11558         int numsurfacelist = 0;
11559         if (model == NULL)
11560                 return;
11561
11562         if (r_maxsurfacelist < model->num_surfaces)
11563         {
11564                 r_maxsurfacelist = model->num_surfaces;
11565                 if (r_surfacelist)
11566                         Mem_Free((msurface_t**)r_surfacelist);
11567                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11568         }
11569
11570         RSurf_ActiveWorldEntity();
11571
11572         surfaces = model->data_surfaces;
11573         update = model->brushq1.lightmapupdateflags;
11574
11575         // update light styles on this submodel
11576         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11577         {
11578                 model_brush_lightstyleinfo_t *style;
11579                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11580                 {
11581                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11582                         {
11583                                 int *list = style->surfacelist;
11584                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11585                                 for (j = 0;j < style->numsurfaces;j++)
11586                                         update[list[j]] = true;
11587                         }
11588                 }
11589         }
11590
11591         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11592
11593         if (debug)
11594         {
11595                 R_DrawDebugModel();
11596                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11597                 return;
11598         }
11599
11600         rsurface.lightmaptexture = NULL;
11601         rsurface.deluxemaptexture = NULL;
11602         rsurface.uselightmaptexture = false;
11603         rsurface.texture = NULL;
11604         rsurface.rtlight = NULL;
11605         numsurfacelist = 0;
11606         // add visible surfaces to draw list
11607         for (i = 0;i < model->nummodelsurfaces;i++)
11608         {
11609                 j = model->sortedmodelsurfaces[i];
11610                 if (r_refdef.viewcache.world_surfacevisible[j])
11611                         r_surfacelist[numsurfacelist++] = surfaces + j;
11612         }
11613         // update lightmaps if needed
11614         if (model->brushq1.firstrender)
11615         {
11616                 model->brushq1.firstrender = false;
11617                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11618                         if (update[j])
11619                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11620         }
11621         else if (update)
11622         {
11623                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11624                         if (r_refdef.viewcache.world_surfacevisible[j])
11625                                 if (update[j])
11626                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11627         }
11628         // don't do anything if there were no surfaces
11629         if (!numsurfacelist)
11630         {
11631                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11632                 return;
11633         }
11634         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11635
11636         // add to stats if desired
11637         if (r_speeds.integer && !skysurfaces && !depthonly)
11638         {
11639                 r_refdef.stats.world_surfaces += numsurfacelist;
11640                 for (j = 0;j < numsurfacelist;j++)
11641                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11642         }
11643
11644         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11645 }
11646
11647 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11648 {
11649         int i, j, endj, flagsmask;
11650         dp_model_t *model = ent->model;
11651         msurface_t *surfaces;
11652         unsigned char *update;
11653         int numsurfacelist = 0;
11654         if (model == NULL)
11655                 return;
11656
11657         if (r_maxsurfacelist < model->num_surfaces)
11658         {
11659                 r_maxsurfacelist = model->num_surfaces;
11660                 if (r_surfacelist)
11661                         Mem_Free((msurface_t **)r_surfacelist);
11662                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11663         }
11664
11665         // if the model is static it doesn't matter what value we give for
11666         // wantnormals and wanttangents, so this logic uses only rules applicable
11667         // to a model, knowing that they are meaningless otherwise
11668         if (ent == r_refdef.scene.worldentity)
11669                 RSurf_ActiveWorldEntity();
11670         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11671                 RSurf_ActiveModelEntity(ent, false, false, false);
11672         else if (prepass)
11673                 RSurf_ActiveModelEntity(ent, true, true, true);
11674         else if (depthonly)
11675         {
11676                 switch (vid.renderpath)
11677                 {
11678                 case RENDERPATH_GL20:
11679                 case RENDERPATH_D3D9:
11680                 case RENDERPATH_D3D10:
11681                 case RENDERPATH_D3D11:
11682                 case RENDERPATH_SOFT:
11683                 case RENDERPATH_GLES2:
11684                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11685                         break;
11686                 case RENDERPATH_GL11:
11687                 case RENDERPATH_GL13:
11688                 case RENDERPATH_GLES1:
11689                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11690                         break;
11691                 }
11692         }
11693         else
11694         {
11695                 switch (vid.renderpath)
11696                 {
11697                 case RENDERPATH_GL20:
11698                 case RENDERPATH_D3D9:
11699                 case RENDERPATH_D3D10:
11700                 case RENDERPATH_D3D11:
11701                 case RENDERPATH_SOFT:
11702                 case RENDERPATH_GLES2:
11703                         RSurf_ActiveModelEntity(ent, true, true, false);
11704                         break;
11705                 case RENDERPATH_GL11:
11706                 case RENDERPATH_GL13:
11707                 case RENDERPATH_GLES1:
11708                         RSurf_ActiveModelEntity(ent, true, false, false);
11709                         break;
11710                 }
11711         }
11712
11713         surfaces = model->data_surfaces;
11714         update = model->brushq1.lightmapupdateflags;
11715
11716         // update light styles
11717         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11718         {
11719                 model_brush_lightstyleinfo_t *style;
11720                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11721                 {
11722                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11723                         {
11724                                 int *list = style->surfacelist;
11725                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11726                                 for (j = 0;j < style->numsurfaces;j++)
11727                                         update[list[j]] = true;
11728                         }
11729                 }
11730         }
11731
11732         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11733
11734         if (debug)
11735         {
11736                 R_DrawDebugModel();
11737                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11738                 return;
11739         }
11740
11741         rsurface.lightmaptexture = NULL;
11742         rsurface.deluxemaptexture = NULL;
11743         rsurface.uselightmaptexture = false;
11744         rsurface.texture = NULL;
11745         rsurface.rtlight = NULL;
11746         numsurfacelist = 0;
11747         // add visible surfaces to draw list
11748         for (i = 0;i < model->nummodelsurfaces;i++)
11749                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11750         // don't do anything if there were no surfaces
11751         if (!numsurfacelist)
11752         {
11753                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11754                 return;
11755         }
11756         // update lightmaps if needed
11757         if (update)
11758         {
11759                 int updated = 0;
11760                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11761                 {
11762                         if (update[j])
11763                         {
11764                                 updated++;
11765                                 R_BuildLightMap(ent, surfaces + j);
11766                         }
11767                 }
11768         }
11769         if (update)
11770                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11771                         if (update[j])
11772                                 R_BuildLightMap(ent, surfaces + j);
11773         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11774
11775         // add to stats if desired
11776         if (r_speeds.integer && !skysurfaces && !depthonly)
11777         {
11778                 r_refdef.stats.entities_surfaces += numsurfacelist;
11779                 for (j = 0;j < numsurfacelist;j++)
11780                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11781         }
11782
11783         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11784 }
11785
11786 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11787 {
11788         static texture_t texture;
11789         static msurface_t surface;
11790         const msurface_t *surfacelist = &surface;
11791
11792         // fake enough texture and surface state to render this geometry
11793
11794         texture.update_lastrenderframe = -1; // regenerate this texture
11795         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11796         texture.currentskinframe = skinframe;
11797         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11798         texture.offsetmapping = OFFSETMAPPING_OFF;
11799         texture.offsetscale = 1;
11800         texture.specularscalemod = 1;
11801         texture.specularpowermod = 1;
11802
11803         surface.texture = &texture;
11804         surface.num_triangles = numtriangles;
11805         surface.num_firsttriangle = firsttriangle;
11806         surface.num_vertices = numvertices;
11807         surface.num_firstvertex = firstvertex;
11808
11809         // now render it
11810         rsurface.texture = R_GetCurrentTexture(surface.texture);
11811         rsurface.lightmaptexture = NULL;
11812         rsurface.deluxemaptexture = NULL;
11813         rsurface.uselightmaptexture = false;
11814         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11815 }
11816
11817 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)
11818 {
11819         static msurface_t surface;
11820         const msurface_t *surfacelist = &surface;
11821
11822         // fake enough texture and surface state to render this geometry
11823         surface.texture = texture;
11824         surface.num_triangles = numtriangles;
11825         surface.num_firsttriangle = firsttriangle;
11826         surface.num_vertices = numvertices;
11827         surface.num_firstvertex = firstvertex;
11828
11829         // now render it
11830         rsurface.texture = R_GetCurrentTexture(surface.texture);
11831         rsurface.lightmaptexture = NULL;
11832         rsurface.deluxemaptexture = NULL;
11833         rsurface.uselightmaptexture = false;
11834         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11835 }